Device-Agnostic Design

Responsive Web Design


Learning Objectives

  • You know the terms responsive web design and adaptive design.
  • You know of techniques used in responsive web design.

The term Responsive Web Design was coined by Ethan Marcotte, who outlined a set of techniques that allow web pages to adapt to the available screen size and orientation. The goal of responsive web design is to provide a good user experience regardless of the device used to access the site. This has been mainly done by utilizing Cascading Style Sheets (CSS) techniques to create flexible content.

Here, it is also worthwhile to mention adaptive web design. Adaptive web design promotes creating multiple fixed versions of a layout, each specifically tailored for specific screen sizes. While in the past it has been the way to go e.g. in the context of mobile phones and mobile applications, responsive web design has mostly surpassed adaptive web design.

Here, we are looking into responsive web design as a design approach, as well as into HTML and CSS as implementation techniques for responsive web design.

Media queries

Media queries provide the possibility to ask for details about features of the device displaying the content, and to apply styles depending on the features of the device. Media queries are built with set of media features and logical operators not, only and and. The most common features are: width, height, orientation, aspect-ratio, color and resolution (which is actually pixel density), where some of the features include a minimum (min) and maximum (max) values.

For a comprehensive list of media features, see MDX Web Docs on Using media queries.

As an example, the following styling dictates that by default, the background color of a page is white, and if the width of the viewport is smaller than 500px, the background color of the page should be light gray. Finally, if the width of the viewport is smaller than 300px, the content should not be shown at all.

If you click the “View in browser” text, you can see what the content would look like, and can also adjust the width of the browser window to see how the content changes.


Loading Exercise...

Relative sizes

With responsive web design, the key idea is that all content, including fonts and image sizes, can be contextually resized to fit the given space. Instead of using actual pixel sizes for defining the element sizes, the sizes are defined or scaled using percentages or relative units (mostly) with the available viewport properties.

When defining the size of elements, the following operators are the most commonly used:

  • em — size relative to its parent element (nested hierarchy)
  • rem — size relative to the root element (HTML tag)
  • vw — size relative to the viewport width
  • vh — size relative to the viewport height
  • % — size relative to the parent element

In general, the calculation is always done in the form target / context = result.

When considering fonts, the most common default font size in browsers is 16 pixels (px). In terms of em, this would make 1em = 16px, while 2em = 32px, 3em = 48px, and so on. As em definitions are inherited from their parent elements and most markup languages are — well — a spaghetti of embedded hierarchies, the rem is convenient when one looks to refer back to the original scaling defined in the top most MTHL header (or in the browser).

In practice, we could set the font size of the body of a document to be 2em, and then create two separate stylings, where one of them has 1.5em as size, while the other has 1.5rem as size. When these are used within an element that resides within the body, the relative difference is visible.

In the content below, the text Hello em is in an element that uses the style with the identifier em, while the text Hello rem is in an element that uses the style with the identifier rem.

While em and rem are primarily used for font sizing (in addition to px), %, vw, and vh are mostly used for margins, padding, spacing, and widths/heights. The following example provides another example, where a level 1 heading element is styled with 1.5em font size, and div elements are styled with 40% width. The div elements are also styled with 60vh height, which is a shorthand for 60% of the viewport height.


Loading Exercise...

Flexible images

Relative sizes are also used to make images and other media flexible. In the following example, the width of an image is set to 50% of the viewport’s width, leading to the image scaling up and down as the width of the viewport changes.

#image {
  width: 50vw;
}

Furthermore, when considering the format of the image, one would ideally use vector graphics whenever possible to ensure that the image scales up and down without losing quality. Note that vector graphics are not always the best choice as, for example, a vector graphic of a picture would either take very large amounts of space or it would not be able to capture the details of the image. For pictures, it is better to use a raster image, such as a JPEG or PNG.

Flexible layouts

Flexible layouts are used to define layouts that adjust based on the screen size. Controlling the order and flow of elements is done primarily with three approaches: float, flexbox and grid.

Floats

The CSS float property is used to define how an element should be positioned on a page. It can be used to make an element float on the side, allowing the content on the page to wrap around it. The following example demonstrates the use of the float property to make an element float to the left.

Flexbox

Flexbox is used to define how children of an element should be positioned. Flexbox is taken into use through the display style flex, and by defining the styles for the child elements.

The following style defines a container that has its children positioned in a row, and that wraps the children to the next row if there is not enough space for them in the current row. The children are given a width of 150 pixels, and the children are given a margin of 1 em on all sides. The children are also given a border radius of 0.33 em, and a background color of rgb(207, 232, 220).

Note that when you adjust the width of the screen, you’ll notice that the children of the container are repositioned to fit the width of the screen. This is because the children are given a width of 200 pixels, and the container is set to wrap the children to the next row if there is not enough space for them in the current row.

Grids

Grids are used to create grids of elements. They are used by setting the display value grid to a container, and potentially also outlining the number of rows and columns that the grid should have. The following example demonstrates the use of a grid to create a three-column layout, where the leftmost column would have a width of 125 pixels, the middle column would have the width of 250 pixels, and the rightmost column would have the width of 175 pixels. Items in the grid have a margin of 1 em on all sides, a border radius of 0.33 em, and a background color of rgb(207, 232, 220).

Note that as you resize the screen, the above layout will not change. This is because the grid is defined to have three columns, and the width of the columns is fixed.

Responsive grids are defined with the fr unit, which refers to a fractional unit. One fr, i.e. 1fr, refers t one part of the available space. The following example demonstrates the use of the fr unit to define the width of the columns. The leftmost column would have a width of 2 times the width of the middle column, and the rightmost column would have a width of 1 times the width of the middle column. The items in the grid have a margin of 1 em on all sides, a border radius of 0.33 em, and a background color of rgb(207, 232, 220).


Loading Exercise...

Breakpoints

When we consider the challenges and solutions to device-agnostic design, one of the approaches for prioritization was mobile first, which means that the design would be first optimized for mobile devices, after which the design would be adapted for larger screens.

With media queries, this would be achieved with breakpoints, which refer to the points (e.g. widths) where the layout changes. In effect, we could first create a breakpoint for mobile devices, and then continue by creating breakpoints for larger screens.

The commonly used breakpoints have changed over time with the evolution of devices. As an example, presently, TailwindCSS has the following default breakpoints: 640px, 768px, 1024px, 1280px, and 1536px.

If you’re interested in learning more about TailwindCSS, it is briefly discussed in the course Web Software Development.

As an example, we could define a style sheet template as follows. The first breakpoint is for styles smaller than 640px, the second breakpoint is for styles between 640px and 768px, and so on.

@media (max-width: 639px) { }
@media (min-width: 640px) { }
@media (min-width: 768px) { }
@media (min-width: 1024px) { }
@media (min-width: 1280px) { }
@media (min-width: 1536px) { }

The following demonstrates the use of two breakpoints. The first breakpoint is for styles smaller than 480px, and the second breakpoint is for styles between 480px and 640px. The background color of the body is set to light gray for the first breakpoint, and light blue for the second breakpoint.

When you adjust the width of the screen, you’ll notice that the background color of the body changes to correspond to the breakpoints.


Loading Exercise...

Responsive layouts

In practice, the breakpoints and media queries are the basis for responsive layouts that adapt to match device screen sizes. As an example, below, a grid layout with one columns is used for the first breakpoint, a layout with two columns for the second breakpoint, while the third breakpoint uses three columns.


Loading Exercise...

Container queries

One of the more recent additions to CSS is container queries, which allow defining styles based on the size of the container (i.e., the element that contains the content). This is in contrast to media queries, which are used to define styles based on the size of the viewport.

Container queries are useful as they provide more control over the styling in relation to a container. Container queries are used with the @container tag, which is used in the same way as the @media tag. However, containers need to also be declared a containment context, which is used to define the container that the container query relates to (e.g. the container whose size is being adjusted to).

The following example defines a page that has a different layout depending on the size of the container. The container is defined as a grid, with three columns if the width of the container is larger than 360px, and two columns if the width of the container is smaller than 360px. Furthermore, the container is set to be a containment context (container-type: inline-size) — that is, all container queries are related to the element with the id container.

In addition, the example also defines a class .item that is used to style the items in the container. By default, the items have a margin of 0.75em and a padding of 0.75em, and the items have a light green background color. However, if the width of the container (not the item) is larger than 480px, the margin and padding are increased to 1em, and the color changes to light blue.


Loading Exercise...

Responsive layouts.. everywhere?

When you browse the internet, you might notice that not all websites are responsive. This is because creating responsive layouts can be time-consuming. However, as having a responsive layout can improve user experience, you notice that the majority — if not all — companies that try to keep users in their websites have responsive websites.