How to Create a Responsive Website Layout

Web Development Post by Christopher Spicer
Responsive Website Layout

Excellent content is what draws visitors to your website. But excellent page layout is what ensures that your visitors are able to find and engage with that content.

Let’s face it. We live in a high-speed world. You may have spent days poring over every word and every image that appears on your site. But visitors will determine in seconds whether to stay on your page or hit the back button. A decision that is made or broken in the time it takes them to glance at a few pictures or scan a few lines of text.

First impressions are critical. The presentation of your website makes an impact on visitors long before they’ve explored the depth of your content. And a good page layout is an essential element of that presentation.

So what exactly is layout? Simply stated, layout is the organizational framework that provides structure to the information presented on your page. It is the use of size, position, spacing, and contrast to define relationships between individual design elements.

Okay, so what is a good layout? Well, that is a bit more nuanced. But a good layout:

  • Structures information in a way that is logical and intuitive
  • Groups related elements and separates unrelated elements
  • Establishes a clear hierarchy that focuses attention on the most important elements first
  • Maintains consistent design elements to build a cohesive experience
  • Creates a natural flow and sense of balance between elements
  • Remains functional and aesthetic in all its variations

This article, which is the first in a series of web development tutorials, will guide you through the process of creating basic layout elements that you can use to structure your web pages in an endless variety of configurations. We'll create simple content using HTML, then use CSS to drive our page, section, and grid layouts. Step by step, we’ll transform concepts into code before ultimately combining these examples into complete web page demonstrations.

In this article we'll use our standard HTML document structure and CSS naming convention.

Skip Ahead

Looking for something specific? Select a topic in this article to read more:

Responsive Design

There was a time when the internet was a realm accessible only to computers. It was the 1990s. Cell phones were the size of small pets. America Online CDs seemed to multiply like bunnies. And across the country homes resonated with the delightful hissing and cracking of 56k modems dialing up to the web.

Fast-forward twenty years and nearly every device with a screen, from the pocket-sized to the wall-consuming, is internet-capable. And this presents a unique challenge to web developers. How do we construct page layouts that look good on all devices, from a 320-pixel-wide phone to a 3,840-pixel-wide television?

We could create unique layouts dedicated to every possible combination of screen size and resolution. But given the hundreds (perhaps thousands) of difference screen sizes and resolutions currently in use, with new configurations entering the market each year, that would seem a near-impossible task.

Fortunately there is a better option. Rather than designing multitudes of fixed layouts to fit specific devices, we instead design a single fluid layout that automatically adjusts to fit all devices.

This technique is called “responsive design”. And it allows us to create one dynamic layout that looks great at any size and any resolution. The key to developing a responsive design is the creation of a flexible layout that resizes, repositions, and even hides or shows elements based on the size and resolution of the screen.

Let’s take a look at how the same responsive layout might appear on different devices:

Responsive Website Layout as Viewed on a Phone

Phone

Responsive Website Layout as Viewed on a Tablet

Tablet

Responsive Website Layout as Viewed on a Computer

Computer

Now that we understand the basic concepts of responsive design, let’s use it to start building our layout!

Viewport

To create a responsive layout, we must first instruct web browsers exactly how to control the width and scale of our page. We do this by inserting a meta tag into the <head> of our document:

HTML

<meta name="viewport" content="width=device-width, initial-scale=1">

This tag sets the width of the page equal to the screen width of the device. It also sets the initial scale of the page so that 1 CSS pixel equals 1 device-independent pixel.

Box Sizing

To create a responsive layout, we must also instruct web browsers exactly how to control the size of the elements that appear on our page.

We do this by creating a CSS rule to specify the box sizing model used for all elements in our document:

CSS

* {box-sizing: border-box;}

This rule instructs browers to apply the "border box" model, which includes the dimensions of an element's border and padding when calculating the size of the element.

By default, browsers apply the “content box” model, which calculates the size of an element based only on its content. Because the content box model does not include the dimensions of an element's border or padding, our layout may not behave as expected.

Applying the border box model solves this problem.

At this point it is also convenient to reset the default margins, borders, and padding to 0. Now we can consciously apply these properties to specific elements where desired without being surprised by default styles that may vary from browser to browser.

We do this by adding three properties to our CSS rule:

CSS

* { margin: 0; border: 0; padding: 0; }

Mobile-First Design

In web development there is an important principle known as "mobile-first design". This principle states that responsive website layouts should be initially constructed in the small screen configuration. Our layout should then adjust to a medium or large screen configuration where required.

This approach is advantageous because small devices like smart phones are typically slower than large devices like desktop computers. If a small device first loads the large screen layout before adjusting, the slower device speed makes this transition very apparent (and rather annoying) to visitors. However, if a large device first loads the small screen layout before adjusting, the faster device speed makes this transition nearly seamless.

To that end, the CSS rules in our examples and demonstrations will first be defined in the small screen configuration. Subsequent CSS rules will then be applied to progressively change specific properties to create the medium and large screen configurations where required.

Progressive Enhancement

In web development there is another important principle known as "progressive enhancement". This principle states that the core content and functionality of our website should be fully accessible at its most basic level of presentation. Additional layers of content and functionality are then added to this core presentation as permitted by the capabilities of the visitor's device.

This approach is a reversal of the "graceful degradation" strategy, where website elements are designed for the latest technologies, then allowed to systematically fail on older platforms. Progressive enhancement is advantageous because it ensures that the critical components and features of our website are available to all visitors. Visitors with more advanced software and greater bandwidth will see a presentation that is progressively enhanced to match the capabilities of the browser and internet connection that they are using.

To that end, the core page content in our examples will be fully developed in HTML. Additional page styles will be added using CSS. And additional page functionality will be added using JavaScript. At each level of enhancement (HTML only, HTML/CSS, and HTML/CSS/JavaScript) the presentation will preserve the critical components and features of our website.

Page Layout

As we start to plan the layout of our page, it’s natural to feel compelled to fill every available pixel with text and images. After all, content is valuable and screen space is limited.

But even the best content can't draw attention entirely on its own. A good page layout needs to create a sense of contrast to bring individual design elements into focus. Without it, a composition is little more than a blurry mosaic of visual white noise that is sure to send visitors racing for the back button.

The component that most effectively creates this sense of contrast is called "whitespace". And it simply refers to the empty, or negative space between design elements. Despite the name, whitespace doesn't necessarily have to be white. So long as it's free of design elements like text and images, it can exist atop a background of any color. Though simple in concept, it is a powerful tool. Whitespace is the breath that brings content to life.

One way that we can include whitespace in our layout is by controlling the width of our page. On small and medium screens, where space is limited, we allow the page to expand to the full width of the viewport. But on large screens, where space is ample, we constrain the page so that it is narrower than the viewport. This creates a natural separator on each side of our layout that strengthens the visual impact of our content.

Controlling the width of our page allows us to optimize the line length of our text area. A number of studies have explored this topic, and it is generally accepted that 40 to 80 characters per line provides the most comfortable reading experience. Much shorter than that and readers are forced to move their eyes back and forth at an unpleasant pace. Much longer than that and readers find it difficult to transition from the end of one line to the beginning of the next.

Let’s take a look at two examples:

Unconstrained Page Width

Unconstrained Page Width

Constrained Page Width

Constrained Page Width

In the second example, do you notice how the additional whitespace around our layout places more focus on the content? And how the optimized line length makes the text more comfortable to read?

Now that we understand the basic concepts that are driving our page layout, we're ready to write the code!

Let's start with the HTML used to create our page:

HTML

<section class="page"> <h1 class="heading"> Heading 1</h1> <p class="text"> Paragraph</p> </section>

First we create our page container using the <section> element and assign it:

  • The class="page" attribute to control the width of the page container

Inside the page container we place:

  • The <h1> element to create a heading
  • The <p> element to create a paragraph of body text

Next the CSS:

CSS

.page { max-width: 640px; margin: 0 auto; } @media (min-width: 960px) { .page {max-width: 960px;} } .heading {font: bold 32px / 1.5 sans-serif;} .text {font: 16px / 1.5 sans-serif;}

First we create the .page CSS rule to control the behavior of our page container. This rule includes:

  • The max-width: 640px property to limit the maximum width of the page container to 640px
  • The margin: 0 auto property to horizontally center the page container

This layout looks pretty good on small and medium screens. But on large screens, our page container seems a bit narrow.

Let's change the behavior of our page container so that:

  • The maximum width is 640px on small and medium screens (959px and below)
  • The maximum width is 960px on large screens (960px and above)

To accomplish this, we introduce the @media CSS rule (commonly called a "media query"). This rule contains CSS properties that are applied only when the conditions of the rule are met.

In this case, the property is a maximum width of 960px applied to our page container. And the condition is that the device has a minimum width of 960px.

You’ll notice that the media query is placed after the initial page container rule. This allows the media query properties to take precedence over the initial properties (when the conditions of the rule are met).

Finally we create the .heading CSS rule to control the font size and style of our heading. And the .text CSS rule to control the font size and style of our and body text.

Section Layout

Even simple layouts are likely to contain multiple sections of content. And keeping these sections clearly defined is an important part of creating a well-structured layout.

The human eye naturally perceives elements that are positioned closely together as being more connected than elements that are positioned farther apart. This is a principle known as the "Gestalt Law of Proximity". And it's one that we can apply to our layout through the strategic use of whitespace. By decreasing the whitespace between elements, we pull them together to show that they belong to the same section. And by increasing the whitespace between elements, we push them apart to show that they belong to different sections.

Let’s take a look at two examples:

Unpadded Sections

Unpadded Sections

Padded Sections

Padded Sections

In the second example, do you notice how the additional whitespace within our layout gives more clarity to the document structure?

Now that we understand the basic concepts that are driving our section layout, we're ready to write the code!

Single-Level Sections

First we'll explore a simple document structure containing a series of top-level sections.

Let's start with the HTML used to create our single-level sections:

HTML

<section class="page section"> <h1 class="heading"> Heading 1</h1> <p class="text"> Paragraph</p> </section> <section class="page section"> <h1 class="heading"> Heading 2</h1> <p class="text"> Paragraph</p> </section> <section class="page section"> <h1 class="heading"> Heading 3</h1> <p class="text"> Paragraph</p> </section>

First we create our section containers using the <section> element and assign each:

  • The class="page section" attribute to control the width and padding of the section container

Inside each section container we place:

  • The <h1> element to create a heading
  • The <p> element to create a paragraph of body text

Next the CSS:

CSS

.section {padding: 8px;} .heading { padding: 8px; font: bold 32px / 1.5 sans-serif; } .text { padding: 8px; font: 16px / 1.5 sans-serif; }

To create the whitespace around our single-level sections, we add:

  • 8px of padding to each section
  • 8px of padding to each heading and paragraph

These values combine to produce:

  • 32px of whitespace between sections
  • 16px of whitespace between headings and paragraphs

Multiple-Level Sections

Next we'll explore a more complex document structure containing a series of top-level sections, each including a series of lower-level subsections.

Let's start with the HTML used to create our multiple-level sections:

HTML

<section class="page section-1"> <header class="section-2"> <h1 class="heading-1"> Heading 1</h1> <p class="text"> Paragraph</p> </header> <section class="section-2"> <h2 class="heading-2"> Heading 1-1</h2> <p class="text"> Paragraph</p> </section> <section class="section-2"> <h2 class="heading-2"> Heading 1-2</h2> <p class="text"> Paragraph</p> </section> </section> <section class="page section-1"> <header class="section-2"> <h1 class="heading-1"> Heading 2</h1> <p class="text"> Paragraph</p> </header> <section class="section-2"> <h2 class="heading-2"> Heading 2-1</h2> <p class="text"> Paragraph</p> </section> <section class="section-2"> <h2 class="heading-2"> Heading 2-2</h2> <p class="text"> Paragraph</p> </section> </section>

First we create our section containers using the <section> element and assign each:

  • The class="page section-1" attribute to control the width and padding of the section container

The first item inside each section container is the header container. We create these items using the <header> element and assign each:

  • The class="section-2" attribute to control the padding of the header container

Inside each header container we place:

  • The <h1> element to create a first-level section heading
  • The <p> element to create a paragraph of body text

The remaining items inside each section container are the subsection containers. We create these items using the <section> element and assign each:

  • The class="section-2" attribute to control the padding of the subsection container

Inside each subsection container we place:

  • The <h2> element to create a second-level subsection heading
  • The <p> element to create a paragraph of body text

Next the CSS:

CSS

.section-1 {padding: 16px 0;} .section-2 {padding: 8px;} .heading-1 { padding: 8px; font: bold 32px / 1.5 sans-serif; } .heading-2 { padding: 8px; font: bold 24px / 1.5 sans-serif; } .text { padding: 8px; font: 16px / 1.5 sans-serif; }

To create the whitespace around our multiple-level sections, we add:

  • 16px of vertical padding to each section
  • 8px of padding to each subsection
  • 8px of padding to each heading and paragraph

These values combine to produce:

  • 64px of whitespace between sections
  • 32px of whitespace between subsections
  • 16px of whitespace between headings and paragraphs

And this process is highly scalable. In theory, you can continue to add vertical padding to nest as many section levels as you wish. In practice, however, it's recommended not to nest more than three section levels, as an excessively complex hierarchy may be confusing to the reader.

Grid Layout

So far we've composed our page layout with a purely vertical flow. But our design can (and in many cases should) include horizontal flow as well.

To create a layout that allows us to build in both directions, we subdivide our page into rows and columns that collectively form a system known as a “grid”. Using these rows and columns as a framework we can arrange blocks of content in an endless number of ways.

By its nature, a grid is both versatile and modular. It provides the creative freedom to alter the balance and flow of a page with great flexibility, while simultaneously maintaining a sense of consistent structure and purposeful design.

Let's take a look at the components that make up a grid:

Anatomy of a Grid

Anatomy of a Grid

  • Margins are the negative spaces around the content area
  • Gutters are the negative spaces between columns
  • Flowlines are the lines created by horizontally subdividing the content area
  • Columns are the areas created by vertically subdividing the content area
  • Modules are the blocks of content created by the intersections of flowlines and columns

In this tutorial we'll construct our grid using the CSS Flexible Box Module (commonly called “flexbox”), a purpose-built tool designed specifically for page layout. Before this tool was introduced, web developers were forced to use tables or floated elements to compose complex layouts. However, neither technique was ever intended to be used in this way, and both are limited in their capabilities.

When it comes to page layout, flexbox is the best tool for the job.

Now that we understand the basic concepts that are driving our grid layout, we're ready to write the code!

Grid Container

The first grid component that we construct is the container that will bound our modules.

Let's start with the CSS used to create our grid container:

CSS

.grid { display: flex; flex-flow: row wrap; justify-content: flex-start; }

This rule includes:

  • The display: flex property to apply flexbox behavior
  • The flex-flow: row wrap property to set the main axis of flow in the horizontal direction, and to allow flexible elements to continue from one line to the next
  • The justify-content: flex-start property to align flexible elements to the left

Let's expand this to create independent grid containers for left-aligned, right-aligned, and center-aligned layouts:

CSS

.grid-left { display: flex; flex-flow: row wrap; justify-content: flex-start; } .grid-right { display: flex; flex-flow: row wrap; justify-content: flex-end; } .grid-center { display: flex; flex-flow: row wrap; justify-content: center; }

Fixed Grid Modules

Now that we've constructed the container for our grid, let's construct the modules that we'll use to arrange our content.

We know that the space within a grid is subdivided into columns And we know that modules are able to span any number of these columns. But exactly how many columns should we choose?

As the designers, it's entirely up to us to select the number of columns that works best for our layout. Throughout the web, two, three, four, and six-column grids are all quite common. However, it is perhaps the twelve-column grid that is most widely used. This configuration is particularly versatile because it not only supports twelve-column layouts, but two, three, four, and six-column layouts as well.

Take a look at the complete set of module widths available in a twelve-column-grid:

Column Span Module Width
1 Column 8.33%
2 Columns 16.66%
3 Columns 25%
4 Columns 33.33%
5 Columns 41.66%
6 Columns 50%
7 Columns 58.33%
8 Columns 66.66%
9 Columns 75%
10 Columns 83.33%
11 Columns 91.66%
12 Columns 100%

You'll notice that we've intentionally rounded down the percentage values. The reason is that rounding up would, in some cases, produce modules that are slightly too wide to fit the grid.

For you perfectionists out there (and I count myself among you), feel free to use as many decimal places as you like. But there’s no need to get carried away. Even on large screens, two or three decimal places is enough to provide sub-1-pixel accuracy.

Let's start with the CSS used to create our fixed grid modules:

CSS

.grid_mod-1 { flex: 0 0 auto; width: 8.33%; } .grid_mod-2 { flex: 0 0 auto; width: 16.66%; } .grid_mod-3 { flex: 0 0 auto; width: 25%; } ... .grid_mod-12 { flex: 0 0 auto; width: 100%; }

To fully support our fixed layout, we need to create a CSS rule for each of the twelve available grid module widths:

  • .grid_mod-1 creates a grid module that spans 1 column (8.33% wide)
  • .grid_mod-2 creates a grid module that spans 2 columns (16.66% wide)
  • .grid_mod-3 creates a grid module that spans 3 columns (25% wide)
  • ...
  • .grid_mod-12 creates a grid module that spans 12 columns (100% wide)

Each rule includes:

  • The flex: 0 0 auto property to specify that the grid module does not grow or shrink
  • The width property to specify the width of the grid module

Next the HTML:

HTML

<div class="page grid"> <section class="section grid_mod-4"> <h1 class="heading"> Heading 1</h1> <p class="text"> Paragraph</p> </section> <section class="section grid_mod-4"> <h1 class="heading"> Heading 2</h1> <p class="text"> Paragraph</p> </section> <section class="section grid_mod-4"> <h1 class="heading"> Heading 3</h1> <p class="text"> Paragraph</p> </section> </div>

First we create our grid container using the <div> element and assign it:

  • The class="page grid" attribute to control the width and behavior of the grid container

Inside the grid container we place our grid modules. We create these items using the <section> element and assign each:

  • The class="section grid_mod-4" attribute to control the padding and width of the grid modules (33.33% wide on all screens)

Inside each grid module we place:

  • The <h1> element to create a heading
  • The <p> element to create a paragraph of body text

Fluid Grid Modules

So far we've constructed our grid with fixed module widths. But we can take this system one step further by including fluid module widths that change based on the size of the screen.

This allows us to design a responsive grid that reconfigures modules to optimize the layout for different devices. For example, we can begin with a one-column layout, which looks great on small screens, and allow it to progressively expand to a two-column layout on medium screens, and a three-column layout on large screens. Remember how we used the media query rule to control the width of our page? We can use the same technique to control the widths of our grid modules.

The first step in this process is setting the breakpoints – specific screen sizes where control of our layout is handed from one media query rule to another. But exactly how do we know where to set these breakpoints?

As the designers, it's entirely up to us to select the screen sizes where our layout should change. You'll recall that a basic principle of responsive design is to create a layout that looks great not only on specific devices at specific sizes, but on all devices at all sizes. With that in mind, it is purely the scalability of our layout, and not the size of particular devices, that we consider when setting these controls.

Take a look at the breakpoints that we'll be using in our examples and demonstrations:

Device Size Viewport Width
Small 479px and Below
Medium 480px to 959px
Large 960px and Above

Let's start with the CSS used to create our fluid grid modules:

CSS

/* Small Devices */ @media (max-width: 479px) { .grid_mod-sm-1 { flex: 0 0 auto; width: 8.33%; } .grid_mod-sm-2 { flex: 0 0 auto; width: 16.66%; } .grid_mod-sm-3 { flex: 0 0 auto; width: 25%; } ... .grid_mod-sm-12 { flex: 0 0 auto; width: 100%; } } /* Medium Devices */ @media (min-width: 480px) and (max-width: 959px) { .grid_mod-md-1 { flex: 0 0 auto; width: 8.33%; } .grid_mod-md-2 { flex: 0 0 auto; width: 16.66%; } .grid_mod-md-3 { flex: 0 0 auto; width: 25%; } ... .grid_mod-md-12 { flex: 0 0 auto; width: 100%; } } /* Large Devices */ @media (min-width: 960px) { .grid_mod-lg-1 { flex: 0 0 auto; width: 8.33%; } .grid_mod-lg-2 { flex: 0 0 auto; width: 16.66%; } .grid_mod-lg-3 { flex: 0 0 auto; width: 25%; } ... .grid_mod-lg-12 { flex: 0 0 auto; width: 100%; } }

To fully support our fluid layout, we need to create a set of CSS rules for each of the three screen size ranges:

  • .grid_mod-sm-* defines grid module properties for small screens (479px and below)
  • .grid_mod-md-* defines grid module properties for medium screens (480px to 959px)
  • .grid_mod-lg-* defines grid module properties for large screens (960px and above)

For each screen size range, we also need to create a set of CSS rules for each of the twelve available grid module widths:

  • .grid_mod-*-1 creates a grid module that spans 1 column (8.33% wide)
  • .grid_mod-*-2 creates a grid module that spans 2 columns (16.66% wide)
  • .grid_mod-*-3 creates a grid module that spans 3 columns (25% wide)
  • ...
  • .grid_mod-*-12 creates a grid module that spans 12 columns (100% wide)

Each rule includes:

  • The flex: 0 0 auto property to specify that the grid module does not grow or shrink
  • The width property to specify the width of the grid module

Next the HTML:

HTML

<div class="page grid"> <section class="section grid_mod-sm-12 grid_mod-md-6 grid_mod-lg-4"> <h1 class="heading"> Heading 1</h1> <p class="text"> Paragraph</p> </section> <section class="section grid_mod-sm-12 grid_mod-md-6 grid_mod-lg-4"> <h1 class="heading"> Heading 2</h1> <p class="text"> Paragraph</p> </section> <section class="section grid_mod-sm-12 grid_mod-md-6 grid_mod-lg-4"> <h1 class="heading"> Heading 3</h1> <p class="text"> Paragraph</p> </section> </div>

First we create our grid container using the <div> element and assign it:

  • The class="page grid" attribute to control the width and behavior of the grid container

Inside the grid container we place our grid modules. We create these items using the <section> element and assign each:

  • The class="section grid_mod-sm-12 grid_mod-md-6 grid_mod-lg-4" attribute to control the padding and width of the grid modules (100% wide on small screens, 50% wide on medium screens, and 33.33% wide on large screens)

Inside each grid module we place:

  • The <h1> element to create a heading
  • The <p> element to create a paragraph of body text

And there you have it! A three-column grid layout that scales responsively to fit screens of all sizes. But there’s no need to stop there. You can experiment with different combinations of module widths and quantities to achieve any design that you like!

Putting it All Together

We've covered a lot of topics in this article - responsive design, mobile-first design, progressive enhancement, page layout, section layout, and grid layout. So far we've explored these concepts individually. But now it's time to combine them into complete web pages.

Below are six demonstrations to illustrate how this is done.

To see it in action, open the demonstration in a new window. View the source code in your web browser to see how the page is constructed.

To customize the demonstration, first save a local copy of the document on your computer. Then open the file in your text editor to add, remove, and modify code to create your own web design masterpiece.

Demo 1

Sample “Home” page with a one and three-column layout:

See Demo

Demo 2

Sample “About” page with a one, two, and three-column layout:

See Demo

Demo 3

Sample “Product” page with a one, two, three, and four-column layout:

See Demo

Demo 4

Sample “Service” page with a one and three-column layout:

See Demo

Demo 5

Sample “Portfolio” page with a one and three-column layout:

See Demo

Demo 6

Sample “Blog” page with a one and three-column layout:

See Demo