Instructor: Right now, the design we implemented in the last lesson looks great on mobile, but it starts to fall apart as soon as you start resizing the viewport. One simple way that we could fix this is to just constrain the width of the design.
We could head over to this wrapper element here, we could have a max-width utility like say maybe max-width-md. It's clamped down to 28 rem wide. Then we can set margin-left and margin-right to auto using mx-auto.
If we head back to Chrome, we can see that the design is nicely centered. Yeah, it does work on all sizes technically, but it does seem like a bit of a missed opportunity to not take advantage of this extra screen space.
In this lesson, I'm going to show you how to Tailwind's responsive utility classes to make this design truly responsive. Let's head back to the code.
The first thing to understand is that out of the box Tailwind ships with four default breakpoints. We have the small breakpoint which kicks in at 640 pixels wide, the medium breakpoint which kicks in at 768, the large breakpoint at 1024, and the extra-large breakpoint at 1280.
If we want to style this page differently at these different sizes, all we need to do is take any of Tailwind's existing utility classes, like we've used over here, and prefix them with the screen size to get that utility to only apply at that breakpoint. I'll show you what I mean.
Say, we wanted to change the background color of this page at the small breakpoint, all we need to do is head up to the body here and say sm: for the small screen size, and then set the background to maybe green-500. All of a sudden, you'll see we have a green background.
Something that's important to understand is that all of Tailwind's default breakpoints are min-width breakpoints. This page is going to be green not only on small screens, but also on medium screens, large screens, and extra-large screens as well.
If we want to change the background color to something else on medium screens, all we need to do is similarly, write md:bg-red-500. All of a sudden, we've got a red background. We could change it to yellow on large screens by doing bg-yellow-500. We could change it to maybe pink on extra-large screens by doing bg-pink-500 on extra-large screens.
If we cycle through these breakpoints, you'll see we've got green, red, yellow, and pink. Say, we wanted to change the background to pink on extra-large screens, but we wanted it to be green on small, medium, and large screens, we don't actually have to repeat bg-green-500 at both of these breakpoints.
We can just set it at the small breakpoint. That will cascade through the other breakpoints until we get to the extra-large screen, which is the first time that property is overridden again.
Of course, just changing the background color here isn't really improving our design. Let's revert these changes and talk about some of the changes we can make to actually make this design work better at different screen sizes.
Let's head back to the small screen to start, get rid of these changes here, and think about what we could do to improve this. Since we have a lot more room on the sides here, maybe we could increase the size of everything here to take advantage of the extra space.
I'm going to start by increasing the max-width of this page. Instead of just max-width md, like we have here, why don't we set it to something a little bit bigger on smaller screens? Maybe something like max-width xl. Let's see how much space that takes up. Now we have a lot more room to work with.
The next thing I'm going to do is increase the space between the image and the logo. Since everything's blown up a little bit, we should increase the white space as well. Instead of just mt-6, why don't on small screens, we go up to something like mt-8?
Next, this image is actually a little bit too tall at this size. It pushes the text down a little bit too far. Why don't we give the image an explicit height so it doesn't get too tall? Why don't we do something like sm:h-64 to set a size on this image? Now it's a little bit shorter.
I don't like that the image got narrower, though. Why don't we make it full width and see what that looks like?
Now, it's taking up the right amount of space, but the image is distorted. Let's fix that distortion by using the object fit and object position features of CSS.
We can use those in Tailwind by saying sm:object-cover, to say that the image should cover the available space without distorting. That should be a bit of an improvement, and it is. Then just to be safe and make sure it's centered, we can say object-center, to make sure that the image is always rendered in the center of its available space as well.
Next, let's look at this headline. This text can be bumped up in size now. How about instead of text-2xl, we try something like text-4xl, and see what that looks like? That's looking a lot better to me.
What about the space between this text and this image? We bumped up the gap here. We should probably do the same thing here as well.
Why don't we do something like sm:mt-8, just like we did with the image? That gives us a little bit more breathing room.
Next, let's increase the size of this paragraph text, because this feels way too small compared to everything else now. How about we set it to something like text-extra-large? That looks great. With the bigger sizes, we do need a little bit more space between these two lines of text.
Why don't we increase the margin here from mt-2 to maybe mt-4? Let's also add a little bit of space above this button. Instead of just mt-4, maybe we'll do something like mt-6 and push that down a little bit. Let's increase the text size on the button, too, because it feels a little too small at this point.
Right at the end here, I'm going to add sm:text-base. We'll bring that up to the base font size, because we had it set to the small font size. Yeah, now I think this is looking pretty good.
Why don't we check out what things look like at the medium screen size, and see if there's any changes we can make to improve it.
Looking at the medium breakpoint, I think this looks pretty good. We've got the width constrained, and everything's centered, but I don't think we could make use of this available space without increasing the size of everything again. That might be a little extreme.
On the medium breakpoint, let's just leave things the way that they are because I think it works perfectly fine, and see if there's an opportunity to improve things at the large breakpoint instead.
At the large breakpoint, it's definitely starting to feel like we have a lot of space to work with. What if we try and do a more interesting layout here? Maybe we can put the logo and all those content on the left, and do a full bleed image on the right that takes up the entire right-hand side of the page.
This is going to be a drastic change, so it's going to be interesting to see how we pull this off with utility classes.
If we want some stuff on the left, and some stuff on the right, in my head, I'm thinking we're going to need two containers for that. You can see this div as the first container, the container for all of the content. We're going to need a second container for the image itself.
I think it's going to be too complicated to reuse this image tag for both of this position and the position all the way on the right, so we're going to want to hide this one on large screens and show a different instance of the image of those screen sizes instead.
Let's create a second container div here, and let's copy this image and move it down here. I'm going to get rid of all of the classes on this because they're going to be different. Let's at least focus on trying to get things in the right place, to begin with.
Now, we have these two containers. We've got this div that we're imagining is going to be on the left, and this div that's going to be on the right. In order to get these side by side, we're going to need to wrap those in a flex container.
I'm going to add another div here, and I'm going to add the flex class to it. Now, I'm going to take both of these divs, and I'm going to move those up. With any luck, we should be starting to see things move closer to the right place.
You can see we've got this thing on the left and this thing on the right. The sizes are all screwed up, but it's a start.
The first thing I'm going to do is I'm going to hide this entire div by default and make sure that it's only visible on large screens. We can do that by adding the hidden class, which is going to make it hidden for every screen by default.
If we send it to lg:block, that's going to bring it back to display: block once we hit the large screen size.
You can see, on medium screens, that div doesn't even exist. On small screens, it doesn't exist. All the way down to small mobile screens, it doesn't exist, but as soon as we get to large, all of a sudden, it pops into place.
Similarly, we're going to want to hide this image once we do get to large screens. On the image over here, I'm going to add lg:hidden so this image disappears on large screen. OK, now we're getting somewhere.
Next, let's make these two sides equal widths. We want this to take up one half of the page, and this to take up one half of the page. I'm going to head up to these containers. Here, I'm going to say lg:w-1/2. Then similarly, down here, I'm going to set this to be w-1/2 on large screens as well. OK, great.
The next thing I want to do is...You can see we have this max-width set, so we're containing this to a certain size. Since we want this to be specifically one-half, I think on large screens, we need to disable this class. We don't want it to get constrained to this size if one-half is ever bigger.
Why don't we go ahead and say that on large screens, the max-width should be full, which is 100 percent. This is why we're essentially saying there is no max-width. It's free to expand to take up the full width of the container if necessary.
Next, let's try and get this image to take up the full height of this column on the left to make them match. The way that we're going to have to do this is using some absolute positioning trickery.
What I'm going to do is I'm going to set this div to have a position of relative so we can use a positioning reference. Then, we're going to use absolute positioning on the image itself to make it fill the entire container.
If we give this a class of absolute so it's position: absolute, then we can use this class inset-0which is a shorthand for top zero, right zero, bottom zero, left zero, stretching it to the full size. Let's also add h-full, for height of 100 percent, and w-full, for width 100 percent, and see what that gets us.
Now, we have that distorted image, but it is taking up the right amount of space. We can use object-cover and object-center to undo that scaling, and now everything looks pretty good.
One thing I want to mention, I don't want this image to extend to the full height of the entire screen because then, when you go to tall viewports, things are going to basically be impossible to make work all the time. Instead, I just want this image to match the height of this panel on the left.
You can imagine on a fully-designed marketing page, there might be more content sections underneath. To simulate that, why don't we change the background color of the page to maybe something like bg-gray-300, and the bg-gray-100 to this wrapper element, so you have a better sense of what this contained area is.
The next thing I'd like to do is add a little bit more of vertical padding to this panel, and maybe horizontal padding as well because it feels a little bit tight.
How about over here, on large screens, why don't we give it some pretty extreme vertical padding? Maybe something like py-24, see what that looks like. That looks good.
For the horizontal padding, why don't we go with something like px-12, see what that looks like. That's looking pretty good.
I don't like how this text is wrapping. We might want to drop the text size down a bit since we actually have less space to work with here, now that we're only using one half of the viewport than we did at the medium screen size.
How about here where we're using text-4xl on small screens, why don't we try something like text-3xl on large screens and see if that gets the text to wrap? It does, and that looks a lot better.
Finally, let's check out the extra large screen size and see what things look like. This isn't looking too bad except you can see this text is all of a sudden no longer wrapping and things are starting to get a little bit wide.
If we were to go over to Chrome here and test out some really large viewports, you see that things just continue to expand and expand. I don't think this looks great.
What we should do is maybe constrain the width of this section so that even at really huge screens, it stays just to a reasonable size and is maybe right-aligned so it just fits in this space over here.
Let's take a stab at that. Let's head back to the code here and figure out how we can do it.
It's still important that this element is set to width one half, because it does need to take up half the width of the viewport, but the content inside of it is what we want to constrain to a specific width.
We're going to need yet another wrapper element here. I'm going to create this div here. I'm going to take this content and move it inside so that we can constrain the width of the content while still having the panel be 50-percent width.
Let's add a class here. On extra-large screens, why don't we give it a max-width of, say, large and see what happens. If we head back to Chrome where we have the extreme width potential, you can see that it gets to a certain width and it stays there, which I think is pretty reasonable.
Let's try and get this to be butted over to the right. We can do that by setting a left margin of auto. We can say xl:ml-auto. Now that moves over to the right. That's looking pretty good.
I don't really like this line break thing. I'd like if this was on a separate line. Let's take a look at where this actually happens so we can understand the best place to fix it.
Right now, we're at 1484. Let's drop that to 1024, which is our large breakpoint. Things look OK here. We can see that as we get wider, the word take actually jumps up at 1179-ish, which is earlier than the 1280 breakpoint.
If we never want this to be on the same line as this, what we're going to need to do is add a line break here. Let's head back to our code and fix this.
What I'm going to do is I'm just going to add a line break element here, br, but I'm going to give it a class. I'm going to say that by default, this should be hidden. It shouldn't actually be rendered in the browser. We're not going to force this line break by default.
On large screens, we're going to set that back to its default of display inline. Now if we check things out in Chrome, we should see that that line break is always there no matter what happens.
Let's bring this up pretty big and see how things look. This is looking pretty good to me.
The last thing that we could do to improve this slightly is maybe bump this font size up a bit since we do have a little bit of room on the extra-large screen.
Let's head back to code here. How about right here on this h1, on xl screens. Let's set this back to text-4xl and see how that looks. Now we've got this nice, big headline here. Everything still wraps as expected.
If we go back to Chrome, where we can cycle through these breakpoints really quickly, you can see we start this over a mobile width. Things don't wrap beautifully here, but that's just the nature of the beast when it comes to mobile. As we get to larger sizes, we constrain the width a bit here, keeping things looking good.
As we get to the small screen size, we just bump up the size of everything, which makes better use of the space and looks pretty solid to me. Medium screens, we don't change anything. We decided that just keeping the width constrained was a good idea here.
Once we get up to the large screen size, we jump to this cool side-by-side layout. As we get up to the extra-large screen size, we bump the headline font a bit, make sure things are constrained. This is looking pretty solid to me.
There we go, a perfectly responsive splash page built entirely with utility classes. We did all of this by just using all of Tailwind's utility classes, which we've used already, and simply prefixing them with the screen size any time we wanted that utility to only apply conditionally.
The really cool thing about this is that every single utility class in Tailwind works this way. It's not just certain features that can be enabled responsively. You can change literally anything, from the letter spacing, to the background size, to the width and height, to the display type, to the positioning.
Anything you want to change can be changed at any breakpoint you want. You have all the power in the world when you're building these complex responsive designs.