Membrane SoftwareTechnology development studio
Tips for a responsive website
Wednesday, April 19 2017 15:14 GMT
Posted by: MembraneTags:programmingwebsites
As webmasters of the Membrane Software site, it's our duty to deliver so-called "responsive" content: a page arranged in the best way possible for each user's individual device. These days, we can expect more than half of our web requests to come not from old-fashioned desktop PCs, but rather from new-fangled mobile devices. On these devices, we aim to load the page at a text size large enough to be immediately readable, and with a layout that makes most effective use of limited screen space without requiring the user to zoom. But there are still a lot of those desktops out there and our site needs to look good on them, not to mention larger mobile devices like tablets. How do we program a system to appropriately present a single set of content for such a wide range of screen sizes? Today, we'll explore ways to fulfill this unquestionably essential need for our modern web.
The mobile browser
Palm VII in dock
Just flip the antenna and the device signs onto the internet service. Do a little shopping this way if you want, but don't blow that data allowance!
My earliest experience with the mobile web came in the late 1990s, programming sites to run on "Personal Digital Assistant" (PDA) devices. This type of device functions as a small handheld computer and fell out of common use during the 2000s when mobile phones started adopting the same capabilities. The Palm Pilot was the best-known brand of PDA, and its 1999 Palm VII model sported a flip-up antenna for mobile web connectivity. This was the first time I was able to do truly over-the-air web browsing, and I of course found it useful for all kinds of applications while roaming about the city, at least while the data lasted. Luckily, I was able to play with this thing at work and didn't have to pay my own monthly fee for the privilege of network access.
Handheld devices have certainly come a long way since the old days, but the needs of their users have not. Today, the Palm is no more and we deal primarily with iOS and Android devices. Yet mobile screens still retain their rather obvious defining feature of being small compared to those of desktops, giving us very specific requirements for sites we expect to browse on them. A few of the most important ones are:
  • Font size: Fonts typically need to be larger for better readability on small screens.
  • Clicks: Mobile users need larger click targets when tapping with fingers as opposed to pointing a mouse. They usually can't do things like right-click, so our interface shouldn't include those types of actions.
  • Orientation: Modern mobile devices support both portrait and landscape orientation. If the user has rotated the device for a clearer look at the content, our page had better adapt accordingly.
The first version of the Membrane Software site accounted for none of these needs; its inflexible layout was created for that bygone era of desktop domination. Let's look at some of the techniques available to provide a more mobile-friendly experience.
An unresponsive start
To begin, we'll illustrate the main problem of an unresponsive site such as the first version of Membrane Software.
Membrane Software site, image 1
An unresponsive site, viewed at an 866px width
Membrane Software site, image 2
Viewed at a 344px width, our unresponsive site fails to reflow text, forcing the user to scroll horizontally.
This sub-optimal layout is a simple enough problem to reproduce by resizing a browser window, although I recommend keeping a collection of phones and tablets on hand for most effective testing. Looking through the site's CSS code, we find static width specifications such as:
1  #main { width: 800px; }
2  #content { width: 800px; }
These days, style attributes such as these are generally ill-advised in responsive sites. They can still be effective in some situations, but are certainly not suitable when applied to main or content div elements as we see in the screenshot images.
1  body { width: 100%; height: 100%; }
2  #main { width: 100%; height: 100%; }
3  .horizontal-divider { width: 80%; }
As our first fix, we changed to a mindset that prefers element sizes expressed as percentages of their parent size.
Viewport tag
The meta viewport tag is a bit of code that needs to be present on a site for correct screen width handling. The unresponsive Membrane Software had no such tag, but we added one to each page's head element.
1  <meta name="viewport" content="width=device-width, initial-scale=1" />
For our site, width=device-width, initial-scale=1 has always worked as a content attribute; I'm not aware of any cases where a different value would be needed.
Media queries
After adding our viewport tag, the next task was to make use of CSS media queries. With these pieces of code in place, the site applies different style attributes based on its available width, as determined by window size on a desktop browser or screen size on a mobile browser.
01  @media: (max-width: 320px) {
02    body { font-size: 12px; }
03    .top-link-span { font-size: 0.8em; }
04    #logo-img { width: 132px; height: 50px; }
05    #tagline-span { margin-top: 12px; font-size: 0.9em; }
06    #paypal-button-image { width: 76px; height: 23px; }
07    .left-cell-width { max-width: 100px; }
08    .screenshot-thumb-img { width: 100px; height: 68px; }
09    .screenshot-thumb-div-item { margin-right: 4px; }
10    .screenshot-thumb-div-item3 { display: none; }
11    .screenshot-thumb-div-item7 { display: none; }
12    .contact-left-cell { min-width: 80px; }
13    .contact-text-area { min-width: 120px; }
14    .contact-text-input { min-width: 120px; }
15    .single-row-img { max-width: 300px; }
16  }
17  @media: (min-width: 321px) and (max-width: 479px) {
18    body { font-size: 12px; }
19    .top-link-span { font-size: 0.8em; }
20    #logo-img { width: 132px; height: 50px; }
21    #tagline-span { margin-top: 12px; font-size: 0.9em; }
22    #paypal-button-image { width: 76px; height: 23px; }
23    .left-cell-width { max-width: 100px; }
24    .screenshot-thumb-img { width: 96px; height: 66px; }
25    .screenshot-thumb-div-item { margin-right: 4px; }
26    .screenshot-thumb-div-item3 { display: none; }
27    .screenshot-thumb-div-item7 { display: none; }
28    .contact-left-cell { min-width: 80px; }
29    .contact-text-area { min-width: 120px; }
30    .contact-text-input { min-width: 120px; }
31    .single-row-img { max-width: 320px; }
32  }
33  @media: (min-width: 480px) and (max-width: 640px) {
34    .screenshot-thumb-div-item { margin-right: 4px; }
35    .screenshot-thumb-img { width: 96px; height: 66px; }
36    .single-row-img { max-width: 360px; }
37  }
38  @media: (min-width: 641px) and (max-width: 800px) {
39    .screenshot-thumb-div-item { margin-right: 8px; }
40    .screenshot-thumb-img { width: 125px; height: 75px; }
41    .single-row-img { max-width: 640px; }
42  }
43  @media: (min-width: 801px) {
45  }
With this set of queries, we define five screen width ranges: 320px or lower, 321px to 479px, 480px to 640px, 641px to 800px, and 801px or above. There don't seem to be a set of standard ranges, but the larger web has a range of opinions for proper media ranges; see: Media Queries for Standard Devices, Responsive Web Design Media Queries. We chose our ranges after some testing and a bit of research on the most typical screen sizes. We're not planning on getting too attached to them, though, since "typical screen sizes" change over time.
For each width range in our media queries, the site applies a separate set of style attributes to various page elements.
  • Some div elements hide themselves by setting "display: none;" at certain widths. With this setup, we cause the site to remove layout columns when the screen is too narrow to fit them.
  • Certain img elements vary their width and height properties based on the screen width.
  • Many elements use smaller margin sizes at narrower screen widths.
  • The body element specifies a smaller font-size of 12px at narrower screen widths, compared to a default size of 18px. This is the only place we use a pixel measurement for font-size; all other elements specify an em measurement for proper relative sizing. For example, font-size: 0.9em; causes an element to render fonts at 90% of the default size.
  • We didn't end up needing any specific style attributes in the 801px or above category, but left the empty query there as a placeholder.
Clearly, we're breaking our rule from before about avoiding static pixel measurements. But in this case, our static sizes are for use only within the context of a particular width. Therefore, we can be reasonably sure they're suitable and, of course, verify their effect by diligently testing the site on each of our target devices after a change is made.
Responsive images
Some of the images appearing on the Membrane Software site benefit from the responsive treatment. The most common of these images are banners, which we would like to span most of the page width at any screen size. We could use an 800px wide image asset, but that would push the entire page to be 800px wide, forcing the user to scroll. We could also use the aforementioned img width and height attributes to specify an image size, but our banner image might not look great when scaled too far away from its original size. To solve this issue, we create each banner as a set of four images at different sizes, then display the banner using a div with its background-image property chosen dynamically based on a media query.
The Membrane Software site is implemented using PHP and the Smarty PHP Template Engine. To provide responsive banner images, we'll have Smarty include a section with our background-image media queries.
01  {foreach from=$bannerImages item=item}
02  #{$item} {
03    background-repeat: no-repeat;
04    background-position: center top;
05    background-size: contain;
06    width: 100%;
07    padding: 0px;
08    margin-bottom: 6px;
09  }
10  @media (max-width: 320px) {
11    #{$item} {
12      background-image: url("/img/{$item}_0.png");
13      height: 90px;
14    }
15  }
16  @media (min-width: 321px) and (max-width: 640px) {
17    #{$item} {
18      background-image: url("/img/{$item}_1.png");
19      height: 175px;
20    }
21  }
22  @media (min-width: 641px) and (max-width: 800px) {
23    #{$item} {
24      background-image: url("/img/{$item}_2.png");
25      height: 220px;
26    }
27  }
28  @media (min-width: 801px) {
29    #{$item} {
30      background-image: url("/img/{$item}_3.png");
31      height: 294px;
32    }
33  }
34  {/foreach}
The template expects to receive a $bannerImages array with items to be converted into a set of queries. On the PHP side, we pass our desired identifiers to the template using the Smarty assign method.
1  $smarty->assign ('bannerImages', array ('star-commander-banner-0'));
In this case, the $bannerImages array is made to contain one "star-commander-banner-0" $item, causing our set of media queries to contain CSS attributes for an element carrying that ID, with background-image assets named "star-commander-banner-0_0.png", "star-commander-banner-0_1.png", "star-commander-banner-0_2.png", and "star-commander-banner-0_3.png". To complete our banner implementation, we just need to make sure these images are available at the expected URLs, then include a div with id="star-commander-banner-0" on our page.
1  <div id="star-commander-banner-0"></div>
Star Commander Banner 1
Star Commander Banner 2
With this scheme in effect, our "star-commander-banner-0" div is made to load and display a different image at each of its defined screen width ranges. In this case, the smaller banner moves the "Core 4x gaming" text to keep it from obscuring game elements in the background.
Success... for now
Having made these changes, our site is now in much better shape for viewing on a range of screen sizes.
Membrane Software site, image 3
At the wider screen size, we get the large banner and the default text size.
Membrane Software site, image 4
When the screen shrinks, the site reflows properly and uses the smaller banner asset and text size.
While we've accomplished the broad strokes in making the site responsive, keeping the site that way promises to be an ongoing battle. For example, our multiple-image banner solution may have worked out well, but we have also signed up for additional ongoing maintenance: each new banner now requires us to create four different versions instead of just one. Also, as a live site our content is ever-changing, yet each modification must now be verified on several screen sizes instead of just one. However, the extra work is well worth it to present a mobile-friendly site for our users, and as we move forward, we shall always seek to lessen our maintenance burden by accumulating ever more tips, tricks, and tools.
What did you think of this article? Leave a comment or send us a note. Your feedback is appreciated!