Responsive layouts - Designing for the responsive web - The Responsive Web (2015)

The Responsive Web (2015)

Part 2. Designing for the responsive web

Chapter 5. Responsive layouts

This chapter covers

· Using percentages to create fluid layouts

· Animating the off-canvas navigation pattern

· Adjusting the layout for varied screen sizes

Building a responsive layout is, quite possibly, the easiest task in building a responsive website. All a layout has to do is gracefully refactor at given breakpoints. In chapter 1, I showed you some media queries to enable this refactoring, and you saw how selectors can override each other when applied from within a media query. To build a responsive layout, you just need to apply this logic. An element in a small screen should be one width, and then another width in a larger screen. But despite how simple this sounds, things always find a way of getting more complicated.

Responsive layouts tend to get more complicated because layout is often still determined in fixed terms. When a layout is created in a graphics editing program, the sizing is specified using measurements like pixels. It’s easy to adjust sizes and share screen space when you’re using CSS, but doing it in graphics programs is a recipe for inconsistency and extraneous coding because there’s an inherent difference in the way these two technologies render their visual layers. That’s why it’s important to determine layout for a responsive site in the browser, not in a comp.

In this chapter, we’ll cover the most effective ways of crafting a responsive layout. This means building a fluid grid system using percentages instead of pixels. We’ll also cover some of the tricks you can use to make this process a little easier.

Designer insight: a designer’s role in layout

Though much of the hands-on responsibility for layout lies on the shoulders of the developer, an art director’s sense of space is absolutely crucial to prevent the layout from looking too static or uniform.

Quick sketches and regular, short check-ins are crucial so that the designer retains input in this phase of the process. Naturally, this is going to require some understanding and trust on both sides, but the result of working like this is a site that everyone can be proud of.

5.1. Fluid layouts via percentages

In responsive web design, you’ll notice the use of percentages for layout widths. These percentages create what’s called a fluid layout, which is a layout that adjusts to the available space. In order to understand how this works and why it’s important, you need to know how box sizing and percentages work in CSS.

5.1.1. How percentages work in CSS

Historically, web designs based all sizing on pixels. These pixels represent screen pixels, although it’s not a one-to-one representation. High DPI screens will convert what’s set as a “px” or “pixel” size into its appropriate grouping of screen pixels. This conversion can be complicated and isn’t particularly important for our purposes; what is important is understanding that pixels are fixed units of measurement on digital screens. A pixel on a screen is a unit of measure, like a centimeter or an inch on a ruler.

The problem with pixel sizing in responsive web design is that a fixed size doesn’t lend itself well to scaling. Once it’s set, it’s set. The elements set with pixels can have their sizes adjusted, but this requires changing everything on the screen. To effectively build a responsive site, you need to set sizes relative to something, and this is where percentages come into play.

Percentages work in CSS as you might expect: an element occupies a percentage of some space. That percentage of space is determined by the parent element. If a parent element is 1,000 pixels wide, and inside it are two elements, one of which is 20% wide and the other 80% wide, the element that’s 20% wide will be rendered as 200 pixels wide and the one that’s 80% wide will be rendered at 800 pixels wide. The total adds up to the 1,000-pixel-wide parent element (see figure 5.1).

Figure 5.1. Widths represented in percentages

If figure 5.1 was represented in code, it might look like this (it’s included in the 5.3 directory of this chapter’s source code):

<div class="parent">

<div class="twenty-percent">

</div>

<div class="eighty-percent">

</div>

</div>

<style "type=text/css">

.parent{

width:1000px;

height:20px;

outline:1px solid green;

}

.twenty-percent{

width:20%;

height:20px;

float:left;

background:red;

}

.eighty-percent{

width:80%;

height:20px;

float:left;

background:blue;

}

</style>

This code produces a 20-pixel-tall line:

When you scale this down in size, it can retain the same proportions. The layout remains “fluid” because it’s relative to a fixed point on the page, in this case the parent (.parent) element. By using percentages, you’ve detached the layout from a fixed pixel width that’s only useful in a single situation.

You can see this by changing the percentages to pixels in the example. Let’s change the previous rules as follows:

.twenty-percent{

width:200px;

height:20px;

float:left;

background:red;

}

.eighty-percent{

width:800px;

height:20px;

float:left;

background:blue;

}

This code still creates this line (available in the 5.1 directory this chapter’s source code):

The image is thicker because the line is a strict 1,000 px, but the width of the red and blue lines is the same. But watch what happens if you shrink the .parent element to 800 pixels wide:

.parent{

width:800px;

height:20px;

outline:1px solid green;

}

The layout is now broken (available in the 5.2 directory):

The 800-pixel-wide element is too big to be in line with the 200-pixel element, and it has moved to a second line. But if you change the 200px and 800px back to percentages, you’ll get a different result entirely:

.twenty-percent{

width:20%;

height:20px;

float:left;

background:red;

}

.eighty-percent{

width:80%;

height:20px;

float:left;

background:blue;

}

The line is now back in place, except it’s 800 pixels wide instead of 1,000 pixels, because the two objects have kept their widths relative to their shared parent (viewable in the 5.3 source code):

At this point, you might say, “but there’s still a fixed pixel size—the .parent element!” You’d be right, but this is just an example. In practice, that .parent element could be the browser’s viewport. The point here is that you should keep everything relative, flexible, and fluid. Just as liquids fill the space they’re given, so do fluid layouts.

Developer insight: what about height?

If you’re paying attention, you might have noticed that I’ve been using fluid widths, but even in the examples here I used a pixel height. I set the height so the elements are visible, but fixed heights can often be troublesome; if their inner elements have a greater height, they can overlap the fixed-height element.

One way of overcoming this problem is to let the child elements determine their own height automatically. For example, if you need to set a height that’s relative to the width of an element, such as to maintain aspect ratio, an effective way is to set the height to 0, and then use padding-bottom to set the proper percentage. This is because padding is set relative to the width of the parent element, just like width, and that also applies to padding on the top and bottom. Most browsers will still display the content if it’s contained in the padding of an element.

We’ll implement this technique (box sizing) in the following section.

5.1.2. Box sizing

Maintaining margins and padding is one of the things that makes responsive design very difficult. Say you have the previous 20% and 80% example, and you want to put some margin between the two elements. This would be easy if you had nice round numbers for your margin, like 1% or 2%. In a perfect world, you could just draw the 20%-wide box as 19%, add a margin-left of 1%, and be done with it.

Unfortunately this is rarely the case. In the real world, you’ll find yourself searching for percentages that aren’t that rounded. You could end up trying to use a margin-left of 1.5436%. You could easily do some math, subtract the padding from width, and adjust. But this becomes a real burden when you need padding-left and padding-right. Then you’ll find that the padding needs some tweaking, and you’ll have to change things over and over.

Fortunately, there’s a better way. CSS3 introduced a property in CSS called box-sizing, and this property is used to alter the CSS box model. The typical box model width is determined by a simple sum, like this (where width is the width specified in the element):

padding-left + border-left + width + padding-right + border-right = total width

The initial value of box-sizing is content-box, and it implements the classic box-model equation above. By setting box-sizing: border-box, the width of an element is determined like this (where rendered width is the width specified in the element):

width = rendered width

Figure 5.2 shows this another way: two elements with the same defined width, left and right padding, and left and right borders but with different box-sizing. Even though both elements have the same width, the first box occupies more space because it’s rendered with box-sizing: content-box, which, as you saw previously, is the sum of the specified width plus left and right borders and left and right padding. The box at the bottom is rendered with content-box: border-box. The rendered width of the box will be the specified width; the left and right padding and border space will be subtracted from the content space.

Figure 5.2. Two elements with the same width, padding, and borders but with different box sizing. The gray areas are the padding, and the black lines are the borders.

Let’s create a working example that illustrates the box-sizing concept. Here’s a simple grid of four 25% width elements, illustrated in figure 5.3 and viewable in the 5.4 directory of the source code:

Figure 5.3. A simple grid

Everything is going just fine, but let’s put some padding between these elements:

Now, in figure 5.4, all of our spacing is off. Our grid is broken, but by changing the box-sizing property, we can change how the elements’ widths and heights are calculated. By adding the following rule, you can set all the elements to use the border-box box-sizing model, as seen infigure 5.5:

Figure 5.4. A broken grid. Applying box-sizing will fix this. (This is included in the 5.5 directory in the chapter 5 source code.)

Figure 5.5. Now with box-sizing added. You can view this in the 5.5.1 directory in the chapter 5 source code.

Now you can change your padding to be whatever you want without affecting your grid! This will make building responsive sites dramatically easier by ensuring that sizing is predictable.

Browser support

One concern with box-sizing might be browser support. Fortunately, box-sizing works in all modern browsers and Internet Explorer starting with IE8. Unfortunately, there’s no fallback for IE7 and under, so if supporting IE7 and lower is a priority, you might be better off avoidingbox-sizing altogether.

5.1.3. Fluid grid systems

Now that you know how fluid layouts work in a purely structural sense, let’s talk about grid systems. Around the time that “Web 2.0” became a thing, web designers switched from using table-based layouts to div-based layouts, which created the need for a div-based grid system, such as the hugely popular 960 grid system, found at http://www.960.gs. The grid system was popularized as a method for applying vertical structure to a webpage. It arranged the site into columns to give more sense to the structure of the content.

Because of the predictable nature of screen sizes at the time, layout grids were set at a standard size, like 1,024 pixels wide. Now this predictability has vanished, and an alternative approach is required. Now we need a fluid grid system.

Out of the box grids

Many frameworks include grid systems out of the box. Bootstrap (http://getbootstrap.com/) and Foundation both include their own unique grids, but they’re similar enough that when you’re picking a front-end framework, the included grid systems shouldn’t be a deciding factor.

There are dozens of other self-contained grid systems, such as Skeleton and The Golden Grid system. These too amount to a matter of taste and are nearly identical. I refrain from using the out of the box grids most of the time, simply because in production you’ll likely only ever use a small number of their features, and generally you’ll require a custom grid system with sizes that reflect the needs of the site. If a grid does its job, it should be consistent throughout the site, so it’s better to base the grid on the design and maintain that grid’s consistency.

Building a grid

In order to show how a basic grid system works, we’ll build a grid rather than use an out of the box fluid grid. We’ll build a single “row” class to define a grouping of grid pieces, a “grid” class to define a grid piece, and a few classes for the number of columns each grid should occupy.

First you need to identify how many columns you want each row to contain. For the sake of simplicity, we’ll start with an eight-column grid for the desktop and a four-column grid for mobile, as seen in figure 5.6.

Figure 5.6. Desktop and mobile grids. It’s important that the number of columns in the desktop grid be divisible by the number of columns in the mobile grid, so that the rows contain an even number of columns and the grid structure is retained.

To create an eight-column grid, we’ll start with some boilerplate HTML and simple CSS. We’ll make an eight-column row that breaks into four columns for mobile. We’ll set the sizing against the grid elements as opposed to the row itself (which is a popular method in some “out of the box” grids). This gives us the flexibility to adjust the grid elements within the row.

Here’s the HTML:

<div class="row">

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

<div class="grid m-grid-1 d-grid-1">

</div>

</div>

And here’s the CSS:

In figure 5.7 we have the beginnings of a custom fluid grid system. The elements here represent one row with eight columns inside; the blue and red border is to visualize the space that the columns will take. The classes prefixed with m- are for the mobile grid, and the classes prefixed withd- are for the desktop grid. Each object has its width applied by its m- or d- class.

Figure 5.7. The start of a simple grid system with mobile and desktop views. You can view it in the 5.6 directory within the chapter 5 source code.

You can expand this grid system by adding more grid-sizing classes. (The grid created by the code can be viewed in the 5.7 directory within the chapter 5 source code.)

With these new rules, you now can build layouts with a bare-bones grid system. You can adjust it to fit your needs, but this should give you the underlying basis for building something more robust. The CSS class name for each column would be like this: X-grid-Y. X is replaced with either mfor mobile or d for desktop; Y is a number from 1 through 8 representing the number of columns. You could potentially break this down further by adding a t- prefix for tablets and a second breakpoint.

This sort of fluid grid is helpful in creating a basic fluid layout, but let’s dig into some trickier components.

5.2. Building a fluid layout

With the basics out of the way, it’s time for us to dig in and build a layout. In this section we’ll build a fluid, responsive header for our site that adapts to a fixed width in the desktop size. We’ll build parts of the page that refactor themselves as they change viewports.

5.2.1. Interpreting the prototype

If we were pressed for time, we could develop straight from our prototype in chapter 1, but we aren’t, so we’ll break the prototype into pieces so we can identify all the parts, and then combine them into a whole. Building a layout out of a prototype is simply a matter of trying to find efficiencies and applying the design to the code you have.

Given that one prototype can be wildly different from the next, there’s no set way to interpret a prototype. I can, however, give you a few tips to make it easier:

· A prototype is for communicating ideas—nothing in the prototype form is final. Remember this when you’re interpreting what’s in a prototype.

· Identify groupings of objects on the page to identify major layout components. This will help you determine the templates you need and identify the layout options you need to accommodate.

· The design elements in the prototype should serve to inform the typography and user interface. It’s helpful to write the code for these layout elements and typographical design before you build the actual page. This can serve as a style guide for the site and encourage consistency between all the pages.

After you’ve identified your first layout elements, it’s time to start coding. For our example site, we’ll start with a header.

5.2.2. Starting coding

Browsers parse HTML first to determine DOM structure, so it’s important to keep your markup as tidy as possible while writing code that’s maintainable. Your markup is going to be interpreted by browsers as well as people, and a good front end should appeal to the interests of both. Dissecting how browsers work is too big a topic to cover here, but any time you spend reading up on the inner workings of web browsers will be time well spent.

Designer insight: inside the browser

Learning how browsers render web pages can be especially challenging for designers who don’t spend time writing code and seeing how HTML and CSS interact. To learn more on the subject, take a look at Rob Crowther’s great book, Hello! HTML5 & CSS3 (Manning, 2012).

Another good resource on the subject is the 2011 article by Tali Garsiel and Paul Irish, “How Browsers Work: Behind the scenes of modern web browsers” (http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/), which is a revision of a previous publication by Garsiel.

Figure 5.8 shows what the header (with two placeholder red squares for buttons and the grey placeholder center block for a logo) will look like after we’ve written the markup and added CSS.

Figure 5.8. The header, with two buttons represented by red squares and a grey logo placeholder in the center, after we’ve written the markup and added CSS

Let’s write some markup for the required elements to render figure 5.8 (code samples for this section can be found in the 5.8 directory of this chapter’s source code). We’ll need two text content areas: one for some supplemental information and one for navigation. In the markup, we also want the site to retain the same basic structure as the viewport expands.

The markup for this section is pretty straightforward. We’ve taken the substance of the prototype and added some content and design to improve communication and ease of use. Now we need to add some CSS for layout.

Developer insight: layout versus style

CSS is used to add both styles and positioning to page elements. In this workflow, we want to handle those two tasks separately because we’re using two deliverables to articulate our ideas. The prototype is for layout, and the style guide is for style. This way we can create the layout with input from user experience (UX) designers, and the style with input from art directors, without the two disciplines offering conflicting feedback.

In our CSS, the two concerns can be combined in the same file, but a distinction in class naming will provide better structure to the overall CSS.

We want to hide the off-canvas navigation first, as we did in chapter 4, and make the interface elements visible. To see this in detail, check out index.html and style.css in the 5.8 directory of this chapter’s code.

With these pieces in place, we need to add a little jQuery code to make the layout move around.

5.2.3. Animating the off-canvas elements

Now we’re going to add classes to the body tag on the page to communicate page states. In figure 5.9 you can see the off-canvas navigation expanded.

Figure 5.9. The left offcanvas element expanded

In order to implement the off-canvas navigation, we have to toggle between CSS classes that will define the positioning of the wrapper (.wrapper). We’ll do this with a touch of jQuery. For each of the buttons (infoTray and navTray), we’re going to define a click function that will toggle the respective CSS class in the body of the page. By adding this class to the body, we can affect multiple elements on the page simultaneously without having to add multiple classes. This will reflect interface state page-wide:

$("#infoTray").click(function(){

$("body").toggleClass("info-active");

});

$("#navTray").click(function(){

$("body").toggleClass("nav-active");

});

Next, we need some CSS to support our states:

.info-active .wrapper{left:50%;}

.nav-active .wrapper{right:50%;}

We now have a simple off-canvas design pattern. Because we’re focusing on layout styles, it’s going to look completely unstyled, but the base is there, and we can start adding design elements. The source code for this is found in the 5.8 directory of the chapter’s source code.

With this header in place, let’s make this element responsive. We’re going to do this for each element, so we can focus on one element at a time while we step through the page width and make each modular element on the page function appropriately.

5.2.4. Making the element responsive

In responsive web design, a site is only complete when it will work for a range of site widths (you will want to focus on the widths that are used by the devices that have the largest audiences, because each breakpoint that you customize will required time and resources). We have a nice starting point for our website, but now we need to expand it for wider views, or we’ll just have a gigantic mobile website.

Adding media queries to make the header responsive

When you’re building a responsive site, you need to use the same HTML elements on the page to create different layouts for different screen sizes. You want to have a single HTML base and very few hidden objects on the pages. You want to avoid the trap of toggling between HTML elements at assigned breakpoints simply because a particular device has a certain viewport. New devices with new resolutions are coming out all the time, so your goal should be to make something fluid that doesn’t depend on a few set viewports.

In our example design, our first breakpoint is at about 720 pixels. This is a good breakpoint, because although the elements still seem to work well at this size, there’s some open space to play in. At our first breakpoint, we need to consider the amount of space we now have and take advantage of it according to our site’s priorities. Because the content on the left is supplemental and the content to the right is site navigation, leading users to different top-level sections of the website, the content to the right takes priority.

Developer insight: tracking viewport with console.log

One thing that makes my life much easier is logging the current viewport width to the browser console. This gives me an absolute number to base my media queries on.

To log the viewport width, call console.log(document.body.clientWidth); in JavaScript.

Also, major browser vendors provide developer tools, which makes life easier. For example, if you open the settings in the Chrome developer console, you can dock the tools to the right. The browser will retain its viewport width, minus the size of the inspector tools, so you can preview a mobile site and have a large console at the same time.

What we want to do is open up some of the space on the right to give us room for navigation. To do this, we can move the logo left and then add the site navigation links to the right side of the header. We also need to hide the navigation button on the right, since we won’t be using it. The following code does this at a breakpoint for 720 pixels:

With a few minimal tweaks, we’ve changed the layout of the page completely (see figure 5.10).

Figure 5.10. Our updated layout

Our breakpoint is a success. Without changing our markup at all, we’ve adapted our header’s layout to fit its new context. But although the right navigation looks great, our left-side elements are now a little off. There’s an issue with the left-side navigation in an expanded state. The revised layout is shown in figure 5.11.

Figure 5.11. Our expanded information panel at the left of the page looks out of place in the larger viewport.

In this larger context, the content within the off-canvas navigation doesn’t seem to justify its screen real estate. Let’s change the way this button works, while keeping its core as intact as possible.

The easiest way to do this is to change the CSS, and the most elegant way is not to change how the navigation functions, but to change where the interaction takes place. Instead of hiding the off-canvas elements to the left, let’s move them to the top and pull them down into the user’s view.

We now have a header in place, with a single breakpoint at 720 pixels, as seen in figure 5.12. From here we can start expanding our page for larger screens. This is going to mean adjusting not just the positioning, but also some of the logic behind our elements.

Figure 5.12. Our navigation now drops down from the top.

5.2.5. Expanding into the wider views

When going from tablet to desktop, you can start opening up your layout a bit. You have room to move your elements around a little more. In our case, we want to keep things mostly the same but increase the sizes a little.

The easiest way to set this is with a max-width rule on the .wrapper class. Because everything within the wrapper is percentage-based, the site should retain its structure. We’ll add the following rules to .wrapper in the style.css file:

max-width: 1024px;

margin:0 auto;

Our site will now be framed in a 1,024-pixel-wide wrapper (see figure 5.13). In this breakpoint, you can see the header in its inactive state, with the supplemental material hidden.

Figure 5.13. Our framed site header

Our header now has a lot of empty whitespace, which is okay for the most part. Once we get into designing the page, we’ll be glad we have that extra space, because it’ll give us more space to expand creatively.

One thing we can do now in the layout phase is increase the size of the logo and decrease the size of the information button, as shown in figure 5.14.

Figure 5.14. A smaller information button

With this new layout, our site functions nicely in a desktop browser. We’ve created a header module that reacts responsively, both in its interaction and in its layout. We’ve used few fixed-width elements, instead relying entirely on percentages, giving us a nice degree of fluidity for small and mid-sized screens.

5.3. Summary

In this chapter we covered the core fundamentals of building a responsive layout. You learned the basics of using percentages to create a fluid layout. We also discussed how fluid layouts differ from pixel-based layouts, and how they can be changed with media queries.

We touched on the use of box-sizing to affect how the box model renders on a page and what its benefits and drawbacks are. We also discussed fluid grid systems, building off-canvas navigation, and hiding content off the page.

We covered a lot of ground in this chapter, but with this bit out of the way, we’re ready to proceed and start building responsive layouts. In the following chapters, we’ll build on what you’ve learned and go into more details.

5.4. Discussion points

· In creating a responsive web site, what are some of the common pain points in establishing a grid system for a design?

· When building a site, what information do you need to have early on to create a more effective grid system?

· When considering a user’s experience on the site, what do you use to communicate interface elements effectively?

· In building a responsive site, what unique elements need specific consideration from designers? If a button is used on both mobile views and desktop views, how does that affect how it’s developed?