Our first responsive example
In the first paragraph I promised that by the end of this chapter you would know all you needed to build a fully responsive web page. So far I've just been talking around the issue at hand. It's time to walk the walk.
Note
Code samples
You can download all the code samples from this book by visiting rwd.education/download.zip or via GitHub at https://github.com/benfrain/rwd. It's worth knowing that where individual examples are built up throughout a chapter, only the final version of the example is provided in the code download. For example, if you download the code samples for Chapter 2, Media Queries – Supporting Differing Viewports, the examples will be in the state they are at by the end of Chapter 2, Media Queries – Supporting Differing Viewports. No intermediate states are provided other than in the text.
Our basic HTML file
We will start with a simple HTML5 structure. Don't worry at this point what each of the lines do (especially the content of the <head>
, we will cover that in detail in Chapter 4, HTML5 for Responsive Web Designs).
For now, simply concentrate on the elements inside the <body>
tag. I'm pretty sure nothing there will look too unusual; a few div's, a graphic for a logo, an image (a tasty looking scone), a paragraph or two of text and a list of items.
Here's an abridged version of the code. For brevity I have removed the paragraphs of text in the code below as we only need to concern ourselves with the structure. However, you should know that it's a recipe and description of how to make scones; quintessentially British cakes.
If you want to see the full HTML file, you can download it from the rwd.education website.
<!doctype html> <html class="no-js" lang="en"> <head> <meta charset="utf-8"> <title>Our first responsive web page with HTML5 and CSS3</title> <meta name="description" content="A basic responsive web page – an example from Chapter 1"> <link rel="stylesheet" href="css/styles.css"> </head> <body> <div class="Header"> <a href="/" class="LogoWrapper"><img src="img/SOC-Logo.png" alt="Scone O'Clock logo" /></a> <p class="Strap">Scones: the most resplendent of snacks</p> </div> <div class="IntroWrapper"> <p class="IntroText">Occasionally maligned and misunderstood; the scone is a quintessentially British classic.</p> <div class="MoneyShot"> <img class="MoneyShotImg" src="img/scones.jpg" alt="Incredible scones" /> <p class="ImageCaption">Incredible scones, picture from Wikipedia</p> </div> </div> <p>Recipe and serving suggestions follow.</p> <div class="Ingredients"> <h3 class="SubHeader">Ingredients</h3> <ul> </ul> </div> <div class="HowToMake"> <h3 class="SubHeader">Method</h3> <ol class="MethodWrapper"> </ol> </div> </body> </html>
By default, web pages are flexible. If you were to open the example page, even as it is at this point (with no media queries present), and resize the browser window you'll see the text reflows as needed.
What about on different devices? With no CSS whatsoever, this is how that renders on an iPhone:
As you can see, it's rendering like a 'normal' web page would on an iPhone. The reason for that is that iOS renders web pages at 980px wide by default and shrinks them down into the viewport.
The viewable area of a browser is known technically as the viewport. The viewport is seldom equivalent to the screen size of a device, especially in instances where a user can resize a browser window.
Therefore, from now on, we will generally use this more accurate term when we are referring to the available space for our web page.
We can fix that prior problem easily by adding this snippet in the <head>
:
<meta name="viewport" content="width=device-width">
This viewport meta
tag is a non-standard (but de facto standard) way of telling the browser how to render the page. In this case, our viewport meta
tag is effectively saying "make the content render at the width of the device". In fact, it's probably easier to just show you the effect this line has on applicable devices:
Great! The text is now rendering and flowing at a more 'native' size. Let's move on.
We will cover the meta
tag and its various settings and permutations (and the standards based version of the same functionality) in Chapter 2, Media Queries – Supporting Differing Viewports.
Taming images
They say a picture is worth a thousand words. All this writing about scones in our sample page and there's no image of the beauties. I'm going to add in an image of a scone near the top of the page; a sort of 'hero' image to entice users to read the page.
Oh! That nice big image (2000px wide) is forcing our page to render more than a little wonky. We need to fix that. We could add a fixed width to the image via CSS but the problem there is that we want the image to scale to different screen sizes.
For example, our example iPhone is 320px wide so we could set a width of 320px to that image but then what happens if a user rotates the screen? The 320px wide viewport is now 480px wide. Thankfully it's pretty easy to achieve fluid images that will scale to the available width of their container with a single line of CSS.
I'm going to create the css/styles.css
CSS file now that's linked in the head of the HTML page.
Here is the first thing I'm adding. Ordinarily I'd be setting a few other defaults, and we'll discuss those defaults in later chapters, but for our purposes I'm happy to open with just this:
img { max-width: 100%; }
Now when the page is refreshed we see something more akin to what we might expect.
All this max-width
based rule does is stipulate that all images should be a maximum of 100% of their width (in that they should expand to 100% of their size and no more). Where a containing element (such as the body
or a div
it sits within) is less than the intrinsic width of the image, it will simply scale up to the maximum available space.
Tip
Why not simply width: 100%?
To make images fluid you could also use the more widely used width property. For example, width: 100%
but this has a different effect. When a property of width
is used then the image will be displayed at that width, regardless of its own inherent size. The result in our example would be the logo (also an image) stretching to fill 100% of its container. With a container far wider than the image (as is the case with our logo) this leads a massively oversized image.
Excellent. Everything is now laid out as expected. No matter the viewport size, nothing is overflowing the page horizontally.
However, if we look at the page in larger viewports, the basic styles start to get both literally and figuratively stretched. Take a look at the example page at a size around 1400px:
Oh dear! In fact, even around 600px wide it's starting to suffer. Around this point it would be handy if we could rearrange a few things. Maybe resize the image and position it off to one side. Perhaps alter some font sizes and background colors of elements.
Thankfully, we can achieve all this functionality quite easily by employing CSS media queries to bend things to our will.
Enter media queries
As we have established, somewhere beyond the 600px wide point, our current layout starts to look stretched. Let's use CSS3 media queries to adjust the layout depending upon the screen width. Media queries allow us to apply certain CSS rules based upon a number of conditions (screen width and height for example).
Tip
Don't set breakpoints to popular device widths
'Breakpoint' is the term used to define the point in which a responsive design should change significantly.
When people first started making use of media queries it was common to see breakpoints in designs built specifically around the popular devices of the day. At the time it was typically iPhone (320px x 480px) and iPad (768px x 1024px) that defined these 'breakpoints'.
That practice was a bad choice then, and it would be an even worse one now. The problem is that by doing that we are catering a design to a specific screen size. We want a responsive design—something that is agnostic of the screen size viewing it; not something that only looks at its best at specific sizes.
Therefore, let the content and the design itself determine where a breakpoint is relevant. Maybe your initial layout starts to look wrong at 500px wide and greater, perhaps 800px. Your own project design should determine when a breakpoint is needed.
We will cover the entire gamut of CSS media queries in Chapter 2, Media Queries – Supporting Differing Viewports, inventively titled Media Queries.
However, for the purpose of whipping our basic example into shape, we will concentrate on just one type of media query; a minimum width media query. CSS rules within this type of media query only get applied if the viewport is a minimum defined width. The exact minimum width can be specified using a raft of different length units including percent, em, rem, and px. In CSS, a minimum width media query is written like this:
@media screen and (min-width: 50em) { /* styles */ }
The @media
directive tells the browser we are starting a media query, the screen
part (declaring 'screen' is technically not needed in this situation but we will deal with that in detail in the next chapter) tells the browser these rules should be applied to all screen types and the and (min-width: 50em)
tells the browser that the rules should be limited to all viewports above 50em of size.
Tip
I believe it was Bryan Rieger (http://www.slideshare.net/bryanrieger/rethinking-the-mobile-web-by-yiibu) who first wrote that:
"The absence of support for media queries is in fact the first media query."
What he meant by that is that the first rules we write, outside of a media query should be our 'base' rules which we then enhance for more capable devices.
For now, simply be aware that this approach re-enforces our smallest screen first mentality and allows us to progressively layer on detail as and when the design necessitates it.
Amending the example for a larger screen
We've already established that our design is starting to suffer at around 600px/37.5rem width.
Therefore, let's mix things up a little by way of a simple example of how we can lay things out differently at different viewport sizes.
Tip
Almost all browsers have a default text size of 16px so you can easily convert widths to rems by dividing the px value by 16. We will discuss why you might want to do this in Chapter 2, Media Queries – Supporting Differing Viewports.
First off, we will stop that main 'hero' image getting too big and keep it over on the right. Then the intro text can sit to the left.
We will then have the main portion of text, the 'method' that describes how to make the scones, on the left below with a small boxed out section detailing the ingredients over on the right.
All these changes can be achieved relatively simply by encapsulating these specific styles within a media query. Here's what things look like with the relevant styles added:
It still looks essentially the same as it did before on smaller screens but adjusts to the new layout as soon as the viewport is 50rem or wider.
Here are the layout styles that were added:
@media screen and (min-width: 50rem) { .IntroWrapper { display: table; table-layout: fixed; width: 100%; } .MoneyShot, .IntroText { display: table-cell; width: 50%; vertical-align: middle; text-align: center; } .IntroText { padding: .5rem; font-size: 2.5rem; text-align: left; } .Ingredients { font-size: .9rem; float: right; padding: 1rem; margin: 0 0 .5rem 1rem; border-radius: 3px; background-color: #ffffdf; border: 2px solid #e8cfa9; } .Ingredients h3 { margin: 0; } }
That wasn't too bad was it? With only minimal code we have built a page that responds to the viewport size and offers a preferable layout as needed. By adding just a few more styles things look even easier on the eye. With those in place, our basic responsive page now looks like this on an iPhone:
And like this above 50rem width:
These further visual embellishments don't add to the understanding of what's happening responsively, hence I have omitted them here but if you'd like to view the relevant code, download the chapter code at http://rwd.education or https://github.com/benfrain/rwd.
This has been a very basic example but it has encapsulated the essential methodology of building out a responsive web design.
To reiterate the essential things we have covered; start with 'base' styles, styles that can work on any device. Then layer enhancements on progressively as the viewport size and/or capabilities increase.
Note
You can find the full specifications for CSS Media Queries (Level 3) here: http://www.w3.org/TR/css3-mediaqueries/
There is also a working draft for CSS Media Queries (Level 4) here: http://dev.w3.org/csswg/mediaqueries-4/