The introduction of Media Queries to the CSS specification in 2012 was the beginning of an age of Responsive Web Development. With CSS getting more and more comprehensive, we could now roll out completely different looks at certain breakpoints, on certain devices and even if the user had their phone on landscape!
When learning CSS, it is highly recommended to build your site and get it to a place where you are happy with its desktop layout, then to add in media queries to affect page elements as the browser's width reduces to the width of a mobile phone screen. I build to account for screens as narrow as 320 pixels; the width of the iPhone 4/iPhone SE.
But what if, you could create completely responsive layouts, starting from desktop and intelligently allocating itself space on the page when it starts to get too narrow?
Flex - When your elements vary
Let's take a form of inputs as an example. Some inputs are going to require a long string of text from the user, with a high amount of variance, such as an Email Address. Some are not so long, such as a name field. If elements can fit on the same line, then you would want them to, especially if the inputs are contextual to each other in the form. Then they become full width on their own line if the available screen width starts to narrow.
Resize your screen, change your screen's orientation on mobile, or open up the HTML/CSS tab to narrow the form width. You'll see that the inputs move to their own line!
The secret is the power of flex: auto.
input {
max-width: 100%;
}
input.fill {
flex: 1 0 auto;
}
input#fname {
flex: 1 0 240px;
}
input#email {
flex: 1 0 350px;
}
With flex-wrap: wrap
set onto the container, the child elements will attempt to drop down to a new line once it gets too narrow. If no breakpoint has been set, then it will use its content and padding to determine it's minimum width.
In this example, the telephone field and the submit button are both set to flex: auto
, attached to the class name fill
. The name and email set with pixel widths via flex-basis
, the third value of the flex
shorthand. This width is the basis for which it can determine that it will grow to full width (set by the 1 in flex: 1 0 ___px
) if the space is available to do so.
And finally, setting max-width: 100%
will prevent all inputs from exceeding the width of the container. Quite unsightly!
So, as long as you know what elements will be last on their line, you can allow the first element on the line to determine when you want everything to drop onto its own line. Pretty neat!
Grid - When your elements don't vary
Grid is the cool kid on the block. Flexbox fanatics are scared of it, but I find it sneaking it's way into many different solutions to common problems when building websites. In this case, it can also allow for a responsive layout, but with fewer lines of code than flexbox.
Grid works exceptionally well when all the items you want to make responsive are of equal width and size, like a gallery of images or a grid of blog posts.
You can achieve this layout with a complicated-looking grid-template-columns
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
(The 250px can be set to allow more columns to fit onto a single line at once. You can even set it to rem
if you want to change the minimum size with media queries later)
-
repeat
applies this resizing logic to all grid items -
auto-fill
attempts to fill up the grid row.auto-fit
will ignore the container's full width and look at the minimum width of the item instead. Both are worth using for different situations! For a more in depth look at this, read Sara Soueidan's article on CSS Tricks -
minmax
allows you to decide what is the minimum and maximum width that the grid item can have. In my example, it can be as narrow as 250px and as wide as the container will allow. Since only 2 items can fit at 500px, at 450px a single item will stretch the entire width.
The main advantage over flexbox here is the inclusion of grid-gap
which removes a lot of stress with creating whitespace around your grid items. Bootstrap likes to have a gap of 15px around it's columns, but I feel that working in multiples of 8 is easier to scale upwards depending on your page content.
If CSS Grid is absolutely alien to you but you're eager to dive into it, I strongly recommend bookmarking Grid by example by Rachel Andrew and following Her on Twitter.
Flex is for when grid isn't suitable
At this moment in time, the CSS grid spec struggles to "auto-fill" individual grid items. grid-column
allows you to span your grid item an unfixed number of columns, but it does not take into account other items on the same line. If you know where your dynamic grid item will start will, then you can do...
.grid-item {
grid-column: 4 / -1;
}
which will stretch the item to the end of the line from the 4th column. But as you can see, you would have to be aware of explicit grid item(s) previously on the same line. That's not at all responsive!
Thanks for reading!
Top comments (10)
Hi
I wonder if you can help me, I still in the learning phase, I ยดve made a layout using css grid, but its not responsive although Iยดve used the :
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
my layout is in:~
codepen.io/fretagi/pen/qBaPExy
When you use grid-column on a grid containers children, you lose the responsive ability unless you set it again in a media query.
Auto-fit/auto-fill works best with equal size elements. If you're trying to make a traditional website page structure using grid (highly recommended), then look into grid-template-area
Thanks!
Thanks a lot, I was under impression that I was doing something wrong
change the value of minmax
Hi Kyle,
This is Mike. Thanks for your sharing. I've got a question about navbar, how can I only use grid to make a responsive navbar?
Either you use media queries to change the column widths as you go down in screen width, or you use minmax on equal size columns to dictate what the smallest width a part of the navbar can be.
It depends on how your navbar will look.
Thanks!
I think you cannot do that, media query is required for navigation bar to became "responsive" as "Hamburger style"
Hi, its really nice article. Btw, do you have any tricks to use responsive font size without media query ? I usually use media query to resize the font, but the font size is not scaling in the larger device screen, its size just fixed based on i defined in media query
You can use calc combined with media queries.
font-size: calc(16px + 0.5vw);
This will scale your font with the width of the screen. Of course, the caveat being that on a TV or abnormally ultra wide screen, you'll have issues with text being huge. So you'll need to use media queries to tame it.
Thanks!
Thanks for sharing this.