Responsive web design can be broken down into two components: a design philosophy, and CSS style rules that accommodate multiple browser sizes. The goal of this class is to discuss and understand the principles of responsive design, and implement some basics in student sites.
- Discuss mobile first, graceful degradation vs progressive enhancement, some history of the mobile web)
- Introduce media queries (the demo link provided is a great way to show how they work)
- Demonstrate the use of fluid images, and defining width/height in percentages
- Discuss flexible grids, the benefit they can provide. Build a simple one and demonstrate its usefulness
- Briefly discuss frameworks, their pros and cons
This is the story of two design philosophies: one which dominated the old web, and one tailored for the new where mobile phones prevail. Graceful degradation is designing an optimal experience for the largest, most feature-rich browser (typically a large, modern desktop browser) first, and stripping away as browser size and capability decreases. Progressive enhancement is optimizing for the smallest, most restrictive browser (typically a mobile phone, perhaps a slightly outdated version) first, and embellishing as browser size and capability increases.
On the surface, each of these methods would seemingly produce similar results — so why do we even? Since few designers like to spend their time or energy on less-than-ideal designs, there is a tendency to put the most time and effort into your optimal design. So with a graceful degradation approach, you often end up with a watered down version of our optimal design after stripping away features and content. With progressive enhancement, you focus on creating an ideal experience for mobile, deciding to include only features that are necessary. Then as you expand out, anything you add in is just icing on an already optimal cake.
And if the holistic "things tend to be better" argument isn't enough for you, progressive enhancement can lead to more performant sites as well. If you are going to hide certain assets like video or images in your mobile design, it might make sense to only load them in at larger screen sizes, or not load them at all (i.e. does this 6mb background video really add enough value to my site to justify the loss in performance?). This is because even when you hide something using display: none; in CSS, the browser still needs to make a request to load that asset. The more requests the browser has to make, the slower your page loads.
A media query is an expression that specifies a scope in which the styles it contains will be applied. We can now start to think of our CSS documents as being separated into zones defined by screen sizes.
body{
font-size: 16px;
background-color:blue;
}
video{
display:none;
}
@media (min-width:480px){
body{
font-size:18px;
}
}
@media (min-width:1200px){
body{
font-size:22px;
}
video{
display:block;
}
}
What we've done here is create three unique "zones" in our CSS document. Each of the media queries marks its own zone, and all the rules above them make up a zone as well.
Let's talk about the first zone, the rules outside of any media queries. In a mobile-first setup, this zone consists of two things: mobile-only styles, and universal styles.
Mobile-only styles are defined by rules that get overwritten in a subsequent media query. For instance, here we set the font-size on body to be 16px. This rule will hold until the browser viewport reaches 480px wide, at which point it is overwritten to now be 18px. Now at any screen size between 480px and 1199px, this rule will hold. At 1200px, our final media query evaluates to true and the font-size is once more overwritten, this time to be 22px.
Universal styles are declared outside of any media queries, and are never overwritten. In this case we set the background-color on body to be blue, and never changed that value in any subsequent media queries. As media queries are only used for overwriting rules or introducing new ones, we never have to repeat ourselves if we want a style to remain the across all screen sizes.
In addition to screen sizes, media queries can limit styles to certain media types such as print and tv:
@media print{
// rules within this media query will only apply if a user tries to print the page
}
@media tv{
// rules within this media query will only apply if the output device is a television
}
They can also be used to detect browser height, device orientation, screen color, and much more:
@media (max-height:800px){
// rules within this media query will only apply if the browser height is less than 800px
}
@media (orientation: landscape){
// rules within this media query will only apply if the device's orientation is landscape
}
@media (color){
// rules within this media query will only apply if the screen outputs in color
}
Here is a link to a demo that demonstrates basic use of screen size media queries. There are five "p" tags, each describing a certain size range. The CSS changes the background-color and hides/shows only the "p" tag describing the range you are in.
http://codepen.io/tjbenneche/pen/GJKQYe
By defining element widths or heights as percentage values rather than fixed pixel values, you allow an element to scale as the browser window is resized.
For instance, an image with the following style rules will be rendered as 600px wide regardless of screen size:
img{
display:block;
width:600px;
}
If, however, we were to define the image's width as 50%, it will adjust as you shrink or enlarge the browser:
img{
display:block;
width:50%;
}
It is important to note that percentage values are relative to the size of an element's parent container. If the only parent element is the "body" tag, then the parent is the size of the entire page. But let's say that image were in a "div", like so:
<div>
<img src="http://placehold.it/30x30">
</div>
and we had the following CSS rules applied:
div{
width:1000px;
}
img{
display:block;
width:50%;
}
Now, since the image has a parent with a fixed pixel width, even though its width is defined in a percentage, it will not scale with the page. Instead, it will always render at 50% of its parent — in this case 500px. To make this setup fully responsive, we could define both the "div" and "img" as percentage widths:
div{
width:80%;
}
img{
display:block;
width:50%;
}
Now as you resize the browser, the div will always be 80% of the entire width, and the img will be 50% of that (or 40% of the whole).
This technique can be applied to heights as well, and both height and width come with sister properties: min-height and min-width, and max-height and max-width.
A combination of min, max, and the standard width properties is often used in creating Fluid Images. Fluid images were one of Ethan Marcotte's original tenets of Responsive Web Design, and are created using a combination of percentages and fixed pixel values.
Let's start with an assumption: any image (with the exception of an svg — scalable vector graphic) when stretched beyond its natural resolution, will become pixelated or blurry. With this in mind, we would never want our images to expand beyond that given size.
So let's say we have an image whose natural resolution is 600x400. We want this image to scale with the page, but never get pixelated. We can accomplish this in CSS like so:
img{
width:50%;
max-width:600px;
}
This technique could also be used in reverse. Let's say we wanted the image to always be shown at its natural resolution, except at screen sizes where it won't fit, in which case it should take up 100% of the space available.
img{
width:600px;
max-width:100%;
}
Another tenet of Responsive Web Design that Ethan Marcotte outlined is a flexible grid. This is basically a method of organization for various widths and margins, used by many of the popular responsive frameworks (explained next). The idea is this:
Rather than worrying about applying widths and/or margins to each element in your CSS, spend some time upfront to specify a number of classes that represent columns in a grid. The two primary responsive frameworks, Bootstrap and Foundation, use 12-grids, and because of that simplicity we will as well. Here are the classes we would create:
//One class for each column-width
.one-column{
width: calc((1/12)*100%);
}
.two-columns{
width: calc((2/12)*100%);
}
.three-columns{
// 3/12 is exactly equal to 1/4, so no calc method needed here
width: 25%;
}
...
.twelve-columns{
width:100%;
}
// One class for each column-margin-width
.offset-one
margin-left: calc((1/12)*100%);
}
.offset-two
margin-left: calc((2/12)*100%);
}
...
.offset-twelve{
margin-left: 100%;
}
There we defined two groups of classes: one for widths, and one for margins (or offsets). Then, if we wanted an image to be 50% of the width of the page, and always be centered, we could just assign two of our pre-built classes rather than writing any additional CSS:
<img class="six-columns offset-three" src="http://placehold.it/30x30">
This allows for cleaner CSS and much less work on the developer's end once the system is set up.
A responsive framework is effectively a library of pre-written code that you can use to build a website quickly. The primary benefit of a framework is generally its flexible grid — meaning you can just use column or offset classes out of the box without setting up the grid yourself.
To include a framework in your website, you just reference their CSS file like you would your own:
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
Above we're using a hosted version of Bootstrap, but you can also download it and include it among your CSS files (they even let you customize which components are included to reduce file size).
Both Bootstrap and Foundation offer many features out of the box, including modals, carousels, and more. There are some seriously great benefits to using a framework, but of course they do come with some drawbacks. Because there are so many pre-build styles included, you may at times see some unexpected behavior if you accidentally assign a class with a name used in the framework. Also, to modify any of their code you have to use style rules with equal or higher specificity than theirs, which may result in some ugly, long selector chains in your CSS.
http://www.w3.org/wiki/Graceful_degradation_versus_progressive_enhancement
http://designshack.net/articles/css/mobilefirst/
http://alistapart.com/article/responsive-web-design
http://blog.froont.com/9-basic-principles-of-responsive-web-design/
http://demosthenes.info/blog/586/CSS-Fluid-Image-Techniques-for-Responsive-Site-Design
http://blog.cloudfour.com/the-ems-have-it-proportional-media-queries-ftw/
Let's make our sites responsive! Add at least two media queries into your CSS. At first test to see if they're working by making blatant changes (background-color on body is generally a good test), then once that's confirmed make changes so your site behaves well on different screen sizes. On elements where it makes sense to do so, change any fixed value widths to percetanges. Next week we will review responsive (it's a lot to grasp and will probably require a little more than one class, and certainly some practice on your own), prepare for final presentations, and introduce CSS transitions and transforms.