17

Responsive Design and Media Queries

In today’s world, websites can be viewed on computers, tablets, phones, watches, glasses, or even kitchen appliances. It’s impossible to design for every single scenario, and that’s where responsive web design (RWD) comes in. RWD ensures that your website looks good no matter what device it’s viewed on.

This is achieved through media queries—we can write CSS that essentially asks the browser questions and then presents styles based on the answers.

Defining Media Queries

Unlike most of the CSS declarations you’ve seen so far, media queries aren’t just sets of properties and values. They are containers for other rulesets. Those rulesets are then implemented based on the results of the media query. All media queries are formatted like this:

@media [media type] and ([media features]) {
    [Rulesets go here]
}

As you’ll see later, there are lots of different types and features to check for. But for now, here’s a common media query:

@media screen and (min-width: 600px) {
    main {
        display: flex;
    }
}

This says, “If the user is viewing this site on a screen whose viewport is at least 600px wide, display all <main> elements as flex.”

Throughout the book you’ve seen references to screen size, window width, and browser size. While each term refers to how wide an area your website renders in, the most succinct term is viewport, which refers to the exact area of the screen that is rendering your website.

Other media types include all, print (for printing a webpage), and speech (for use with screen readers).

Using breakpoints

A common term in RWD is breakpoint, the point at which your layout changes to accommodate the viewport. It allows you to make your layouts more useable based on the size of the device your users are viewing the site on.

For example, if you have a navigation menu that is 601px wide, it won’t look great on devices with a viewport of less than 601px. You can use a breakpoint to say, “Once the viewport is wider than this size, change the layout of the navigation menu.”

So if you select a media query for min-width: 600px, your breakpoint is 600px.

Choosing breakpoints is an important decision because it ensures your layout doesn’t, well, break. Many breakpoints focus around specific devices—usually iOS devices—but as the field of screen sizes increases, this is not a good approach.

Instead, choose your breakpoints based on the point at which your content starts to look bad.

If you’re starting mobile first, that means adding a breakpoint that takes effect when the page is on devices with larger screens. As the viewport expands past the breakpoint, it can switch to different layout settings, such as multicolumn layouts or layouts that are centered in the screen.

If you’re starting by designing your pages for large screens (a large tablet or desktop), when the page is viewed on a smaller device you select your breakpoint by resizing the browser window (and therefore the viewport) down until the content becomes unreadable.

Ultimately, you’ll probably have three major breakpoints (where there’s a major shift in content) and three to four minor breakpoints (with smaller fixes for specific content). But that’s a guide, and it’s completely up to you. Do what works best for your design.

Responsive Layouts

So how do you make responsive layouts? Where do you start, and how do you structure your code? I recommend setting all the base styles above any media queries (as in, write them down in your style sheet first) and starting with the smallest layout. Media queries should modify your website as the viewport gets bigger. Here’s a simple example to start.

To change the background color at 600px:

  1. In your style sheet, type body to establish the default values for the page.

  2. Type { to begin the rule.

  3. Type background: followed by the hex code for the starting background color. For this example use #FF0000;.

  4. Type color: followed by the hex code for the text color. In this case, use #FFFFFF;.

  5. Type } to close the rule.

  6. Type @media to begin the media query.

  7. Type the name of the media type you want to target. Because you want to implement a different style rule when the user’s browser window changes, use screen.

  8. Type and.

  9. Type the name and value (in parentheses) of the media feature that should trigger a change in the background color. This value is your breakpoint for the page, and you want the break to occur when the browser window is 600px or wider, so use (min-width: 600px) {.

  10. Type the element you want this rule to affect. In this case, body {.

  11. Type the attribute and value that you want to change at the breakpoint. In this example, use background: #0000FF;.

  12. Type }.

  13. Type } to close the media query.

Now resize the browser window. When it is below 600px wide, the background is red (FIGURE 17.1). When it’s 600px or wider, the background is blue (FIGURE 17.2).

The screenshot shows a page in the browser window having a width lesser than 600 pixels. The page is elongated vertically and the background color is red. The font color is a lighter shade of brown with the caption in white font.

Figure 17.1 The page when the browser window is less than 600px wide

The screenshot shows a page in the browser window having a width of 600 pixels or more. The page seems to be horizontally elongated and the background color is blue. The font color is white for both the header and the content.

Figure 17.2 The page when the browser window is 600px or wider

Note that the font color was set outside the media query. The goal is to avoid repetition in your code that might bloat your style sheet. Any styles set inside media queries will apply only when the media query is true. So if you have multiple media queries but don’t want the color to remain the same, you’d have to set it in every media query.

This is another benefit of the mobile first approach. You will likely start at default displays for smaller screens and then introduce changes as the page is displayed in larger viewports, allowing you to set as many default styles as possible before you start making changes.

For example, here is a simple CSS Grid layout that shows the pitfalls encountered when defining the bigger screen first (CODE 17.1). It tells divs to display their children in columns as long as the viewport is wider than 599px. At 599px or smaller, it display divs as a block.

In the media query, you’re actually resetting the div back to its default display mode.

You can avoid the dangers of designing for the large screen first by treating the larger screen as the special case, and allowing the smaller screen to use the browser’s default settings.

And now, we’ll define media queries used in designing for small screens first (CODE 17.2). You don’t have to reset div to its original state because it maintains that state (display: block) until you change it for bigger viewports.

This is a seemingly trivial example, but in the mobile first layout, it wasn’t necessary to define any special styles, because the browser defaults were adequate. The desktop-first layout required some resetting of styles. You can imagine that using multiple breakpoints, or more varied styles and layouts, will compound the cases in which you find yourself redefining styles.

As you create your layouts, think about how to reduce the number of styles you override and how to make your style sheets easier to manage.

Making a Full-width Layout Responsive

So what goes into making a fully responsive layout? Here, you’ll build it in sections. CODE 17.3 shows the HTML markup you’ll work with. CODE 17.4 shows the initial CSS styles, in a style.css file. Both are available at github.com/jcasabona/html-css-vqs/Ch17/.

FIGURE 17.3 shows the smallest screen and FIGURE 17.4 the largest screen.

A screenshot shows a browser window in a mobile layout.

Figure 17.3 The mobile layout

A screenshot shows a browser window in a desktop layout.

Figure 17.4 The desktop layout

Starting small: mobile first styles

Most of the styles in Code 17.4 are for general look and feel and are not related to layout. On the smallest screens, everything will be a single column, so the browser’s default styles for the elements will work. The changes you see for margin, padding, fonts, and colors were just to add some personality to the page and make the layout changes more obvious (like giving the aside a different background color from the body).

So now it’s time to answer the question of when to start changing the layout—at what point can you begin to space the content out a bit more?

As you try to figure this out, the best thing to do is resize your browser. Since this layout lends itself very well to a one-column format, not a whole lot needs to be done in terms of adjusting it. Complicated layouts require more complicated media queries.

However, there are a few things that can be done to take advantage of more screen real estate.

The mid-sized screen layout

One way you can take advantage of more screen space when your page is being viewed on bigger devices is to spread out the header text a bit. One way to do this is to set up a grid on the <header> element and use columns to space the child elements.

To create a two-column layout at a breakpoint:

  1. Start by defining your media query, based on the breakpoint at which you’ve chosen to change your layout. Type @media screen and (min-width: 768px) {.

    Add this code to the end of your style sheet (assuming you’re using the code from Code 17.4).

  2. Target the element you’d like to change at your determined breakpoint. Type header {.

  3. Add the styles for this element at the specific breakpoint, one per line. Type display: grid;.

  4. Type grid-template-columns: 2fr 1fr;.

  5. Type grid-gap: 15px;.

  6. Type justify-items: center;.

  7. Close the ruleset for your element by typing }.

  8. Close the media query by typing }.

Once you extend your browser window to a width of at least 768px, your header will move the byline out from under the heading and to its right (FIGURE 17.5).

A screenshot shows a header with the viewport having a width greater than 768 pixels. The header seems to be horizontally elongated. The background color of the header is black while the fonts are in white.

Figure 17.5 The header once the viewport is widened beyond 768px

This is a good first step, but the real fun starts at the next breakpoint: 1000px.

The large-screen layout

On a large screen, you can really take advantage of the screen real estate. Using a multicolumn layout for large screens is a great way to show more information to the user, now that they have the room for it. A wrapper div comes in handy here. This div “wraps” the elements—header, main, aside, and footer—so that they are all siblings. That means you can apply display: grid to the .wrapper selector and easily control how each child element (or grid item) is displayed.

Since the large screen layout builds upon all the styles added to style.css before it, add the following styles to the end of style.css.

To set up a grid layout at a specific breakpoint:

  1. You want this layout to go into effect at the largest breakpoint you determined works best for your layout. Type @media screen and (min-width: 1000px) {.

  2. You will also need to create the grid-areas. Based on Code 17.3, type header { grid-area: header; }.

    Because of the cascade, this will essentially be added on to previous rulesets targeting header.

  3. On a new line, type main { grid-area: main; }.

  4. On a new line, type aside { grid-area: sidebar; }.

  5. On a new line, type footer { grid-area: footer; }.

Be sure to leave off the } that would close the media query. We’re not done with it yet!

With those defined, it’s time to convert the wrapper div into a grid with a template layout.

To convert wrapper to a grid layout:

  1. It’s time to target your entire layout at this breakpoint. Type .wrapper {.

  2. A grid lends itself well to controlling each element of the layout. On a new line, type display: grid;.

  3. On a new line, type grid-gap: 15px;.

  4. Determine how many columns you want in your layout. For this example, choose five to make it clear we won’t have a main section and aside that are the same widths. On a new line, type grid-template-columns: 1fr 1fr 1fr 1fr 1fr;.

  5. Type grid-template-areas:.

  6. Type "header header header header header".

    Remember from the mid-sized layout task, that header is also using grid. This controls the width of the header element, which we want to extend across the entire page.

  7. Type "main main main main sidebar".

  8. Type "footer footer footer footer footer";.

  9. Close the .wrapper ruleset by typing }.

  10. Close the media query. On a new line, type }.

Now the sidebar shows up to the right of the main content, just like in Figure 17.4.

Now for the fun part: resize the browser window and watch your layout change!

There are a few more stylistic changes you can make, like increasing the heading font size and tightening up some styles, but you’ve just taken your first layout and made it responsive.

The rest of this chapter explores other functions of CSS media queries.

Not Just for Screen Widths

The only media type you’ve seen in action so far is screen, and the only feature you’ve seen is related to width. While these are the most common implementations for media queries, they aren’t the only ones. For starters, there’s another common media type to look at: print.

Creating a print style sheet

Because computers print websites more or less exactly as they appear in the browser window, such printouts often aren’t very helpful to those who want readable text (FIGURE 17.6).

An example for printing a webpage is shown.

Figure 17.6 Trying to print a webpage

Luckily, you can add a media query to apply print styles to the page. Here’s how to do it, starting with the markup from the previous section.

To add printer styles to a website:

  1. At the bottom of your style sheet, type @media print { to target printers.

  2. Type the elements you want to include in the printout. For this example, you want the whole page, so include body, header, aside, footer {.

  3. On a new line, type background: #FFFFFF;.

    This step and the next set the background color and text to white and black, respectively, so the text is more easily readable when printed.

  4. On a new line, type color: #000000;.

  5. On a new line, type }.

  6. On a new line, type .wrapper {.

    This is the crux of the print styles.

  7. On a new line, type display: block;.

    Simply setting the display to block makes the browser ignore all grid-related properties (like grid-template-columns) and moves the content into one column.

  8. On a new line, type width: 75%;.

    This is a stylistic decision on my part, but it gives the reader plenty of margin on either side of the content.

  9. On a new line, type margin: 0 auto;.

  10. On a new line, type } to close the .wrapper ruleset.

  11. On a new line, type } to close the media query.

This creates a single column of black text that looks great when printed (FIGURE 17.7).

A sample webpage that is printed by implementing printer styles is shown.

Figure 17.7 The printed page

Aside from media types (all, print, screen, speech), you can also target specific media features.

Targeting specific media features

You might want to target a specific feature on touch devices, check if a device is in portrait or landscape, or much more. This is what the extended media features are for. A great example is checking to see whether a user has enabled dark mode.

To apply dark mode styles:

  1. At the bottom of your style sheet, type @media screen.

  2. To specify one or more media features, type and followed by the name of the media feature in parentheses. To check for dark mode, type (prefers-color-scheme: dark) {.

  3. Type the selectors you want the style to apply to; in this case, body, header, aside, footer {.

  4. To make sure the text harmonizes with the overall inky environment, reverse the usual black-on-white colors. Type background: #272727; to make the page a dark gray.

  5. Type color: #FFFFFF; to make the text white.

  6. Because it’s light text on a dark background, a bit more spacing will make the text easier to read. Type line-height: 2em;.

  7. Type }.

  8. Type one more }.

Now, when you visit the site on a device using dark mode, it will look like FIGURE 17.8.

The browser window shows the webpage of a book titled "A Case of Identity," printed by implementing dark mode. The background is dark, and the text is white.

Figure 17.8 Dark mode styles applied to a webpage

Experiment with more of these media features, as you can do checks for the following:

  • Pointer (cursor) support (with any-pointer)

  • Hover support (with any-hover)

  • Retina displays (with resolution, min-resolution)

  • Inverted colors (with prefers-color-scheme)

And much more. The possibilities for customizing a website’s experience are growing quickly!

Wrapping Up

Media queries are essential to creating great user experiences no matter what device your site is being used on. From adjusting layout based on width to swapping out colors in dark mode, your styles are completely customizable based on the user’s preferences and their browser’s capabilities.

And now that you’re familiar with everything from the basics to layouts in CSS, it’s time to get a little more advanced and look at CSS animations.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset