An Intro to Responsive Web Development
What should I know before beginning?
Experience with some of the following technologies will be helpful, but you should still be able to follow along:
- HTML (structural)
- CSS (presentation)
- JavaScript (behavioral)
Recommended reading before beginning:
What is Responsive Web Design? and how does it differ from fixed, fluid & adaptive?
A Fixed Layout
With a fixed layout the page is built to look good at fixed or static dimensions. So you might create a container for your content and set its width in pixels, and you might set your font sizes using pixels as well. This allows you some control over layout of your page, provided the user hasn’t changed a bunch of the browsers default settings. If the user is viewing the site at a narrower width than your container, the browser will introduce scroll bars. If the user is viewing on a modern smart phone/mobile device, the browser will try to fit the width of the page to the viewport’s width. This is how a great deal of sites have been built in the past. It does not offer much in regards to flexibility.
A Fluid Layout
A fluid layout is another approach to building a web page but instead of using static values you would use relative values. With a fluid layout your browser scales the layout depending on the width of the device you’re viewing it on. So that same container for your main content would have a width of say 90% instead of 960 pixels. Your fonts might use percentages as well, or em’s to allow flexibility of your typography. When taking this approach, you are assured the container will always be at most 90% of the page width. While this can be a great first step toward a responsive design, it is not the best solution.
An Adaptive Layout
An adaptive layout is a more modern layout, and it uses CSS3 media queries. With an adaptive layout you might still take the approach of static css values, but change these values to fit comfortably in the viewport. So if the user is visiting your site with a desktop browser you might style the container at 960 pixels, but if they are on a mobile phone in portrait view (320px in most cases), your container might be 300 pixels. You would add a line similar to: @media screen and (max-width: 320px). This is what we call a “breakpoint”, the point at which the browser responds with the CSS specified in that block.
A Responsive Layout
…and finally the moment you’ve all been waiting for! A responsive layout responds to the device it is being viewed on and adapts to that screen’s size. How do you accomplish this? With a combination of fluid and adaptive layout techniques. I think a demo is worth a thousand words so lets take a look at one.
Take a look at the following codepen: Layout Differences. Change the class on the body from ‘fixed’, to ‘fluid’, to ‘adaptive’ and to ‘responsive’
CSS Distance Units, or Ems and Percents and Pixels oh my…
There are quite a few Distance Units, but I am going to focus on some of the more common ones. We will start with Relative length units. With relative length units, the length specified is relative to another length. Relative lengths include:
- em: relative to the calculated font size of the element, unless used on the font-size property, in which case it is the inherited font-size of the element.
- rem: relative to the font size of the root element (the html tag, unless used on the font-size of the html element, in which case it is the initial value, this unit is not supported by IE8 and lower)
- vh: relative to 1% of the viewport’s height (* this unit is not supported by IE8 and lower)
- vw: relative to 1% of the viewport’s width (* this unit is not supported by IE8 and lower)
- vmax: relative to 1% of the viewport’s larger dimension (* this unit is not supported by IE10 and lower)
- vmin: relative to 1% of the viewport’s smaller dimension (* this unit is not supported by IE9 and lower)
** explain ** Child elements do not inherit the relative values as specified for their parent; they inherit the computed values.
** explain ** Font-relative lengths: em & rem
An em is an em is an em, except if the font-size for that element has been set. In that case an em is the calculated font-size. So if the elements font-size is calculated at 16px (the default) 1em is equal to 16px. If the calculated font-size is 24px, well 1em now becomes 24px. So what happens if we have an h1’s calculated value at 24px but its font-size is set to 2em? The font-size of that h1 is now 100% greater than the computed font-size inherited by h1 elements.
Take the following example for instance:
The div has a font-size of 24px, h1 is a child of this div so the h1’s computed font-size is 24px. We are than applying a font-size of 2em to the h1. Since its context is 24px and 2em is 100% greater than 1em, the h1’s font-size in pixels is actually 48px.
For fun, add the following to a codepen:
(Ems)
Viewport-percentage lengths: vw, vh, vmax, vmin
Not all browsers support the following viewport-percentage lengths. For this reason I will not dive deep on them.
- vh unit: Equal to 1% of the height of the initial containing block.
- vmin unit: Equal to the smaller of vw or vh.
- vmax unit: Equal to the larger of vw or vh.
I couldn’t get this example to work on codepen for some reason so lets just open the following site: http://matt.weppler.me. Using the development tools for your browser add the following html to the DOM. Open the javascript console and paste the follwing:
You should now see the newly created h1 element at the top of the page. Lets get the computed css font-size for this element.
I don’t know about you but for me it looks like the computed font size is ‘32px’. Since we’re going to work ‘vw’ which is a relative value no worries if you didn’t get 32px use substitute based on what you got. In this example, we’ll make the browser viewport 400 pixels. You’ll have to do this without the help of javascript. Now with the width of the viewport at 400px, lets set our h1’s font size to 8vw.
Go ahead and resize the window, notice how the font size of the h1 element becomes larger and smaller based on the viewports width.
Absolute lengths: px
Pixels are typically considered relative to the viewing device, one device pixel (dot) of the display.
Percentage lengths: %
Percentage lengths depend on the size of their parent elements. So if you have a div with a width of 500px and 2 child divs at 50% each, the child divs widths are actually 250 pixels.
Even when starting a new project from scratch with a mobile first mindset you’ll still likely be working from a design comp. This will most likely be an Adobe Photoshop file. So you will no doubt be working with static units in some form. Here is a table that you can use to convert between px and em, or px and %.
Points to Pixels to Ems to Percent
Points | Pixels | Ems | Percent |
---|---|---|---|
6pt | 8px | 0.5em | 50% |
7pt | 9px | 0.55em | 55% |
7.5pt | 10px | 0.625em | 62.5% |
8pt | 11px | 0.7em | 70% |
9pt | 12px | 0.75em | 75% |
10pt | 13px | 0.8em | 80% |
10.5pt | 14px | 0.875em | 87.5% |
11pt | 15px | 0.95em | 95% |
12pt | 16px | 1em | 100% |
13pt | 17px | 1.05em | 105% |
13.5pt | 18px | 1.125em | 112.5% |
14pt | 19px | 1.2em | 120% |
14.5pt | 20px | 1.25em | 125% |
15pt | 21px | 1.3em | 130% |
16pt | 22px | 1.4em | 140% |
17pt | 23px | 1.45em | 145% |
18pt | 24px | 1.5em | 150% |
20pt | 26px | 1.6em | 160% |
22pt | 29px | 1.8em | 180% |
24pt | 32px | 2em | 200% |
26pt | 35px | 2.2em | 220% |
27pt | 36px | 2.25em | 225% |
28pt | 37px | 2.3em | 230% |
29pt | 38px | 2.35em | 235% |
30pt | 40px | 2.45em | 245% |
32pt | 42px | 2.55em | 255% |
34pt | 45px | 2.75em | 275% |
36pt | 48px | 3em | 300% |
The Golden Rule: Target / Context = Result
Target divided by Context equals Result. Say it with me: “Target divided by Context equals Result”. One more time…
So where do we begin? Why with a fluid foundation of course.
A Fluid Grid
Lets start with a fixed grid and work our way to a fluid one. The reason for this is that our designs will likely come from a Photoshop file or something similar. These will have been created using fixed value lengths (pixels).
Since we are not actually working from a design comp, I’ll use gridulator as our base for our grid. Open Gridulator and set the overall width to 960 and the number of columns to 8. This should generate a few grid options (column width/gutter width pairs). Click the “Preview” button for the pair with a column width of 106 and a gutter width of 16. You can get an idea of our grid dimensions from the grid image that is displayed. Now click the “Make PNG” button, this should download an image named: 960px-8col-106w-16gut.png.
(960 pixel, 8 column, 106 pixel width, 16 pixel gutter)
Lets start with our ‘grid-container’ class. What we’ll want to do is constrain our container width to 960 pixels & center it in the page. To do this we add the following rules:
Next we create our ‘grid’ class. This will be applied to any elements that will act as a column in our grid. We will need our columns to float so we’ll have to add the float left rule. We can also add the margin or gutter to this class:
Now lets start getting into the specific columns, we will name them ‘grid-1’ through ‘grid-8’ and give them the appropriate widths. To calculate the width we start with our column size of 106 pixels and add that to ‘grid-1’:
For ‘grid-2’ we need to take into account the base column width of 106 pixels, multiply that by 2 since ‘grid-2’ should take up the width of 2 columns, and add the first columns margin/gutter of 16px. So ‘grid-2’ should have a width of 228 pixels:
Moving on to ‘grid-3’ we follow the same approach of multiplying the base width with the number of columns, in this case 3, then we add the gutter base of 16 pixels multiplied by the number of columns minus 1. You can also just apply the following method. Take the previous grids width, so in this case that of ‘grid-2’ and add the base column width plus the gutter width. Either way we end up with grid-3’s width being 350 pixels:
Go ahead and calculate the rest of the classes and check with those below:
Lets work with our grid to get familiar with it. In this example, we have a row of content with 2 columns, each column will take up half of the row. If you apply the following markup and styling notice what happens:
The elements are stacking instead one on top of the other instead of inline side-by-side. Why? Well the ‘grid’ class has a gutter or right margin of 16 pixels. So when we take the width of the ‘grid-4’ class and multiply it by 2 we get 944. Now add the 2 right gutters which increase the width by 32 pixels and we’re over the allowed width of the container’s 960 pixels. We’re over by 16 pixels to be exact. This is a common problem with this type of grid system and what we’ll do to address it is add a new class ‘omega’. This class will set the right margin to 0. We add this to the last column in each row.
…and we update our last column
That does what we expect. Great! Now that we have our tried and tested grid system in place, lets go ahead and make it fluid. Lets start by changing our ‘grid-container’ length from pixels to percent. We’re going to set its width to 90 percent, just because that seems to work well.
For the rest of our grid elements we’re going to apply the Golden Rule:
Target / Context = Result
Start with the ‘grid-8’ and work your way down to ‘grid-1’. Lets apply the target / context rule, where both target is 960 pixels and the context is 960 pixels (the original size of our container in pixels). This gives us 1, or 100 percent really.
That was easy. Now on to ‘grid-7’ Again we apply the target / context, but this time the target is 838 pixels and the context is the 960 pixels. This gives us 0.87291666666667. You may think that rounding here is a good idea, but its not. No lets just set our width to its percentage by multipling by 100:
Go ahead and give the remaining grid classes a shot, check with the values below:
Great but we have one more class to convert the ‘grid’ class itself. In this case we have the gutter or right margin. This takes us to the topic of margin and padding.
Margin & Padding
How do we convert margins and padding? We use the same target / context = result. The main differences is in the context. For margins its simple in this case we use the containers width of 960 pixels.
For padding however we would use the actual element’s width as the context. Since we are not dealing with any padding just yet, we’ll just have to use some mock values in order to drive the point home. Since I am going to use images to do this, we will transition into the next part of responsive design, scalable images.
Scalable Images
Lets swap-out the html in our codepen with the following:
We’re adding another row of images. In the first column of the second row we have 2 images both with the class of ‘half’. All the rest of the images have a class of ‘full’. Notice that the images in the second row first column or the ‘half’ images, are on the same line with no space instead of say on another line with the same indentation. This is because images are inline-block and if we added the space, that space would be added to the width of the elements in this column.
Lets update our CSS now, after the all the ‘grid’ classes and before the ‘omega’ class add the ‘full’ & ‘half’ classes like below:
As you can see the images in the second row, first column are butt up against each other with no padding or space separating them visually. Lets add some right padding to these ‘half’ images.
What is happening now is our ‘half’ class is actually taking up 102 percent of the width of its parent. Obviously this is what is causing the second image to be pushed to a new line. If we adjust the ‘half’ class’ max width to 49 percent, were back in business.
Well except for the fact that now we have right padding on on the second ‘half’ image. So lets remove the right padding from the ‘omega’ class, and bump up the max width on the ‘half’ class to 49.5 percent.
Ok, lets recap. We created a grid composed of fixed values to serve as our baseline. This made it easier to convert to a fluid grid using the target / context rule. We worked with some margin and padding. Margin is based on the size of the parent and padding is based on the size of the element itself. Finally we worked with the max width property, applying it to images to make them scalable. Now we are going to switch gears for a moment. I want to get into adaptive layouts.
Lets talk about adaptive layouts a bit.
With our responsive layout taking shape we can begin building our pages. What we may notice, and hopefully sooner rather than later, is that some of our design, while it fits, it could look better. Look at the layout differences demo and set the layout to fluid. Resize the browser window slowly and notice how the features (‘feature’ class elements) are fluid. Meaning as the window becomes more narrow, the row of three features shrinks and stays inline. Now change the layout to ‘adaptive’ and do the same thing. You can see how as you narrow the window the features go from three in a row, to two in a row, and finally to one per row. Wouldn’t it be great if we could have the best of both worlds? Well the good news is we can! Change the layout to ‘responsive’ and resize the window. This is what we want.
How do we accomplish this? It’s all about the breakpoints. Breakpoints are the point at which your design starts to break down visually. An approach you can take to this is start with your fixed grid and resize the browser. Once you reach a point that it does not look as good. Take note of this break point. It’s at this breakpoint that we will introduce our first CSS3 media query. You rememeber what a media query looks like don’t you? Well if not, it looks something like this:
So what does this even mean anyway? Lets break it into parts and have a go at it:
See the spec for more detailed information on the different media types.
The preceeding was a simple rule so lets take a look at the media queries used in the layout differences demo:
For a more detailed information and examples see the spec
The viewport
When we talk about the ‘viewport’ we are basically talking about a device’s display. One of the first things you should know about is a pixel. We’ve talked a bit about pixels as far as units of measurement. A pixel is a tiny dot that is colored red, green or blue. Your display, whether its a computer monitor or mobile phone screen is made up of many pixels. The pixels that make up your display and the pixel units we have been using in our CSS are not quite the same size however. For most of our daily tasks we are not really concerned by this but you should know a little bit about it. A great article that goes into depth on this is “A tale of two viewports” and I highly recommend reading it. I had to read it multiple times in fact. http://www.quirksmode.org/mobile/viewports.html
When it comes to responsive design we need to consider how an actual mobile browser will render the page. Most modern mobile browsers will fake the devices viewport size. They then display the page in a zoomed out view, trying to fit the page into the viewport. In the past, designers & developers really didn’t put all that much into “what will my page look like on a mobile device”. We, however, are and we don’t want the browser to take this default approach. So we need to override this behavior. Enter the viewport meta tag.
The viewport meta tag allows us to tell the browser that your viewport width should use its actual device width instead of any browser defaults. We also want to set the initial scale to 100%. The tag will look like:
One thing to note is that Microsoft is taking a different approach. Read more about CSS Device Adaptation. The gist of it is to use a viewport rule in your css instead of (or in combination with to be safe) the viewport meta tag. The rule and the microsoft prefix look like:
@viewport {
width: device-width;
}
@-ms-viewport {
width: device-width;
}
Re-building the layout differences page:
We are now going to rebuild the responsive part of the layout differences demo we saw earlier. Open codepen and add the following boilerplate to the html section:
As we learned earlier, our mobile device is faking the viewport size for sites that are not mobile friendly or responsive. So lets add the viewport meta tag before we go any further.
Now we can start marking up our page. Looking at the layout differences as if it were a static comp, lets get semantic. We have two sections, each taking up the width of the container. So what does that look like:
Each section has a headline:
Lets focus on the first section now. It has some images with headlines & descriptions under them. Lets name these modules ‘figure-with-caption’.
Your codepen should look similiar to the following:
(Figure w/Caption Checkpoint)
Now we can move on to the second section. It is basically just table data. Possibly related to our figures. Lets name these modules ‘figures-and-specifics-table’.
Your codepen should now look similiar to the following:
(Figures & Specifics Checkpoint)
Pretty basic and pretty semantic. Lets add some style to the page.
Thats looking better already. Lets work on the ‘figure-with-caption’. We need to float them left, center align the text, give them a margin of 1 percent and a width of 31.5 percent:
Getting better, we just need to make the images take up 100 percent width:
I am happy with the look of the page now. Its time to introduce our first breakpoint. I think a comfortable point is at 1024 pixels.
And our last breakpoint will be at 640 pixels
@media screen and (max-width: 640px) and (min-width: 320px) {
.grid-1, .grid-2, .grid-3, .grid-4, .grid-5, .grid-6, .grid-7, .grid-8 {
width: 100%;
}
.figure-with-caption {
float: none;
margin: 0;
width: 100%;
}
.figure-data, .specifics-data {
float: left;
width: 100%;
}
.figure-data {
background: #1e1e1e;
}
.specifics-data {
background: #262626;
}
}
Looks good. Now at this point we have some minor touching up to do. For the most part the page will look great on any modern phones, tablets, desktops etc…
I hope you’ve found this useful and if you build anything cool using these techniques I’d love to see it. So shoot me an email. Thanks!