Overview
By the end of this chapter, you will be able to implement the mobile-first principle when designing web pages; explain the fundamentals of responsive web design; use a variety of CSS media queries; create a mobile-friendly web page; and implement printer-friendly web page styles.
This chapter introduces you to the world of responsive web design and aims to teach you how to develop web pages using media queries to build mobile-first websites that are suitable for a whole variety of devices, regardless of the device's screen size or hardware. In addition to this, the chapters introduce printer-friendly web page styling.
In the previous chapters, we learned about the basics of HTML5 and CSS3 in terms of structure, layout, and typography. We have also explored HTML forms, and how to go about theming websites.
Now, we're going to look into adapting our web pages for the world of mobile-first responsive web design. A key element of a successful website starts with a good user experience design, providing the user with a seamless browsing experience on the website regardless of their device. Many users access websites through their mobile devices; it's second nature for them. From finding a location on a map to gathering information over the internet, users are finding that everything can be done using their phone, which is convenient since, when on the go, users are hardly likely to have a computer with them. With the rise of the mobile internet, it's realistic to expect to be able to get online in many parts of the world, even the more remote places, these days. Given this, it's not uncommon for users to use their phones more than their computers. As such, it would be wise to assume that users expect websites to just work on all their devices, regardless of screen size, and so we'll be looking at the mobile-first principle and how we can implement it for a website.
The majority of clients these days will ask for a mobile version of their website. It's become an expectation in the industry for a user to be able to browse and/or shop online from their phone, tablet, or computer; and if they can't, then it's generally considered a missed opportunity for custom. With every year that passes, many more new devices with different screen sizes are released and it would be incredibly difficult for a web developer to keep up with them all. This is where the responsive web design approach comes into play, which you'll learn about in this chapter.
With the rapid uptake of the mobile internet over the past decade, it's now very common to see websites that have more mobile web traffic than desktop web traffic. Considering new (and existing) websites from a mobile point of view is now seen as an essential business case, so it's an essential web design principle to put into practice. It's vital, for instance, to consider the mobile user's experience when using the website, right down to the basics of navigation and the experience of buying items if it's an e-commerce site.
In the following figure, we can see three wireframes illustrating an unresponsive website. You can see how the layout of the web page doesn't change despite being displayed on different-sized devices. This figure also shows the output of Chapter 3, Text and Typography Exercise 3.06, Putting It All Together, which is also unresponsive, as it maintains its layout when viewed on a mobile device:
The layout remains the same on each device, even though the more narrow the device is, the more zoomed out the display of the website has to be in order to maintain the layout. This may force the user to zoom in to read website content, which creates a bad user experience and will likely cause users to leave the website when using smaller devices. As a web developer, you would want to optimize the website user's experience to increase your client's potential website conversion. The mobile-first principle plays a key part in this.
The mobile-first principle consists of two main points:
As a web designer following the mobile-first principle, the lack of space on a mobile device is not a disadvantage. It is, in fact, an advantage of the mobile-first design, as the most important content is delivered first, often cutting the "waffle" and getting to the point so that mobile users don't lose interest and instead have a much better mobile user experience.
With a multitude of different devices currently on the market, responsive web design is an approach where a website is designed to respond to work smoothly irrespective of the device's screen size, software (for instance, iOS Safari, Android Chrome, and so on), or orientation (portrait or landscape).
A website built using the responsive web design approach should be built to automatically adjust to the user's device and respond to the user's behavior, such as changing the device from portrait to landscape orientation, resizing the browser window, and scrolling.
The following figure shows a wireframe of a responsive website stacking content, along with an example of stacking from https://packt.live/31e3aUv:
The preceding figures are a good demonstration of putting responsive web design into practice. Content that is currently displayed over three columns on a desktop computer can be stacked vertically across two columns on a tablet and stacked vertically in a single column on a smaller mobile device. Using HTML5 and CSS3, this layout could be achieved with a combination of the flex-based grid layouts discussed in Chapter 2, Structure and Layout, and media queries, which we'll learn about in this chapter.
In order to be able to build a responsive website, it is necessary to understand media queries, but first, we need to ensure that we have the viewport meta tag in the <head> of our HTML document; this was previously introduced in Chapter 1, Introduction to HTML and CSS. The viewport meta tag is widely used in modern web browsers to help ensure cross-browser compatibility in responsive web design. The following code snippet shows where you would place this within your HTML document:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<!-- Website content here -->
</body>
</html>
By setting the viewport width property to device-width, we are instructing the web page to display with the device's natural resolution, as opposed to the default zoomed-out display of the website at desktop resolution on the device, like the example in Figure 6.1. The initial-scale viewport controls the initial zoom on the web page; you should keep this at 1 unless you need to enlarge the page for any reason. Remember that the user can zoom in on the web page themselves using the normal gestures, unless this is disabled by setting another additional viewport property, maximum-scale, to the value of 1 as well. However, this is not recommended for accessibility reasons as some users may find it beneficial to zoom in when browsing, especially if they have a visual impairment.
Media queries are a core feature of CSS3 and they allow the developer to change the display of a page based on the device screen width and orientation (portrait/landscape), or even to display the page differently for printers if a physical copy of the web page is to be created.
First, let's understand what a breakpoint is. A breakpoint is the point at which the web page responds to the device or web browser's width (or height). When the breakpoint threshold has been reached, different styles can be applied in CSS. Take the Packt Publishing website, for example (https://packt.live/34BkPHM). If you load this on a computer and then resize the width of the web browser window from full width to narrow width, you will notice that changes in styling are triggered at certain points: breakpoints. This is made possible using CSS3 media queries. We can have breakpoints with the height of a device or browser screen, too. See Figure 6.3:
A media query is represented in CSS3 with the @media syntax, followed by a condition or breakpoint. For example, if we wanted styles to be applied to a screen with a maximum width of 768 pixels, then we could write this as @media only screen and (max-width: 768px), followed by curly braces { } containing the code to apply when this media query condition is met.
For example, take the following CSS code:
@media only screen and (max-width: 768px) {
p {
color: blue;
}
}
This code will change the p tag's text color to blue when the web page is browsed on a device that is up to 768 pixels wide, as shown in the following figure:
The following code will change the p tag's text color to red when the web page is browsed on a device wider than 769 pixels, as shown in the figure that follows the code:
@media only screen and (min-width: 769px) {
p {
color: red;
}
}
So, as you can see, CSS media queries allow you to apply styling based upon the device/browser width. You can combine the screen minimum and maximum width properties of min-width and max-width to target certain breakpoint windows, meaning certain styles can be applied according to the screen width.
For example, this CSS code combines the min-width and max-width properties:
@media only screen and (min-width: 480px) and (max-width: 768px) {
p {
color: purple;
}
}
This code will change the p tag's text to purple when the screen width is between 480 pixels and 768 pixels, as shown in the following figure:
It's also possible to use media queries to style things based upon the device/browser screen height, as in this example:
@media only screen and (min-height: 1000px) {
body {
background-color: pink;
}
}
The preceding code snippet will change the web page's background color to pink, using the body HTML tag, when the web browser's height is 1,000 pixels or higher, as shown in the following figure:
These @media code examples would be written within a CSS file and work well if you have one stylesheet for your web page. However, if you wanted to have separate CSS stylesheets for different device width breakpoints, this can also be achieved. For example, we can include the stylesheets with this HTML code:
<link rel="stylesheet" media="screen and (max-width: 480px)" href="mobile.css" /><link rel="stylesheet" media="screen and (min-width: 481px) and (max-width: 768px)" href="tablet.css" />
This example code would be placed within the <head> of the HTML document and would use the mobile.css file on screen widths of 480 pixels or lower, and use the tablet.css file on screen widths between 481 pixels and 768 pixels.
This can be a very useful feature, from a code maintenance point of view, for helping to keep device-specific styles together in separate files, particularly if they vary significantly from breakpoint to breakpoint. But to debunk any performance optimizations myths here, sadly, most modern browsers will still load all <link /> files when loading a web page, regardless of screen size – even though the styles are only applied when the media query specified becomes true.
Now, cast your minds back to Chapter 3, Text and Typography Exercise 3.06, Putting It All Together, in which you created a video store web page (see Figure 6.8). We'll be developing this exercise further to introduce media queries to the web page in our first exercise of this chapter:
In this exercise, we'll make the video store navigation work responsively based upon browser screen width.
Let's complete the exercise with the following steps:
It's worth noting the importance of the * { margin: 0; padding: 0; } part of the code, as this resets the browser's default margins and the padding of all elements on the web page to zero. By default, many web browsers apply a margin and/or padding to list styles (ul/li), which would cause us issues when trying to style the navigation. For complete control and cross-browser fluency, it's better to reset, as we have done in the following example code. The following code snippet shows the example code of the completed CSS changes:
<style>
* {
margin: 0;
padding: 0;
}
nav ul {
list-style: none;
}
nav a {
color: white;
background: black;
font-weight: bold;
display: block;
padding: 15px;
font-size: 15px;
text-decoration: none;
text-align: center;
}
nav a:hover {
background: darkgray;
}
</style>
If you now open your exercise web page in the web browser, you'll be able to see how the navigation has changed to be vertically stacked, as opposed to being displayed in a row as it was before. You can see this in the following figure:
@media (min-width: 480px) {
nav ul {
display: flex;
}
nav li {
flex: 1 1 auto;
}
}
We were introduced to flexbox in Chapter 2, Structure and Layout, but, to recap briefly, adding display: flex to the ul parent element ensures that the child li elements are displayed in the same row. Then, by providing the flex: 1 1 auto; directive, we tell the li elements that 'the basis of growing and shrinking in width changes, this flex property combines the flex-grow, flex-shrink, and flex-basis properties into one shorthand property. This will create a single row of navigation elements, with the spacing and element widths being automatically calculated as the web page screen width increases or decreases.
Now, the navigation system will comprise flexible blocks in a row, each with an on-screen width of 480 pixels or above, as shown in the following figure:
@media only screen and (min-width: 768px) {
nav a {
font-size: 20px;
}
}
The following figure shows what the navigation blocks at 479 pixels (or less) look like with a stacked layout; this is most commonly seen on mobiles in portrait orientation:
The following figure shows the navigation blocks at the breakpoint of 480 pixels or above, using the flex column layout and with the font size fixed at 15px:
The following figure shows the navigation blocks displayed at 767 pixels or above, maintaining the previously set flex column layout, but with the font size increased to 20px:
As a recap, in this exercise, you have learned how to take an existing web page that was not responsive or mobile-friendly and change the styling structure to make it a mobile-first web page, and you have used media queries to apply responsive CSS3 styling as the screen size increases to change the styles/layout to suit the screen better. Next, we will be looking at device orientation in media queries to help design responsive web pages.
Mobile and tablet devices have two orientations: portrait (when the device is upright) and landscape (when the device is on its side). When coding websites for such devices, it can be useful to target the device's orientation with media queries to apply different styles to give the user a better experience. The syntax of the media query for checking device orientation is @media (orientation: landscape). This would make the rules apply to devices currently in landscape mode only. You can also have @media (orientation: portrait) for portrait devices only instead.
The following figure shows a screenshot of what this could look like in action on a tablet device:
Here is the full source code for the preceding figure, demonstrating the media query in action:
Example 6.01.html
13 @media (orientation: landscape) {
14 p.warning {
15 display: block;
16 }
17 }
The full example code is available at: https://packt.live/2JXLsyM
You can combine orientation and width media queries together to form more advanced rules. Take this, for example:
@media (orientation: landscape) and (min-width: 400px) and (max-width: 768px)
This would display the p tag with a warning only on screens that are at least 400 pixels wide, but that are no more than 768 pixels wide if the screen is also in landscape orientation mode. You can see this demonstrated in the following figure:
Here is the full source code for the preceding figure, demonstrating the combination of orientation and width media queries:
Example 6.02.html
@media (orientation: landscape) and (min-width: 400px) and (max-width: 768px) {
p.warning {
display: block;
}
}
The full example code is available at: https://packt.live/33s5gBY
As you can see, we can build very effective media queries to change the styling and display of a web page based on many environmental conditions.
In this exercise, we will create a web page to detect device orientation using media queries, and then we will change the layout of the page within these media queries to create portrait and landscape layouts for the website. In the following figure, you can see a wireframe demonstrating what we are trying to achieve in this exercise:
Let's complete the exercise with the following steps:
<!DOCTYPE html>
<html>
<head>
<title>Exercise 6.02: Device Orientation</title>
</head>
<body>
<header>
<img src="https://dummyimage.com/200x100/000/fff&text=Logo" alt="" />
<nav>
<ul>
<li><a href="">Home</a></li>
<li><a href="">Nav #1</a></li>
<li><a href="">Nav #2</a></li>
<li><a href="">Nav #3</a></li>
</ul>
</nav>
</header>
<article>
<h1>Video Review</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus scelerisque, sapien at tincidunt finibus, mauris purus tincidunt orci, non cursus lorem lectus ac urna. Ut non porttitor nisl. Morbi id nisi eros.</p>
<p>Donec et purus sit amet odio interdum accumsan eleifend ut sapien. Praesent bibendum turpis non nisl elementum, sed ornare purus semper. In vel sagittis felis. </p>
<p>Suspendisse vitae scelerisque est. Aenean tempus congue lacus vehicula congue. Vivamus congue ligula nec purus malesuada volutpat.</p>
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Curabitur sit amet mattis urna. Morbi id luctus purus, sodales facilisis odio. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</article>
<footer>
<p>Website by Author Name</p>
</footer>
</body>
</html>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
* {
margin: 0;
padding: 0;
}
header {
text-align: center;
}
nav ul {
list-style: none;
}
nav li {
display: inline-block;
margin-right: 5px;
padding-right: 5px;
border-right: 1px solid black;
}
nav li a {
color: black;
text-decoration: none;
}
nav li a:hover {
text-decoration: underline;
}
nav li:last-child {
border-right: 0;
padding-right: 0;
margin-right: 0;
}
article, footer, nav {
padding: 10px;
}
article h1, article p {
margin-bottom: 10px;
}
footer {
background: black;
text-align: center;
color: white;
}
</style>
You'll notice :last-child, which means that the final element in the navigation, in this case, has slightly different rules to finish off the styling. In addition to styling the navigation, the CSS also adds a basic style to the article content and footer of the web page.
<style>
@media (orientation: landscape) {
header {
display: flex;
align-items: center;
}
nav {
margin-left: 20px;
}
article {
columns: 100px 2;
}
}
</style>
The following diagram shows the output of the exercise in a mobile device, both in portrait and landscape orientation:
The following figure shows a screenshot of the device simulator in Chrome's Developer Tools:
We've extended our knowledge of media queries to now be able to change the styling of a web page based on the device's orientation. We've also utilized the display of the copy within the landscape orientation 'display, by making use of the CSS3 columns property to achieve a two-column text layout. Next, we'll look at combining multiple media queries with the OR operator for media queries.
If you want to apply a certain style change to more than one breakpoint, then you can combine media queries with comma-separated lists. The comma acts as an OR condition in the media query string. Refer to the following code snippet, for example:
@media screen and (max-width: 480px) and (min-width: 320px), (min-width: 1280px) {
body {
background: red;
}
}
This would apply a red background to the web page's body tag when the screen is between 320 pixels and 480 pixels wide, and 1,280 pixels or wider. You can see this in the following figure:
As you can see in the preceding figure, the red background was only visible within the media queries specified, even though it was combined into a single query. This can really help a developer when there is a need to share a certain style between multiple breakpoints in CSS3.
CSS3 media queries allow the developer to specify print-only styles to help control how a web page is displayed when printed out as a physical copy. This can be very helpful on websites where the user may want to print off information; for example, the user may want to print a cooking recipe or resources for an educational activity for later offline use.
There are two ways in which we can tell the browser that these styles are print only:
To implement a print-only stylesheet, you can use the following code:
<link rel="stylesheet" media="print" href="print.css" />
This code allows the print.css stylesheet to be used when printing mode is in use within the browser.
The other method is using @media queries to enable your print mode styles to become active. Take a look at the following example:
@media only print {
/* style changes here */
}
This can be a very useful feature, particularly if you would like the user to be able to print something off, such as a returns label or application form, that's displayed within a web page. We'll now put this into practice in the following exercise.
The aim of this exercise is to update some supplied HTML and CSS code and then apply a CSS layout change to the printable version of the page. The overall aim is to make a printable version of this web page by removing unnecessary items from the printing view and tidying up the styling elsewhere in order to make the page ready for printing.
The following figure demonstrates the layout changes that are expected to be visible within print preview mode:
Let's complete the exercise with the following steps:
@media only print {
footer, aside {
display: none;
}
}
This code will hide the display of the footer and aside tags when the web page is printed off. You should be able to view your print media style changes in the print preview mode of your device.
header, section {
margin-right: 0;
}
The following figure shows a screenshot with the end result when viewed in print preview mode in the web browser. You can see that the sidebar and footer are no longer visible in print mode in the following figure:
For this activity, we're going to turn the product page you've already created for your video store in Chapter 3, Text and Typography, into a responsive web page, coding it while following mobile-first principles, ensuring that it's cross-browser compatible, and making it a robust responsive web page for modern devices. The following diagram shows the video store product page wireframe from Chapter 3, Text and Typography:
The following figure is a mock-up design of the mobile view:
In the preceding figure, we are showing a mock-up of the existing desktop layout for the video store product page. The preceding figure displays the proposed mobile design of the page that you will create in this activity. The instructions for this activity are as follows:
Note
The solution to this activity can be found on page 598.
In this chapter, we have explored the topic of mobile-first and looked at what building a responsive website entails. You should have a good understanding of what media queries are in CSS3 and what you can do with them to aid your web development for multiple screen sizes. You should also know how to modify the styles of the printed version of a website, and, as part of this chapter's activity, you have refactored some existing website code into responsive website code using media queries to help create a mobile-friendly web page.
In the next chapter, we will learn about using the HTML5 media elements, including the audio, video and canvas elements.