Responsive Mobile View

Learn how to adjust the layout - aka "responsive design" - using media queries.

Next video loading... 5
Get Code

Transcript

The layout we have produced so far using CSS and HTML is looking pretty good. However, we have not yet optimized our layout for mobile devices. In other words, as I reduce the width, otherwise known as the width of the viewport, you can see that in particular in the "About" section the graphic begins to clash with the content.

This is due to the fact we have set up the stars graphic as a background image. So, we need to add some additional styles to prevent this clash into the content.

The first step in designing styles for smaller viewports is determining when the layout begins to break. To help us, we will open devtools. And with devtools open, you may notice in the top right as I'm dragging the side of the window that devtools displays the current window dimensions, with the first value being the width. So I can see that the graphics begin to collide right around 800 pixels.

We know we need to create new styles for our "About" section. But how do we designate that they should only occur on smaller viewports? Well, the most common way we can address this is using something called media queries.

Over here in my styles, we're going to create our first media query. Media queries began with the @ symbol and the word media, and then for viewport-based media queries, we place our definition between parentheses because we want our media query to operate off of the width of the viewport.

We are going to say max-widthof 800 pixels. Then within the curly braces of the media query, we can define as many rules as needed to affect the elements and update their styles when the viewport is less than this max-width of 800 pixels.

@media (max-width: 800px) {
/* Styles here */
}

Let's make our first update.

Looking in our dev tools, again, we can see that we have used the max-line-lengthclass on our paragraph, which is currently set to 60ch.

One of the adjustments we can make is to reduce that a bit further when the viewport is below 800px. Because this is a class and it's reused throughout our layout, we need to scope it to the "About" section.

So, we'll write our rule scoped to the "About" section max-line-length class and reduce that to 50ch.

@media (max-width: 800px) {
#about .max-line-length {
width: 50ch;
}
}

And on save, we can look at reducing our viewport, and when it gets to the 800px point, you saw that it changed the width. Now we also need to prevent the graphic from clashing into that content.

Often times, I find it useful to continue using dev tools to help figure out what adjustments we can make. In this case, we know we need to probably reduce the size of the background image, and reposition it. The background image is defined directly on our "About" section.

If you recall, another graphic we have in place is our unicorn. And a trick we used on the unicorn to prevent having to use media queries was to set its width using viewport units. In this case, 25 viewwidths (vh) which means it will never be greater than 25% of the width of the viewport. We can do something similar on our background image.

So using the element styles for now, which we'll transfer into our stylesheet later as a media query, let's set the background-size property as 25vw for the width. You saw that reduce already, and auto for the height.

So the shrinking width helped us out, but it's still going to eventually clash. You may already have identified that we have some space above the content. So let's also reposition our background-position to top right.

Now, if we examine from a wider viewport down, you can see that with the combination of the paragraph shrinking width and the background graphic shrinking width and moving its position, that we have resolved the layout issues.

So now we will copy these styles we created in devtools and add them into our media query rule. This will be set directly on the #about element since that's where the background has already been placed.

@media (max-width: 800px) {
/* ...existing styles */

#about {
background-position: right top;
background-size: 25vw auto;
}
}

So on save, we'll make sure that this comes into effect, and it does.

Now if we scroll down our page, the other area in which we're having a bit of trouble with the content is our Tour Packages. You'll quickly see that that's becoming far too narrow and even breaking our price element.

So what we'd like to do is on smaller viewports adjust the Tour Packages cards to flow in a single column down the page instead of retain three columns across. So similar to our media query here, will create an additional one for the Tour Packages cards.

Now, we don't have to always use the same media query value.

Now, whereas for the "About" section we resized our viewport using dev tools to determine that 800px was the appropriate breakpoint, another tool we can use in Chrome is the device toolbar.

And once that has been opened, we are provided a drop-down where we can easily set common mobile device resolutions. One resolution that's useful to start with is an iPad, and by default this is going to be iPad in portrait mode. And you can see that the dimensions that are used are 768px width by 1024 height. And at 768px width, the cards are still readable and look pretty nice.

You may choose to explore the other devices available, but after the iPad size the resolution dimensions get much smaller.

So using our iPad as a tipping off point, we can set our media query to one pixel less than the iPad width.

So in this case, we will set at @media and our max-width will be one pixel less will be 767px.

@media (max-width: 767px) {
/* Styles will go here */
}

We can also set the device toolbar behavior to "Responsive", and similar to using the inspector to determine the width, we can actually do it within the device toolbar which makes it a little easier to see and maintain the dimension that we're currently viewing. You can also manually type in a dimension, so we'll type in our 767px to put it right at our media query so once we start adding styles, we can see those immediately take effect.

Our Tour Packages cards are within a list, and are set up with display: flex. By default, flexbox layout will not wrap its elements on smaller viewports.

The first adjustment we can make is to set flex-wrap to wrap behavior.

We're still not going to see a change because we've defined the card widths flex behavior to be maintained at 30%. We need to change the flex-basis value of 30% to 100% so that we are telling it to span the width.

You'll see that because I'm using the devtools, that style has only been applied to this top card specifically. Let's go ahead and move back into our real stylesheet to apply this more wholistically on the section. Once again, we want to scope these changes to the #tour section, so scoping these to the #tours .flexbox list and the #tours .card:

@media (max-width: 767px) {
#tours .flexbox {
flex-wrap: wrap;
}

#tours .card {
flex-basis: 100%;
}
}

And on save, we'll see that those have been applied because once again we're already at our 767px media query breakpoint.

You may quickly have identified the one remaining issue we have which is that our full-width cards are now crashing into each other.

The last change we can make is to create a scoped rule for #tours .card and say that a card + card, with "plus" (+) being the adjacent sibling selector. We will apply a margin-top of 24px.

@media (max-width: 767px) {
/* ...existing styles */

#tours .card + .card {
margin-top: 24px;
}
}

And on save we can use our dev tools to see what happened. The first card does not have any margin because the rule is being applied to cards that follow another card, or the adjacent sibling to that previous card. So you can see the orange filling that gap showing us that that's the margin, and the same on the last card.

So using the device toolbar in "Responsive" mode, we can use that to pull out our viewport, and you can see once it hits precisely that 767px, we're switching now from our three column layout to our full-width column layout.

This is also a very common pattern for making adjustments across viewports. You may start to notice this now when you browse other sites on your mobile devices.

In review, we learned a couple new methods of how to address reflowing our layout for smaller viewports. In the first, we reduced the size of elements such as the paragraph and readjusted the background-image size to use viewport units, and also repositioned it.

For smaller screens for the "About" section, we custom defined a breakpoint by manually finding it from adjusting it with our tools. Whereas for the Tour Packages section, we set our breakpoint of max-width: 767px based on that being a width 1px smaller than iPad, which is considered a midsize class of mobile devices.

And we updated our layout to use a common technique of going from columns to single, full-with elements for mobile devices.