Create mobile site layouts with CSS Media Queries

Web sites and apps need to deal with the challenge of serving content to a multitude of browsers and devices. People access web sites and apps via tablets and mobile phones more than ever before, and smart phone usage numbers are growing exponentially. In some populations, mobile Web traffic is higher than traffic from desktops. Technology nowadays means devices and machines range in size from quite small to quite big, and as a result, you the developer must format the content appropriately for each device type. You can accomplish this task by using CSS Media Queries, as they are the best foundation of a responsive UI.

What is a CSS Media Query?

In the past, in order to serve browser or device specific content, we would write code that determines which style sheet to use based on feature detection (or UA detection on older Web sites). Now, instead of having to write code, we can use declarative CSS Media Queries to apply rules to an HTML page based on the requesting device’s characteristics. CSS Media Queries are a way to apply different styles when the requesting browser or device matches the conditions within the media query. With media queries you can target various screen sizes, orientations, and form factors including TV and print, and serve tailored content to them. For example, the media queries below apply a different layout to the tablet sized, landscape screen (768 x 1366 ), vs. the phone sized, portrait screen (320 x 480):

@media screen and (min-width: 768px) and (orientation: landscape)

{
    /* CSS layout for screens with minimum 800px width, landscape */

} @media screen and (max-width: 320px) and (orientation: portrait)

{
    /* CSS layout for screens with maximum 320px width, portrait */
}

While multiple media queries can exist side by side in a single .css file (like the example above), maintenance can be easier if you create one .css file for each type of device you want to support. Doing so allows you to swap style sheets based on the media query defined in the media attribute of the <link> tag.

<link rel=”stylesheet” type=”text/css” href=”smartphones.css” media=”only screen and (max-device-width: 320px)” /> <link rel=”stylesheet” type=”text/css” href=”tablets.css” media

="screen and (min-device-width: 800px)" />

Effectively, media queries rid you of the long lines of “if then” statements otherwise required as conditional logic to figure which style sheet to use for which occasion. You no longer need to resort to using JavaScript to swap style sheets by querying user agents, media types or common device form factors.

Design a page layout with CSS Media Queries

Layouts that fit traditional landscape screens work horribly on smart phones, and thus the need for a responsive layout. A responsive layout is fluid and adaptable, and needs flexible elements such as grids and images that can automatically resize based on the form factor of the requesting device. In addition to resizing elements, you must adapt the page to remove content or unnecessary navigation, because space is at such a premium on small devices.

CSS Media Queries are the foundation of responsive layouts that work across devices. Let’s start with an example of a simple web page with a two column layout in which there is a container <div> and two child <div> tags that render the columns. This layout is for desktop browsers, and later we’ll modify it to run on a phone.

#wrapper 

{ margin:0 auto; height:768px; } #sidebar { background-color:#2885c9; width:24%; height:600px; float:left; } #content { background-color:#229731; width:75%; height:600px; float:right

;
}

<!DOCTYPE html> <html xmlns=”http://www.w3.org/1999/xhtml”&gt; <head> <title>CSS Media Queries</title> <link href=”default.css” rel=”stylesheet” /> </head> <body> <div id=”wrapper”> <div id=”sidebar”><span>Side bar</span></div> <div id=”content”><span>Content goes here.</span></div> </div> </body> </html>

The code above looks like this in IE 10, a desktop browser. There is a column to the left (side bar) and one on the right (content).

 

image_thumb3_2

Of course, this layout just won’t work in a small, portrait, screen. Most side bars are for navigation, that when mobilized is painful to use in such a small form. Repositioning the elements so that the side bar is on top of the content is a much better layout for smart phones, because of the change in orientation. We can do this by creating a media query and modifying the CSS to fit smart phone dimensions. Below is a media query definition containing the same three selectors in the previous sample, but modified for a smart phone layout. What was the leftmost column (the side bar) is now positioned at row #1, and its adjacent content area is now positioned at row #2. As you might expect, the sizes of the elements are smaller than in the desktop version.

@media screen and (max-width: 320px) and (orientation: portrait) { #wrapper { width:320px; height:480px; margin: 0 0 0 5px; } #sidebar { width:320px; height:90px; float:left; margin: 0 0 5px 0; } #content { width:320px; height:380px; float:left

;
    }
}

 

image_thumb2_2SNAGHTML103a6a17_thumb1_2

The media query works great in IE10 desktop when resized to smart phone dimensions (left side, above image). However, in some phones or emulators, the above media query does not work (right side, above image). This is because we are missing a key component in mobilizing content – the <viewport> meta.

Mobilizing sites with the viewport meta

When mobile devices receive content formatted for the desktop or larger sized browsers, their default action is to zoom out to show all the content. The phone browser tries to show the page as a desktop browser does but condensed into its tiny, portrait, view. They do this for backward compatibility of the many non-mobilized sites that phones otherwise render incorrectly and break. We can change this behavior and tell phones to optimize their default zoom for mobile by using the viewport meta element. The viewport meta instructs mobile devices to resize the content to fit on their screen or to a certain scale based on the tag’s attribute values. Below is an all-purpose viewport that resizes content to fit the device:

<meta name=“viewport” content=“width=device-width”/>

If you aren’t sure what attributes to use, use the above as the default, as it renders the page to fit the device. Now because the phone will render the content correctly, and the output looks like the following:

SNAGHTML9843bc_thumb1_thumb

Notice the browser has applied the media query this time. This is because the phone’s browser took a cue from the viewport and rendered the page like a mobile browser rather than a desktop browser.

Summary

As you can see, CSS Media Queries are the best way to deliver perfectly fitted content to any device, with less maintenance hassles. Media queries aren’t just for the Web either – you can write Windows Store apps in HTML/CSS/JavaScript and use media queries for Windows 8 features like Snap-View. If you are working cross platform, don’t worry about support as CSS Media Queries have a wide adoption across desktop and mobile browsers.

Lastly, if you would like to go mobile but must support the older-than-dirt browsers like IE8 and below then check out Respond.js. Respond is a polyfill for CSS Media Queries (a mechanism for backwards compatibility), enabling their use in old or unpopular browsers.

Use Windows Azure Mobile Services to power Windows Store and Windows Phone apps

New to the Azure family, Windows Azure Mobile Services is that all-in-one place for everything backend – data storage, authentication, push notifications, jobs. WAMs provides the tools to build and target cross platform apps for the Windows Store, Windows Phone, iOS, Android, and even plain old web sites.

Why Azure Mobile Services?

Here’s what you get upon creating your WAMS service:

  • Underlying SQL database, but you can also do NoSQL (BLOB storage, etc..)
  • A REST API, along with managed and JavaScript client libraries.
  • Administration via the Azure portal, command line, or SQL Management Studio
  • Server side logic via JavaScript or SQL
  • Push notifications

and…

A bunch of big-name authentication providers:

  • Microsoft acct (aka Windows Live)
  • Twitter
  • Facebook
  • Google acct

WAMS contains basically everything necessary to power an app or web site quickly. It doesn’t matter what you’re developing on the front end, it’s great to have a single point for all things backend.

Connect to Azure Mobile services

Once you have installed the Azure Mobile Services SDK for Visual Studio and setup and configured your mobile service at the Windows Azure Portal, you can download complete project templates or just blocks of the required code to connect and access WAMS on any platform. This is the same portal for all of Azure’s other services. 

Find your URL and key in the Azure portal by selecting the cloud icon next to the Dashboard option (see image below). This page allows you to choose your platform and download complete Visual Studio 2012 projects for Windows Store or Windows Phone in the language of your choice. There are also templates for iOS and Android available at the Azure portal. If you are integrating WAMS into an existing project there are code snippets for the MobileServicesClient (more on this below) you can copy and paste. The below image shows the key highlights:

 image_6

  1. Quick Start menu option.
  2. Choose your poison.
  3. Get the code.

The downloadable projects from the Azure portal contain the appropriate client lib references and code to connect to WAMS, depending on the language. For C#/VB you need a reference to the “Windows Azure Mobile Services Managed Client” extension. For JavaScript, reference the “Windows Azure Mobile Services Javascript Client” extension, as well as a script reference to MobileServices.js in the default.html file. Both dependencies ship with the Azure Mobile Services SDK.

In WAMS projects, you must create an instance of a MobileServiceClient that acts as a proxy to the Azure service, somewhat like a connection that manages itself.

C#

public static MobileServiceClient MobileService = new MobileServiceClient(
    "https://your-site.azure-mobile.net/", "your-key-here"
);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

and Javascript

var client = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient(
    "https://your-site.azure-mobile.net/", "your-key-here"
);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Your site URL and key, both MobileServiceClient constructor arguments are available at the Quick Start page (above image) in the Azure portal. Now that you have a proxy to a mobile service, you can perform all CRUD operations as well as some DDL code locally on the client by populating a IMobileServiceTable<T> with a call to MobileService.GetTable.  Once you do that you can then perform data binding and other CRUD operations.

Work with data in Windows Azure Mobile Services

In C#  you must use a class to represent the data item, while in JavaScript you do not. For example, the below code shows populating & data binding to TextBox inside a XAML ListView control.

<ListView Name="ListItems" Margin="62,10,0,0" Grid.Row="1">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBox Name="NameTextBox" Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The C# code, below.

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Birthday { get; set; }
}

private IMobileServiceTable<Person> peopleTable = App.MobileService.GetTable<Person>();
private void RefreshTodoItems()
{
    var results = await peopleTable.ToListAsync();
    persons = new ObservableCollection<Person>(results);
    ListItems.ItemsSource = persons;
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Additions and updates (but not deletions) to properties of the Person class in client code affect the underlying SQL database. This means that if you add another property to the Person class, such as a FavoriteColor property, the WAMS libraries will automatically infer the type and create the underlying SQL entities. Of course not everything can be done in client code so there are server side alternatives (see below, under Manage WAMS Data Stores)

Below is the equivalent code in Javascript, starting with HTML for data binding.

<div id="TemplateItem" data-win-control="WinJS.Binding.Template">
    <div style="display: -ms-grid; -ms-grid-columns: auto 1fr">
        <input class="itemCheckbox" type="checkbox" data-win-bind="checked: complete; dataContext: this" />
        <input type="text" data-win-bind="text: Name" />
    </div>
</div>
<div id="listControl" style="-ms-grid-row: 2; margin: 20px 0px 0px 0px; -ms-grid-row-align: stretch"
    data-win-control="WinJS.UI.ListView"
    data-win-options="{ itemTemplate: TemplateItem, layout: {type: WinJS.UI.ListLayout} }">
</div>
var peopleTable = client.getTable('People');
var peopleList = new WinJS.Binding.List();
var refreshData = function () {
    peopleTable.read()
        .done(function (results) {
            peopleList = new WinJS.Binding.List(results);
            listControl.winControl.itemDataSource = peopleList.dataSource;
        });
};

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see, you do not need to setup a class since Javascript is not strongly typed but WAMS will still create objects and SQL mappings as needed. However, you can use something like TypeScript to create classes to be more like classes in C#. Either way, once you have a reference to the MobileServiceTable, all required functionality is accessible through that object. For example, insertions are just a simple call from the MobileServiceTable object:

C#

private async void InsertTodoItem(Person person)
{
    await peopleTable.InsertAsync(person);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Javascript

var insertPerson = function (person) {
    peopleTable.insert(person).done(function (item) {
        peopleList.push(person);  // push items onto List object for binding
    });
};

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The other CRUD methods are just as easy and also belong to the MobileServiceTable object. Notice that C# uses the await/async keywords and JS uses the done function to implement asynchronous operations (async is 1st class citizenry in Windows Store & Phone apps).

While the Javascript code will not run on Windows Phone, the C# code does and is easily ported between Windows Store and Windows Phone. You can download templates at the Azure portal specifically for Windows Phone (iOS and Android too).

Of course you need to also manage the data on the backend, regardless of the type or number of front end clients.

Manage WAMS data stores

While there are benefits to automatic creation, mapping, and type inference between client objects and WAMS databases, you can perform any sufficiently advanced db management using Javascript on the server such asvalidation, constraints, etc…. Here’s an example of server side validation in WAMS:

function insert(item, user, request) {
    if (item.text.length > 10) {
        request.respond(statusCodes.BAD_REQUEST, 'Text length must be under 10');
    } else {
        request.execute();
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This is straight-up Javascript. You can run it at the portal or upload the .js files directly to WAMS by using the WAMS command line tools:

azure mobile script upload <service-name> table/<table-name>.<operation>.js

azure mobile script upload NotablePeople people/people.insert.js

This makes it easy to incorporate scripts into source control, and using Javascript on the backend makes it easy to develop cross platform solutions.  

Summary

WAMS is a backend to everything, and is for the most part a turn-key operation, and using WAMS is really as simple as setting up the WAMS service, referencing the proper Visual Studio client libs, and coding against a small and clear set of APIs. Despite all this goodness, WAMS is still a young technology so it does need some polish. I’d like to see server side JS debugging and more SQLesque type utilities, as well as additional data types like binary/BLOB support (which I am told is coming soon, yay!).