Back to Blog

Responsive Web Design Basics

Responsive web design is a term that refers to the design of websites that will render appropriately across a range of device sizes. Modern websites are viewed on everything from mobile phones to ultra-wide monitors, and it is important to build some responsiveness into the design to ensure that visitors have an acceptable experience. Most responsiveness will be achieved using modern CSS techniques that can make large improvements with very little effort. This article will list several techniques that can be used to make your websites responsive.


Media Queries

Media queries are CSS rules that can apply properties to a website if it meets the conditions specified in the query. To make a website responsive, media queries can apply different styles depending on factors such as the size of the viewport or the input method of the client device. Media queries are often used to group styles that change at specific breakpoints, usually based on the width of the viewport or the size of the elements being styled.

The most common method of using media queries is to supply a max-width or min-width to target viewports at different sizes. The following media query would make the body's background blue on all sites smaller than 700px in width:

@media (max-width: 700px) {
  body {
    background-color: blue;
  }
}

The example above illustrates the proper syntax of media queries in CSS files. Media queries can also be written into HTML and Javascript files, however, it is far more common to write them in CSS and the following examples will continue to demonstrate that method.

In addition to using the viewport width, media queries can also be used to target other device features for styling changes. Another common use case is to target the device's capability for hover. It is often useful to display one element when a device has an input device capable of hovering, such as a mouse or trackpad, and another when it does not, such as a touchscreen. The following example would remove one element and display another on devices without a hover capability:

@media (hover: none) {
  .item1 {
    display: none;
  }
  .item2 {
    display: block;
  }
}

To instead target devices that can hover, (hover: none) can be changed to (hover: hover).

Media queries form the foundation of responsive web design. The typical process when designing a website is to style an element and then resize page until the element no longer renders in a way you like. At that size, you would add a breakpoint and media query to change the styles and make the element more appropriate. To make a site responsive for common devices, a site should render without horizontal scrolling on devices as small as 360px wide.

Media queries will be used alongside other responsive design techniques that this article will cover, but will not always be necessary depending on the structure of your website and the use of other design methods.


Flexbox

Flexbox is a tool for modern CSS layouts that makes it easy to align and space elements in a container. Items can be grouped into either a row or column, and their alignment and spacing can be altered using a number of useful tools. Flexbox containers can even wrap items into multiple columns or rows if that is required.

Basics

To declare a container as a flexbox, use the display: flex property.

.container {
  display: flex;
}

Flexboxes default to grouping items in a row. To group as a column, use the flex-direction property. Values that can be used with flex-direction are:

  • row
  • column
  • row-reverse
  • column-reverse
.container {
  display: flex;
  flex-direction: column;
}

Flexboxes will not wrap by default, instead elements will continue to be placed into the same row or column. This behavior can be changed with flex-wrap.

.container {
  display: flex;
  flex-wrap: wrap;
}

Alignment

Two properties are used to control alignment in flexboxes, justify-content and align-items.

The justify-content property controls alignment along the main axis of the flexbox. For a flex row, this would control the horizontal spacing of the flexbox.

The align-items property controls alignment along the cross axis of the flexbox.

justify-content

flex-start

flex-end

center

space-between

space-around

space-evenly

align-items

flex-start

flex-end

center

stretch

Layouts

Flexbox can be useful for a variety of responsive layouts, particularly when elements need to be placed in a row or column. One common use case is to use a flexbox when designing a card.

The example above is a very basic card with an image and some text. It is often necessary to change the layout of these types of cards for different screen sizes. This is very simple to do with flexbox and a media query. The following media query would make the card display as a flex row on screens wider than 700px:

@media (min-width: 700px) {
  .card {
    flex-direction: row;
  }
}

To display multiple cards, a flexbox with flex-wrap can be used. This is useful when the exact number elements is not known, because any additional items will wrap to the next line when the row runs out of space. Flex also has a gap property that can very quickly set up some minimum spacing for the items.

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

When creating more complicated layouts for a web page, flexbox can become difficult to use. In those situations layouts can be built with CSS Grid, which will be covered next.


Grid

CSS Grid is a module used for creating two-dimensional UI layouts. Grid layouts are divided into rows and columns, with elements able to span multiple cells. This allows the creation of complex layouts with differently sized elements, and can be used for a variety of user interfaces. Grid can be used in conjunction with Flexbox to make responsive website designs.

Basics

Grid containers are declared using the display: grid property. The properties grid-template-columns and grid-template-rows are used to size columns and rows. Elements within a grid container can be placed in specific locations and can span multiple rows or columns.

Here is a basic example of a grid container with 4 children:

1
2
3
4
.container {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: .5rem;
}

The fr, or 'fraction', unit is used to divide the grid's spacing between rows or columns. In the example above, the total space is divided into two columns with the second column taking twice the space as the first. The example also makes use of the gap property, which provides the spacing between individual elements. Gaps can also be created with the column-gap and row-gap properties.

Elements within a grid container will be automatically placed into their location in the order they are written. However, there are methods to place items in specific locations on the grid by explicitly declaring their placement. Here is an example of a grid with items placed on a 3x3 grid at different sizes:

1
2
3
4
.box1 {
  grid-column-start: 1;
  grid-column-end: 3;
}

.box2 {
  grid-row: span 2;
}

.box3 {
  grid-row: 2 / 4;
}

.box4 {
  grid-column-start: 2;
  grid-column-end: 4;
}

Elements can be placed with grid-column-start and grid-column-end, or grid-row-start and grid-row-end. The properties grid-column and grid-row are a shorthand in which the start and end are separated by a /. The value span is used to have the element span multiple rows or columns.


Text

There are several useful tools in CSS to make text elements responsive and readable. Media queries can be used to change the size of text areas and to choose the appropriate font size for the viewport. There are properties that can limit the width of paragraphs to enhance readability. Sections containing large blocks of text can also be easily separated into columns.

Media Queries

The most basic form of responsive typography is to explicitly declare different font sizes for different screens. This is generally most important with headlines, as they are a common source of overflow on smaller screens. When writing media queries for text, it is important to check how the text is rendered at all screen sizes.

In addition to font-size, there are several other CSS properties that you may want to alter between small and large screens. The line-height property can be used to change the distance between lines of text. Alignment of the text can be changed with text-align. You may also want to change the max-width or columns properties, especially for large screens.

clamp()

The clamp() function in CSS is used to create responsive sizing for elements. It takes three parameters, a minimum value, preferred value, and maximum value. This can be used to create text that will automatically scale with the size of the viewport in only one line of code.

To get the size to scale with the viewport, use a vw (viewport width) value in the preferred value parameter. The minimum and maximum sizes can be declared with rem. Here's an example for a paragraph font that will scale with the viewport width:

p {
  font-size: clamp(1rem, 4vw, 1.5rem);
}

max-width

To improve the readability of text on a website, elements that have multiple lines of text should use the max-width property. This will allow blocks of text to grow responsively until they hit a maximum size. When setting a max-width for text, the ch (character) unit can be used to set a maximum number of characters per line. Generally, lines of text should be displayed at a maximum of 50-75 characters per line.

p {
  max-width: 60ch;
}

Images

Images are a common source of layout and loading issues on websites. Fortunately, there are several tools developers can use to implement responsive images that will display properly on all devices.

By default, an image rendered in an img tag will display at the full size of the image. This will often cause images to be too large for their containers and create overflow issues on web pages. The solution to this problem is to place the image inside a container and set a width or max-width of 100% to the image in CSS. This allows the image to grow with the container it is placed in without overflowing. If a height: auto value is also added the image will always display in the aspect ratio of original image.

img {
  width: 100%;
  height: auto;
}

Using the max-width property will limit the width of the rendered image to the actual width of the image file. This prevents the image from growing too large and becoming pixelated.

img {
  max-width: 100%;
  height: auto;
}

There are some situations in which the developer will need to set the aspect ratio of an image for styling or because of variations in the image files. To do this, the aspect-ratio property can be used. The property takes a value of width / height.

img {
  aspect-ratio: 16 / 9;
}