Responsive grids and fluid CSS

December 5th, 2012

In this post from Anthony, our lead front end web developer, we give some technical insights into how we tackle the challenge of making the sites we build work well on multiple devices via responsive design.

In order to maximise reach, we now have to cater for multiple devices when we build a website. With the rise of smartphones and tablets this means designing websites that scale smartly from very narrow to very wide. In this situation we can keep one set of code and content and provide for multiple platforms.

Grid systems have been in vogue recently but here at Traffic we take a different approach to the positioning and alignment of elements. Rather than explicitly defining a number of columns an element should occupy, we prefer the flexibility of allowing that element to change its relative size at each media query break point.

Element positioning

Elements are divided into groups. At wider levels, elements float side by side; at the smallest they sit one on top of each other at 100% width.


section {
    float: left;
    margin-left: 30px;
}
section:first-child {
    margin-left: 0;
}

For each media query we can create a custom layout. Each grid item has a specific width that will look good and function well for that screen size. We have to remember that at larger screen sizes paragraphs should not contain too many words, and for mobile screen sizes there should be only a single column with images and videos scaled down to size.

@media all and (min-width: 1217px) { 
     .s1 {  width:50%; }
     .s2 {  width:50%; }
     .s3 {  width:50%; }
     .s4 {  width:50%; }
}
@media all and (min-width: 749px) and (max-width: 977px) {  
     .s1 {  width:70%; }
     .s2 {  width:30%; }
     .s3 {  width:70%; }
     .s4 {  width:30%; }
}
@media all and (min-width: 0px) and (max-width: 748px) {  
    section { 
        float: none; 
        margin: 0; 
        width: 100%; 
    }
     .s3 {  display:none; }
     .s4 {  display:none; }
}


To take this further we can change the float and margin for each individual element. We should remember that as a rule, users won’t be constantly scaling their browser window and their experience will usually be limited to just one of our media queries. For this reason if we need to, we can make each media query as different as the last without much fear of confusing the user.

So by specifying a different layout for each step of the media query we can create an interesting and intuitive responsive website that we have complete control of, all the way down to smartphone size screens.

This method uses media queries to maximise space and increase readability. We can also control the layout of the content, which is particularly useful for mobile screens. In this case we are actually setting the default values to benefit the smallest screens and then adjusting them up for larger screen sizes. It’s also possible to work the other way round by setting default values for huge screens and then working backwards.

Maximising space

All the elements or each group of elements has a parent container. This parent container has a maximum width (for very wide monitors), but as the viewport decreases in size it falls back to a percentage of the overall viewport width. Here we use media queries to decrease the margin by increasing the container percentage width. So at a mobile screen level there is only a 2.5% margin on the left and right. On larger screens the container percentage width decreases to give a bigger margin until the maximum width is reached.


.container {
    width: 95%;
    max-width: 1140px;
    margin: 0 auto;
}
@media screen and (min-width: 680px) {
    .container {
        width: 90%;
    
}
}
@media screen and (min-width: 886px) {
    .container {
        width: 85%;
    
}
}
@media screen and (min-width: 1040px) {
    .container {
        width: 80%;
    
}
}

Positioning elements

Content elements such as the ‘section’ or ‘aside’ are initially set to have a width of 100%. This is the default for mobiles so one section sits on top of the other. As we increase the screen width the elements change to float and sit side by side. (Note: the first two css selectors here are superfluous as their default display attribute is ‘block’.)


section {
    width:100%;
}
aside {
    width:100%;
}
@media screen and (min-width: 680px) {
    section {
        width:70%;
        float:right;
    
}
    aside {
        width:30%;
        float:left;
    
}
}

The two content elements can be spaced by applying a margin to the elements inside one or other of the content elements. This margin also changes width with the viewport and font size. The media query applied here will allow for zero horizontal margin on elements at mobile level.

@media screen and (min-width: 680px) {
    aside h2 {
        margin-right: 1em;
    
}
    aside p {
        margin-right: 1em;
    
}
}

Increasing readability

It’s good practice to increase font sizes for larger monitors while at the same time preserving the space saving idea by having a default smaller font for smaller screens. In this case mobiles will have an overall body font size of the browser default of 100%; if a smaller font is required this can be set to 87.5%. As the media queries start to kick in, the body font size is adjusted upwards. All text elements on the page are then scaled based on this body font size. By avoiding using pixels font sizes and margins, we can keep things simple and avoid bloated media queries stuffed with overrides.


body {
    font-size: 100%;
}
h2 {
    font-size: 1.5em;
    line-height: 1.48em;
    margin-bottom: 1em;
}
p {
    font-size: 1em;
    line-height: 1.48em;
    margin-bottom: 1em;
}
@media screen and (min-width: 680px) {
    body {
        font-size: 112.5%;
    
}
}
@media screen and (min-width: 886px) {
    body {
        font-size: 125.0%;
    
}
}
@media screen and (min-width: 1040px) {
    body {
        font-size: 137.5%;
    
}
}

Good luck in making your next project a responsive one!

m4s0n501