What do you want to learn?
Skip to main content
Modern Web Layout with Flexbox and CSS Grid
by Brian Treese
Explore the modern world of web layout with the Flexible Box Module and CSS Grid Layout.
Start CourseBookmarkAdd to Channel
Table of contents
Layout in the print world is easy. Layout in the web world, well, it's hard. At least it has been until recently. Hi, I'm Brian Treese with Pluralsight, and in this course we're going to see why modern web layout is about to get much, much better. We're going to dig in and explore the two CSS technologies that have completely reimagined the world of web layout as we know it, Flexbox and CSS Grid Layout, but we can't move forward without first understanding where we've been and how we've gotten here. So let's first begin with a little history of layout on the web.
A Little History
In the early days of the web, there wasn't much to web layout. Basically, everything was a single column, and that was pretty horrible. Then, someone discovered that they could use HTML tables to get their content into columns and start doing some pretty cool stuff. Oftentimes a lot of extra junk had to be added to the code to achieve the look. Things like transparent spacer GIF images for example, and extra table cells that otherwise wouldn't be needed. This lasted for quite some time, and was really the web layout standard. Slowly stuff happened that made things better like the evolution of CSS 1, which brought with it revolutionary items like margin, padding, alignment, and even floats. And then came CSS 2 and the real push for true separation of concerns. It was advised that developers begin to write more semantic markup, clear of instructions on how the page will look and feel, and then use external CSS to completely control the layout and design. The browser support issue then began to immerge, which kept developers building in tables in order to gain the most support with the least amount of resistance. As more and more devices and displays entered the scene, the great debate of fixed width verse fluid width sites arose. Some developers and designers felt that the only way to get predictable results on how their designs would look regardless of the display constraints was to work with a fixed width design based off the lowest common denominator, usually somewhere around 800 pixels wide by 600 pixels tall. Others felt that their site should be fluid to better accommodate different viewport dimensions. This brought with it a whole bunch of challenges that required many different hacks and workarounds. Finally the push for a separation of concerns won and many developers ditched table-based layouts in favor of float-based layouts, which again, since they were a bit of a hack, brought with them more challenges, to clear or not to clear. How will this affect things? After breaking away from table-based layouts, we started having to do things like faking the look of equal height columns with various faux column techniques. The most popular of which was probably the repeated background technique. Then we got to a point where there were so many different devices with different dimensions and resolutions on the market that we had to accept responsive design systems, and this meant that many would switch over to float-based responsive grid systems, which brings us to where we are today. This is still the predominant layout technique still in play on the web. Well, we're on the verge of a major change here, and that's likely why you're watching this course, because you know the web layout landscape is about to change dramatically, and those who do not get on board will be like those who raved about tables well into the floats era. A change is coming my friends, and in this course we're going to get up to speed with the future of layout on the web. So coming up in the next module, we'll jump into Flexbox, and then later on we'll explore CSS grid layout, and finally we'll wrap everything up by discussing some gotchas, browser support for Flexbox and grid, and then some resources to make working with them a little easier.
Flexbox, short for flexible box module, an extension of the display property, is a set of CSS properties for creating flexible layouts, distributing extra space, and aligning content for items within a given container. The previous layout modes from CSS 2.1, block, inline, table, and positioning do not provide enough flexibility and control for the web as we know it today. It's become hacky and awkward to lay out some more complex web applications, which is why flexbox has been created. Flex layout provides the ability to arrange items in any direction, left to right, right to left, top to bottom, or bottom to top. It provides the ability to easily reverse or rearrange the visual display order of a set of items. It provides the ability to lay items out linearly without wrapping or to force them to wrap when there isn't enough room. And, it provides the ability to stretch and align items in relation to their parent container. Before digging into the code that makes all of this magic possible, it's important that we first cover some basic concepts and terminology to create a solid foundation to build off of. So, in the next section we'll get started with these basics in terminology.
Flexbox the Basics
In this section, we'll cover some of the core concepts of the flex layout box model, and terminology regarding the specification. Understanding these concepts and terminology is key to developing a deep understanding of the way that it works. Flexbox is all about the relationship between a parent container and its direct descendant child items. This parent container is known as the flex container, and the direct descendants of this container are referred to as the flex items. The flex items flow along what is known as the main axis, which by default is from left to right. The main start is found at the beginning of the flex container, and is where the flex items will begin to flow. These items will flow to the main end, which is found at the opposing side of the flex container. The length from the main start to the main end is known as the main size. The flex container's cross axis runs perpendicular to the main axis. And just like the main axis, the cross axis has a cross start, a cross end, and a cross size. Okay, so now that we've got these covered, in the next section let's dig into the inner workings of the flex container.
The Flex Container
As we learned in the previous clip, flexbox is all about the relationship between a parent container, the flex container, and its direct descendant child items or flex items. This flex container forms the containing block for its flex items and acts very similar to other block level items. To establish an element as a flex container, we use a property we should already be familiar with, the display property; however, instead of using the values that we may already be using such as inline, inline block, block, and table, we will now use a new value, flex. As we can see, the flex property shifts the items into a flex mode. And if we add a border to the flex-container, we can see that it acts the same as a normal block level element. Notice how the flex-items within the container are now side by side instead of stacked on top of each other as they normally would be. I know cool, right? But that's not it for flexbox and the display property, we also have the inline-flex value. Instead of creating a container that acts similar to other block level containers, this value creates a container that acts similar to other inline block level containers by sort of shrink wrapping its contents. So this container will now only take up the width that its children require to display properly. So that's a wrap for now on what it means to be a flex container. Next, we'll take a look at how we can control the direction that flex items flow within these flex containers.
Flex Flow Direction
With flexbox there are various properties, some of which can be applied to the flex container, and others that can be applied to the individual flex items. For the first part of this module, we'll be focusing on those that are applied to the flex container, and then get into those for the flex items a little later on. As we saw in the previous example, by default flex items will flow horizontally from left to right within the container. This is because the flex items flow along what is known as the main axis. And as we saw earlier, the main axis flows from the flex start on the left to the flex end on the right by default. If we want this to act differently, we can change this. To do so, we will use a new property, flex-direction. The default flex-direction is row. So we can see that by adding a flex-direction of row, nothing is changed. If we want the items to flow from right to left, we can do so by setting the flex-direction to row-reverse. As we can see, the order of our items has been reversed. This is because what we have done is we have reversed the main axis from left to right to right to left. If we want our items to flow vertically instead, we will need to again change the main axis. To make our items flow from top to bottom, we set the flex- direction to column, and then we can reverse this as well by setting flex-direction to column-reverse. Now, the main axis goes from bottom to top. So with flexbox, it's pretty easy to quickly alter the way that items flow throughout a given container, but so far we've only looked at examples where there's enough room to contain the flex items without needing to wrap. So how does it work when there are too many items to fit in the container? Well, we'll look at that next.
Flex Line Wrapping
So up to this point we've had plenty of room to accommodate our flex items within their container without needing to decide what should happen when there's not enough room to accommodate them. Well, in this section we'll explore how flex items respond when there's not enough room, and the ways that we can change their behavior to suit our needs. Something many of us have probably done before is use the text-wrap property. What's great about this is that flex line wrapping works in a very similar manner. A flex container like text can have single line or multiline formatting. Single line formatting prevents the content from wrapping even when there's not enough room for it to fit; whereas, multiline formatting forces it to break and wrap to another line. If we want to prevent text from wrapping, we set text-wrap to nowrap, and this will keep it all on one line. This sort of behavior is the default for our flex container. The flex-wrap property is what we use to control how items will wrap, or not wrap. Since no wrap is the default, if we add a value of nowrap, we will see that nothing changes. If we want the items to wrap, we will want to set flex-wrap to wrap. Now we can see the items wrap in rows when there's not enough room. If we want to flip this and make it so items wrap above the first row when we run out of room, we can set the flex-wrap to wrap-reverse. Now we can see that everything remains the same except the rows flow from bottom to top instead of top to bottom. Something to keep in mind with all of the properties that we can set on a flex container is that the way that they work is based off of the main axis. So if we flip the main axis using our flex-direction property, we will see that the wrapping of these items changes accordingly. And if we instead use column-reverse, we will see that the items flip and wrap in the other direction. We can even use shorthand to combine both the flex-direction property and the flex-wrap property using flex-flow. For example, here we have our flex-container and flex-items using the defaults. If we set flex-flow to column and wrap, we will see that they now flow vertically and wrap vertically as well. And if we were to change flex-flow to something like row-reverse and wrap-reverse, we can see how things would change there, so some pretty cool stuff happening here. Now that we understand how to control direction and wrapping, let's take a look at how we can control and manipulate the display order of flex items.
Flexbox is exciting because it gives us so much power and flexibility with such great ease, and if you haven't been impressed with it so far, I would expect that to change after you see how easy it is to control the display order of flex items. Yep, you heard that right. You can easily change the order flex items are displayed within their container. By default, the display order matches the source order within the document. If we want to change that, we can place them into a new ordinal group. By default, all flex items within a container are placed into one ordinal group that has a value of 0. We can use a new property called order to change the display order. If we were to take say the fourth item, and set its order to 0, we can see that nothing changes since they all have the default value of 0. But what if we were to set its order to 1? Well, we can see that it moves it to the very end. So the fourth item is now on its own ordinal group with a larger value than the default value of 0, so it comes after all of those in the 0 group, which is everything else. The ordinal groups of items are place in order from smallest to largest within the container. Now, let's take the second item and give it an order of 1 as well. We can see that it's now moved to the end and placed just before the fourth item. There are a couple of things going on here. First, the item moves to the end because it's now in the second ordinal group that has a value of 1, which is greater than 0, so it's place afterward. It's then placed before the fourth item because it comes before the fourth item in the source order of the page, and they are in the same ordinal group. So if you think about what's going on, it's really acting exactly the same as it does when it's in the default ordinal group, 2 comes before 4, it just happens to have a third item that's in between them in the default. We can also use negative values with order. If we change the order from 1 to -1, we will see that the items move to the beginning of the flex container, and this of course happens because -1 is smaller than 0. While this reordering of content is very exciting, there are some special things to consider regarding the accessibility of the reordered content. The order property only changes the visual order of the content, and not the source order. This means that assistive technologies that sequentially navigate the source code of a document will read it in the order of the source, and not this modified order. This will also be the case for those who use the keyboard to navigate web pages. The key is to use order only to alter the items for visual purposes and not for logical reordering of content. Okay, with order out of the way, let's examine the flexibility of flex items, and how we can control how extra space is distributed amongst them.
Perhaps the most notable component of flexbox is the ability to make flex items flex, to shrink and grow to fill available space within the flex container. In this modern era of web design, everything is flexible in order to accommodate the vast array of devices, screen dimensions, and pixel densities. This is why the flexible box module was created, to allow us to more easily create flexible layouts that can change and adapt to their viewing environment. So, making flex items flexible is core to the foundation of flexbox. This flexibility is controlled on the individual flex items themselves. First we have the flex grow factor, which controls how much a given item in a row or column will stretch relative to the other items within that row or column in order to fill up the positive free space. We can set the flex grow factor using a flex-grow property. If we set it to a value of 1, we can see that the flex items will grow to fill the available space equally. But what if we want one of the items to be larger than the others? Well, we can simply set its own flex-grow to a larger number like 4. This means that when there's extra space around the items, this one will grow to a factor of 4 while the others will only grow at a factor of 1. Then we have the flex shrink factor, which uses the flex-shrink property. As you may have already guessed, this property is the opposite of the flex-grow property. It controls how the space is distributed when there's not enough space for the items to fit. In order to see this property in action, let's add a width to the items so that they're forced to grow. This width would make the items larger than the container, but since they are flex items they flex to fit the area evenly. If we set flex-shrink to 2 on the first item, we will see that it has the opposite effect of the flex-grow property, removing more extra space from the first item than it does from each of the other items. If we set it to 0, we will see that it maintains its original size, the width that we set, while the others shrink. And finally, we have the flex-basis property. Flex-basis sets the initial size of the items before the extra space is distributed. It shares many similarities with the width property, and in fact even uses the exact same length values, meaning pixels, points, ems, rems, or percentages. If we set a flex-basis on the first item to 10em, we can see that it starts at 10em wide, while all the others have a default value of auto, making them shrink up to contain their content. If we were to then set a flex-grow of 1 to all the items, we will see that the first item is wider because it starts at 10em and then adds the same portion of extra space to it as it does the others. Although these three properties can be set individually, it's likely that we will want to use a shorthand version most of the time. The flex shorthand is added using the flex property with values in the order of flex-grow, flex-shrink, and flex-basis. So if we set flex on our items to 0, 1, and auto, we can see that the items do not grow to fill the available space since the flex-grow factor is set to 0. But if we shrink the container up, we will see that the items do shrink by a factor of 1 since the shrink factor is set to 1. If we were to change the flex-shrink property to 0, we will see that the items will not shrink below, or grow above the flex-basis. So now that we've covered some of the concepts behind the flexibility of flexbox, let's take a look at another brilliant feature, alignment.
In CSS 2.1, we often found it very difficult to align items when it seemed like it should be fairly trivial. To vertically center an item within a given container, it required some very hacky CSS. Well, flexbox leverages the CSS box alignment module, which allows us to use simple keywords to align items along the flex containers main and cross axis. Flexbox alignment can be handled in two different ways, it can be applied to all the flex items in a given container via the justify-content, align-items, or align-content properties, or it can be applied to the individual flex items themselves via the align-self property. Let's start with the flex container properties. The justify-content property allows us to align the flex container's items along the main axis. The default value of flex-start will place the items at the beginning of the main axis, known as the main start. We can quickly reverse this by using a value of flex-end instead. Now remember, the justify-content property aligns items based on the main axis, so if we were to flip the main axis using the flex-direction property, we can now see that the items are aligned at the bottom because that becomes the new flex-end location. And we can easily vertically center these items by applying a value of center to the justify-content property while we have the main axis flipped. That's right, no more crazy hacks needed to do something so simple. And if we flip the main axis back, we can see that these items are now aligned horizontally in the center, something that was definitely tricky with a set of floated block level elements in the past. Besides these more basic alignment capabilities, justify-content also allows us to evenly distribute items by dividing up the extra space and adding it in between each of the items via the space-between value. And similarly, we can use the space-around value to add space before the first and after the last item. Notice how the space before the first item and after the last item is smaller than the space in between each of these items? Well, that's because it's actually half the space than between the items. The extra space is divided up and applied to both the left and right side of the flex items, and those items sit next to each other, so the extra space bumps up against each other making it twice as large as it is on the ends. Then we have the align-items property, which will align the flex items along the cross axis. If we set align-items to a value of flex-start, we can see that all the items are aligned to the top of the container. Why does this happen? Well, the align-items property will align the flex items along the cross axis, and in this case the cross axis is vertical and runs top to bottom, meaning that the cross start is at the top of the container. If we flip these axes with the flex-direction property, we can see that the items are aligned differently because the cross axis has changed. If we flip it back and add a value of flex-end, we will see that the items are now aligned to the end of the cross axis, which is the bottom of the container. And if we want to vertical align these items in the middle, well, we can do that too by adding a value of center. So much easier than the old hacks and workarounds that we used to have to use. And we even have a couple more interesting alignment capabilities with the align-items property. If we have text in our items, we can actually align the items so that the baseline of the text in each item will line up using the baseline value. And if we want all the items to take up the entire height of the container, we can use a value of stretch, which is also the default value. This will stretch the items over the entire cross size of the flex container. If we need to align any individual item uniquely, we can do so on the individual item using the align-self property. For example, if we want to align say this guy to the top, we can do so by setting align-self to flex-start. And if we want to align this guy to the bottom, we can do so using flex-end. And maybe we want this guy to stretch so we use a value of stretch. So it's pretty nice and easy to align items when we have a single line of flex items, but what about when we have items that wrap onto multiple lines? Well, this is where the align-content property comes in. It's used to align lines within a flex container along the cross axis when there's extra space available. It will not do anything to single line flex containers. So here we can see that our flex container is pretty tall and all of the items fill the container's height, consuming and dividing all of the extra space. If we don't want this to happen, we could set the align-content property to a value of flex-start. We can see that the items jump up to the top of the flex-container. Align-content does for lines of items within a flex-container what justify-content does for flex-items, except it applies its alignment along the cross axis. So if we don't want to use flex-start, we can use flex-end, or we can use center, or space-between, or space-around, or the default, stretch. So aligning stuff on the web just got a lot better, and our lives just got much easier. Thanks flexbox. So now that we have an understanding of how all the flexbox properties are used and how they work, let's explore some real world use cases for them.
Flexbox in the Real World
Okay, so now we've discussed what flexbox is, how it works, and have explored many of its different properties and values. So now it's time to take a look at it in action. There's really no limit to what flexbox can be used for, so what I'm about to show you is just to get your creativity going. I'm going to show you how to use flexbox to solve a couple of common issues that normally require some not so common solutions. First up, we can create simpler and more elegant grid systems for use within our projects. Oftentimes when using a grid system within a project, we'll use a bunch of div containers with widths and floats. They generally work well, but flexbox provides a much more elegant way with more flexibility, pun intended. In the past, if we wanted to put two items side by side that take up 50% width, we'd have to float them, give them a width, and then clear the floats, right? Well, with flexbox, we simply give the items a flex value of 1, perfectly side-by-side, no clearing needed, and responsive as heck. And what happens if the content on one side is longer than the other, and we want them to have the same height? We used to have to add some sort of min height or something. Well, not anymore. Now with flexbox it will just work the way we want it to. What if we want three equal width columns? Easy, just add them with a flex of 1, and it still works. And four? No prob, just add them and they'll keep working. What if we want to vary the width of a column, like if we want one 50% and two 25% wide columns next to it? Easy, set flex on the first one to 0, 0, and 50%, then make sure you have a flex value of 1 on the other 2. Super easy. You can even handle alignment of grid columns vertically. Aligning a bunch of different height columns along the bottom used to be pretty difficult. Not with flexbox. Just use the align-items property on the flex container, set it to flex-end. Want them aligned in the middle instead? No problem, switch it to center. It's so easy I actually feel sorry for all of us who have been dealing with layout on the web because it's been such a struggle until now. We can take grid systems even further, but you get the idea. The bottom line is that flexbox was made for layout, float was not. Another example of layout made better with flexbox is what is referred to as the Holy Grail layout. You know the one with the header, two equal sidebars, one on each side, content in the middle, and then a footer at the bottom. Yeah, we used to get all crazy and hacky with floats and clears and whatnot, but we just don't have to do that anymore. For example, here we have some containers on a page. A header, main, and footer are all on the same level. The nav, article, and a side are nested within the main. We need to make the first level into flex containers so we set the display to flex on the body. Then, we flip the direction to columns so that they will stack vertically. Then, we make the main into a flex container as well. We can then add flex to the main content article, then set the nav and a side to be flexible as well. There, now we have a nice resizable and flexible Holy Grail layout. We can even easily add some basic responsiveness to this layout by stacking the items when they would break. (Clicking) And, we can flop the sidebars if we want them both on the right-side; a simple order change is all that's needed. Boom, much easier than the old way, right? Flexbox is also really good at handling containers that will have an unknown number of items in them. For example, let's say for normal everyday members of our site we show these three buttons in the section. And then for moderator members, they have five total buttons available. Flexbox will easily accommodate these two different scenarios without us having to do anything extra. This would've normally taken extra classes and extra styling, but now it takes practically no effort at all. Like I said earlier, the sky is really the limit when using flexbox and these are just a few examples of existing problems that many of us face that are really easily solved with flexbox.
So in this module we learned about the new CSS flexible box module. We learned that it's a set of CSS properties for creating flexible layouts, distributing extra space, and aligning content for items within a given container. We learned that flexbox is all about the relationship between a parent container and its direct descendant child items. We learned that flex items flow along the main axis and can be rotated to flow along the cross axis. By default, these items will float horizontally in rows, but we can flip that if we want to with flex-direction so that they flow vertically in columns. We learned that there are many different ways to align flex items, both on the container, and on the individual items as well. We learned that there are many ways to control how flex items stretch, shrink, and grow. We learned that we can very easily reorder the visual display order of an individual flex item or a group of flex items with the order property. And, we looked at a few real world examples of how we can put flexbox to use today. So coming up in the next module we'll dive into the CSS Grid Layout module, and how to use it, and then later we'll look at some gotchas, browser support for flexbox and grid, and then get into some resources that make working with them a little easier.
CSS Grid Layout
So flexbox is pretty amazing, and it makes layout on the web so much more delightful for us as developers, but I truly believe the best has yet to be seen. The new CSS Grid Layout module is likely to blow your mind. Flexbox and CSS grid share some similarities, but the main difference is that flexbox controls how items flow in one dimension, whereas, grid controls how items flow in two dimensions. Flexbox items flow in a similar fashion to the way that text content flows on the web, meaning that items flow in a straight line in one dimension or in a broken line if there's not enough room and they're allowed to wrap. Flexbox is great at handling alignment, distribution, and order of content in space. CSS grid on the other hand is suited to lay items out in both dimensions. The core difference between flexbox and grid is that flexbox lets content size itself based on the space available or the dimensions of the content itself, and grid specifies nothing about how the individual items themselves should be sized, and instead relies on various grid lines being defined on the grid container for its sizing info. CSS grid is more about creating a bunch of virtual areas, and then placing all items within them. The simplest way to understand how grid works is to think of old table-based layout concepts. Items are aligned in rows and columns, and then exist in or span across cells, but they do not rely on content structure like tables do, so they allow for much greater flexibility. The flexibility of CSS grid lends itself to responsive web design, making it easy to adapt layouts in display order based on the size of the viewport and space available. Before digging into the code that makes all of this CSS grid layout magic possible, it's important that we first cover some basic concepts and terminology to create a solid foundation to build off of. So in the next section, we'll get started with these basics in terminology.
Grid Layout the Basics
In this section, we will cover some of the core concepts of the CSS grid layout module, and terminology regarding the specification. Understanding these concepts and terminology is key to developing a deep understanding of the way that it works. CSS grid, like flexbox, is all about the relationship between a parent container and its child items. This parent container is known as the grid container, which contains what are known as grid items. This grid container establishes a grid context for its children. The grid container is also known as the grid. A grid is made up of two sets of lines known as grid lines. One set of lines defines the columns for the grid. These lines run along what is known as the column axis. Then, there's another set of lines that defines the rows for the grid, and these lines run perpendicular to the column axis along what is known as the row axis. These grid lines together make up what are known as grid tracks. A grid track is simply a generic term for grid rows or grid columns. They are created by the space between two consecutive row or column lines, and are given a size, which controls how tall a row can be or how wide a column can be. Where grid rows and grid columns intersect is where we find what are known as grid cells, and these are similar to table cells, and are the smallest units of the grid that we can place items into. And finally, we have what are known as grid areas, which are essentially any portion of the grid that is contained by four grid lines. Okay, so now that we have the core concepts and terminology out of the way, we need to enable grid layout in our browser so that we can see it in action. Next, let's look at how we do that.
Enabling Grid in Various Browsers
CSS grid layout is a newer specification that is still in the process of being developed. It's so new in fact that browsers are still working on their implementation. So before we can begin experimenting with CSS grid layout, we will need to first enable it. Actually, if you're using IE10+ or Microsoft Edge, you'll just need to use the MS prefix along with an older syntax, but it will otherwise just work because it's already enabled. Likewise, if you're using Website Nightly, it's just enabled, so you won't need to do anything except use the WebKit prefix. If you're using Chrome, you'll need to enable the experimental web platform features flag. To do this, navigate to chrome://flags/#enable-experimental-web-platform-features, and then enable the flag. Then you'll be good to go, and it won't require a prefixed version. If you're using Opera, just like Chrome, you'll need to enable the experimental web platform features flag. You'll need to navigate to opera://flags/#enable-experimental-web-platform-features, and then enable the flag. And finally, if you're using Firefox, you'll need to enable the layout.css.grid.enable flag by going to about:config, searching, then right-clicking and hitting Toggle. Okay, phew. Now that we've got our browsers all set up, let's begin by exploring how we can set up and work with grids.
Setting up a Grid
Grid, like flexbox, needs a container element. This container initializes the grid layout for its children items. So how do we set up a container as a grid? Well, just like with flexbox we use the display property, only this time we use a value of grid. And, as we can see this has done something to our elements, but it looks nothing like a grid. Since we have a border on the grid-container, we can see that this container spreads the entire width, just as a normal block level element would. And we can see that establishing the grid context forces the grid-items to take only the space they need and stack on top of each other. Like flexbox, we have the ability to sort of shrink wrap the grid items with the inline-grid property. When using inline-grid, we can see that our grid-container now takes up only as much space as its items require. So far what we have done doesn't look much like a grid though, does it? That's because with grid we need to define columns and rows for our items to be placed within. To do this, we will use a couple of new CSS properties. To define our grid columns, we will use the grid-template-columns property. And to define our grid rows, we will use the grid-template-rows property. The way that we use these two properties is to define a width for our column or a height for our row, then follow it with another width for another column or height for another row, and so on until we have the amount of columns, rows, and gutters that we need. So let's create four columns at 6em wide separated by 1em gutters. To do this, we add these values in this order to the grid-template-columns property. Well, some stuff changed, but it's still not looking very grid like. This is because the grid does not actually control the size of its items. It simply creates virtual areas for the grid items to live. The next step is to place our items into these areas that we've defined. This is done by specifying at which grid lines they should begin and end. We do this by calling each item individually, giving them grid-column-start, grid-column-end, grid-row-start, and grid-row-end values. Let's remove all but a single grid item so that it's easier to see what's happening. Now, if we want this item to start in the upper left corner and be 6em wide, then we need to give it a grid-column-start of 1 because that's the first vertical grid line. Then, we give it a grid-column-end of 2 because that's our next vertical grid line, and it's 6em from the first one. Okay, cool. So how does this look? Well, it doesn't look like anything too special; it's just a box in the corner. The real power of CSS grid is what we can now do with this box. Let's say we want it to actually be placed in the second column over. Easy right? We simply change our grid-column-start to 2, and our grid-column-end to 3. Woah, what happened here? Why is it narrower? Well, if we recall when we set this grid up, we actually wanted 1em gutters, so the second column is actually the gutter that's 1em wide. So it's important to keep in mind with CSS grid, gutters are simply columns and rows like everything else, we simply avoid placing items into them. So we just need to change our item to have a grid-column-start of 3, and a grid-column-end of 4. And there we go. Now it's technically in the second column. And we can easily do other cool stuff like column-spanning. If we want this item to span two columns for example, we would just set its grid-column-end to 6. Now we can see that this item spans across the second column, the second gutter, and the third column. So, so far we've only been discussing columns and have not set up any rows. Well, grid rows work exactly the same as columns do except they run horizontally. So, to add rows to our grid, we will need to add a grid-template-rows property to our grid container, just as we did with grid-template-columns. And then we divide up the space just as we did with columns, defining rows and gutter heights. So after adding in a row, we can see that our grid-container is now taller. And now we can give our grid-item, grid-row-start, and grid-row-end properties to stretch the item vertically within the container. To get a better visual representation of the grid we created in this section, let's go ahead and add back in all of those other items. So there's our grid with cells that are 6em tall, 6em wide, and separated by gutters that are 1em wide and 1em tall. Here we have been very explicit in the way that we've defined our grid and grid-item placement, but we can leverage some features of Grid Layout to handle this in a more implicit manner. Coming up in the next section, we will take a look at how we would do this with the use of some auto grid features.
Auto Grid Features
In the previous section we defined a grid by explicitly defining rows, columns, and their heights, and widths, and then manually placing these items into these rows and columns. This is all fine and dandy, but we may not always want to do this. We may just want to have grid items that are automatically placed into cells on our grid. If we do not declare item position on the grid, then it will use what is known as the grid auto placement algorithm and automatically size and place items. In this example, we've removed the gutters and are just letting the items lay on the grid using auto placement. We can see that all the items are sized based on the grid track that they are in, and automatically take up one cell. If we were to change the width of one of the columns, we will see that the items within the column will properly adjust to match the width. What you may be noticing about this auto placement is that items flow horizontally from left to right along the row axis, and then top to bottom. This is because there is a grid-auto-flow property, which defaults to a value of row, and by now you may have guessed that this causes all items to flow in a horizontal direction. If we needed to switch this however, we could do so by switching this grid-auto-flow property to a value of column. When we do this, we can see that all of the items will now flow top to bottom, and then left to right. Sometimes we may find it necessary to mix some auto placed items and some explicitly positioned ones. Well, there's nothing wrong with that. We can do whatever we want really. So, if we were to take our second item and set some placement on it, we can see that it will move to the location that we defined, and it will force all other auto placed items to wrap around it accordingly. If we didn't have the need to resize grid items, but just wanted to change the order of them, we can do so using the order property that we saw in use with flexbox in the previous module. If we recall, all items have a default order of 0, so if we want to rearrange them, we will need to give them either a positive or negative value other than 0, and then these items will be moved either before or after all other non-placed items. With the auto grid features, we also have a notion of implicit grid lines. These are grid lines that we have not explicitly defined ourselves using grid-template-rows and grid-template-columns. So far in this module we've only seen explicit grid lines. Implicit grid lines are created when we place an item in a grid track outside of these explicitly defined grid lines. So, if we were to add say an eighth and ninth item, even though we only have two rows defined explicitly, we will see that a new implicit grid track has been created below these rows, and our ninth item has been placed within it. So that's pretty much a wrap on the auto grid features. So next we'll try to clean up the amount of CSS needed, and the complexity involved with creating a grid by looking at shorthand for CSS grid properties.
In the examples we've seen so far, we have explicitly defined aspects of our grid item placement, and in most cases this meant defining a bunch of related properties individually. Well, this doesn't have to be the case. There are a few shorthand properties that we can and should use wherever possible. First up, we can avoid defining grid-template-columns and grid-template-rows individually. We can actually define them both in one line using the grid property on the grid container. In order to do this, we need to first add our column values, followed by a slash, and then our row values. As we can see, it looks as we'd expect, but the code is now a little bit more simple. Next up, there's really no reason to define a grid-row-start or end or grid-column-start or end because we have the grid-row and grid-column properties. These properties work by accepting both the start and end values for the item divided by a slash. So, if we wanted our item to start at the second grid column line, and end at the fourth, we would add a grid-column property with a value of 2/4. And if we wanted it to start at the second grid row line, and end at the third grid row line, we would add a grid-row value of 2/3. Pretty cool, right? But we may not even need the two different column and row properties because we also have a grid-area property that will accept all four values. The order of these values is row-start/column-start/row-end/column-end. So we could do the same example with a grid-area of 2/2/3/4. We can also take advantage of the span keyword to control how our grid items span across grid lines. With span, we still need to tell the item what grid line we want it to start on, but then we can use the span keyword with a value that will let the browser know that we want this item to span this many grid tracks, and it can be used either in the column or row direction. One other thing that can be a little cumbersome when it comes to grid is defining all the grid lines individually. Luckily, we have some help with this as well. In cases where we have repeated patterns, we can use the repeat keyword to repeat grid tracks without defining each grid line individually. Repeat works by setting the number of times that we want a pattern to repeat, followed by the actual pattern to repeat. So in this case, we have defined the first column of 6em, and then we use the repeat keyword. The first value that we add is the number of times we want the pattern to repeat. For this example, we will repeat the pattern three times. Then, we set up the pattern that we want to repeat. Here, we have a 1em gutter, followed by a 6em column that will be repeated 3 times. A repeated pattern can be a simple one like this example, or it can be a much more complex pattern. It really doesn't matter, but it sure can make things easier and less cumbersome. So now we know how to write Grid code like the pros by using different shorthand properties. Well, coming up in the next section, we'll take it even further when we look at how we can use custom named grid lines and grid areas.
Naming Grid Lines & Grid Areas
So using the grid shorthand properties and keywords is a great help. It makes code much more simple, clean, and easier to read. But we may find that when we need to target specific grid lines or grid areas for grid item placement, referring to these lines by number makes it more difficult to use because we always have to count the lines to know which ones we need. Luckily, CSS grid allows us to name our grid lines whatever we want instead. We do this by adding our grid line names inside of square brackets in the grid containers grid-template-column and grid-template-row properties. A nice example of where this may make sense is when we create an overall page layout where we may have something like main-content-start, main-content-end, sidebar-start, and sidebar-end. Then, when we want to place our individual grid items on these lines, it makes it easier for us to find what we're looking for. Obviously we would know that we want our main-content item to start on the main-content-start, and end at main-content-end, and likewise for our sidebar. And, we can still span these items just like we can when we're not using name grid lines. So for our header, we may want to stretch it the entire width, so we would use main-content-start, and then have it stretch all the way to sidebar-end. It's even possible for us to name grid lines with the same name, and then refer to them by number. For example, if I had an image gallery and want my thumbnails to be displayed in a grid format, I could define the grid tracks as image-column, gutter, and image-row, gutter. Then, when placing my thumbnails into these cells, it's easier to tell them where to start and end even though I still need to use numbering. At least it narrows it down a little bit while making it easier to understand and maintain. Besides name grid lines, we can also create name grid areas. If we recall back to what a grid area is, we remember that it's simply any area on a grid contained by four grid lines. So in order to create a named grid area, we have to define the name grid area on our elements within the grid-area property before we define our grid. Let's apply this to a media object example. Let's say that our media object has a title, so we create a grid-area named title on the title selector. Then, we have a thumbnail, so we create a grid-area named thumbnail on the thumbnail selector. And then we have a content section, so we create a grid-area named content on the content selector. Next, we set up our grid. We add display:grid and then define grid-template-columns and grid-template-rows just as we always have. After this, we use our custom named grid areas with a new property, grid-template-areas. Here, we want our title section to be on its own row, stretching the width of the grid. In order to do this, we repeat its name once for each column inside quotes. By repeating its name for each column, we are telling the browser that we want the item to span these grid tracks. Next, we want to add an empty row for our horizontal gutter, so we can do this by adding a new set of quotes. Inside of these quotes, we need to let the browser know that these grid cells should be empty, and that's done by adding a period. We need to be sure to add a space in between these periods because that's how the browser knows that the grid track begins and ends. If we just run them together, the grid will associate them as a one column designation, which is not what we want. Then, to move to the next row, we add a new set of quotes, and in this case we want the thumbnail to take up one column, so we put thumbnail in the grid-area in the first track. We then add a period for our gutter since we want some space between the thumbnail and the content. And finally, we add content and place our content item. So naming our grid lines and grid areas can provide clarity and intent that will make it easier to come back to this code later on, and quickly get up to speed with what's going on. So now that we've got a grasp on naming our grid lines and grid areas, let's take a look at a few more items unique to CSS grid layout, auto keyword, a fractional sizing unit, and overlapping and layering items.
Auto, fr, & Overlapping/Layering Items
So far we've covered much of what CSS grid layout has to offer, but there's a few things that we have not covered yet. One is how grid tracks work with the auto keyword. In the examples we've seen so far, we've explicitly defined the width of our grid columns and the height of our grid rows. This can make things fairly ridged, which may be okay, but sometimes we will not want this. Sometimes we will want rows and columns to be auto-sized based on the height or width of their content. This is where we can use the auto keyword. For example, in this grid, we have a row that's going to have some dynamic content, so we set it to auto. Then, the row will size itself based on that content. If the content becomes longer, the row will grow in height. This also really lends itself to responsive design because when the viewport shrinks, the content wraps and becomes taller. If it was a fixed height, it would likely break at some point. Next, we have the fractional sizing unit, fr. The fr unit, like auto, can be used to size grid rows and grid columns. It's used to size a grid track based as a fraction of available space. For example, let's say we have a column with a fixed width of 6em. Then, we have a column with 1fr. This means that this one column will take up all of the available space, which is equal to 100% of the width minus the 6em column. If we add another column and set it to 2fr, this means that the available space will now essentially be divided into 3 units, so we have 1 for the first column, and then 2 for the second column. Then, when these are sized, we will see the 6em column, then the 1fr column that's equal to one-third the available space, and then the 2fr column that's equal to two-thirds of the available space. Another potentially useful feature of grid is the ability to overlap and layer items on top of one another. Say for example that we have a grid defined and we want to break one item out having it overlap and layer on top of the other items. If we just have it overlap, it will layer over the items previously defined in the markup, but under the ones that follow it. Well, with grid items we can use z-index, like we would with positioned items to control the stacking order. So if we change the z-index on this item, we can now see that it will overlap and stack on top of all other items. These things will definitely come in handy at some point when using CSS grid layout. So now that we know how to efficiently work with CSS grid, let's take a look at how we can combine it with a box alignment module to control how grid items are aligned within the grid container.
Grid Layout & Box Alignment
We saw the CSS box alignment module in action with flexbox in the previous module. Box alignment is a specification independent of flexbox and grid, and is intended to generalize the alignment of items within their containers. For this course, we won't dive too far into the spec itself, but since we've already seen how it works with flexbox, we'll now take a look at how it works with grid. It's also lacking quite a bit in browser implementation, so we won't spend too much time on it in this course. So the box alignment spec adds a handful of properties that are added either on the grid container or on to individual grid items themselves. The properties that can be applied to the grid container are justify- content, justify-items, align-content, and align-items. Let's take a look at an example using align-content. We begin by defining our grid as we've already seen. We can see that it looks exactly as we'd expect it to based on what we know about grid so far, but if we apply the align-content property with a value of center, we can see that this has changed the way that our grid looks. It actually took all of the items and vertically aligned them in the middle of the grid container. And what if we were to change it to justify-items? Well that will horizontally align the items based on the column that they're in. We can also apply box alignment to the individual grid items themselves if we need to control them individually. The properties that are applied to the grid items are justify-self and align-self. So if we wanted to align this one item to the bottom of its row, we could simply set align-self to a value of end. And there you go. Just more layout power than we could ask for here. So now that we have an understanding of how all the grid layout properties are used, and how they work, let's explore how it would be used in the real world.
Grid in the Real World
So in this module we learned about the new CSS grid layout. We learned that it's a set of CSS properties for creating flexible, two-dimensional layouts, distributing extra space, and aligning content for items within a given container. We learned that grid is all about the relationship between a parent container, and its direct descendant child items. We learned how to set up a grid using display:grid, and inline-grid, creating grid rows and columns, and placing grid items into these grids. We learned common grid shorthand properties that will keep our code cleaner, more organized, and even make more sense. We explored auto grid features and how we can do a lot with a little bit of setup. We looked at how we can make things even more simple by providing our own custom names for grid lines, and defining our own custom name grid areas. We covered how we can use the upcoming box alignment module to further control how our grid containers align the items within, and how individual items can override this alignment if needed. And, we looked at the most common real world examples of how we can put grid to use today. Coming up in the next module, we'll cover some gotchas when using both flexbox and CSS grid layout, browser support for flexbox and grid, and then some resources to make working with them a little easier.
Gotchas, Browser Support, & Resources
Both flexbox and CSS grid layout are extremely exciting for those of us who have worked with any of the other web layout options in the past. They truly are a breath of fresh air, but they are relatively new, grid even more so, meaning there's definitely some stuff to consider and be on the lookout for when you decide to use them. In this module we will discuss some of these things to consider when using them, we will cover their browser support, or lack thereof, we will cover some of the best resources to make working with these technologies easier, and those that will keep us on top of the game as they continue to evolve, and then, we'll wrap up everything, and send you out on your way to web layout heaven. So let's begin with some common flexbox and grid layout gotchas.
Flexbox and grid layout are the shiny new toys when it comes to CSS layout, and it can be easy to get all starry-eyed, move fast, and gloss over some important concepts. For one, it's important to note that when using these modern layout techniques, both have some custom implementations in Internet Explorer. We will more closely examine browser support in the next section, but it's important to know that they may go back a little further than you'd expect in IE and Edge, but you may have to provide some prefixes and a little different syntax when doing so. The next very important item on the list is that both provide source order independence between the design of the content, and the actual flow in the DOM. While this gives us great power, it also means that we really need to consider the accessibility of our content, and ensure that we continue to provide meaningful flow. With these technologies, semantics still matter, and the way that we structure our documents shouldn't change, except that they will likely contain fewer containing div elements. We need to continue to first structure our content with the proper semantics as we would want it to be navigated if there were no styles applied at all. It's okay for us to reorder page elements visually if it makes sense, but we need to consider the fact that it will not alter the actually structure of the underlying content. This means that we could end up causing some somewhat strange navigation flows for those that use the keyboard or assistive technologies to navigate web pages. It's important that we are mindful of these decisions as we make them. Another important item that I did not cover in the grid module is the notion of sub grid. I decided not to cover it because it's currently at the risk of being removed in the spec. Sub grid is a keyword that can be used along with grid to allow elements nested deeper within the grid structure to adhere to the grid tracks that are set up on the outer grid container. While this certainly sounds useful, you'll just need to be sure that if you decide to use it, it may be removed down the road. Flexbox is gaining more and more traction by the day, and more and more people are using it. And because more people are actually putting it to work, bugs are being discovered. There's actually quite a few. And rather than go through all of them in this course, I will just point you in the direction of a very nice collection of them, flexbugs. Here, there are loads of details about the bugs that have been found and submitted, and workarounds if any are available. The flexbox spec is much further along than the grid spec, so much so that you can actually help shape the grid spec with your feedback. The CSS working group has created a request for comments page where they're asking for feedback on the current spec before it goes into candidate recommendation. You can find it here. I encourage you to dig into some of what you have seen in this course, and try and apply it to some of your own projects. Then, if you run into any issues, you can submit them to the CSS working group, and hopefully they can fix them. Next we'll take a look at browser support for both flexbox and CSS grid layout.
Browser support for these two specifications is a little strange because Microsoft implemented them early on, and then they changed. For example, flexbox has actually been implemented as far back as IE10, but it wasn't until IE11 that they implemented the current, newer syntax. And there's even a different syntax from around 2009 that used display box instead of display flex, which was supported in older versions of Chrome, Safari, and Firefox. The real good news about flexbox here is that it's widely supported in all modern browsers. In fact, if you take a look at caniuse.com for flexbox, it's pretty much green across the board. I would feel perfectly comfortable using it today, and actually have personally used flexbox in production websites. You'll just need to pay attention to the fact that if you need IE10 support, you'll need to add the custom Microsoft version. Likewise, if you're trying to provide support for older versions of Chrome, Safari, and Firefox, you may need to add an older vendor prefix version of the syntax as well. Browser support for CSS Grid on the other hand is not quite here yet. In fact, if you look at caniuse.com for CSS grid layout, you will see that it has virtually no support, and is nearly red across the board. The thing is, grid is gaining a lot of steam and many are predicting that browser support will arrive in newer versions of modern, Evergreen Browsers in 2016. This is evident by the fact that it's actually already built in to pretty much all browsers, and can be activated by enabling a flag in Chrome, Firefox, and Opera. It's enabled by default in nightly versions of WebKit, and Internet Explorer 10+ and Microsoft Edge have support implemented for a slightly different prefix version of the spec already. With all of the vendors getting on board, it's highly likely that we will be able to take full advantage of CSS grid layout very, very soon. And if we're too impatient and really want to take advantage of it in our sites and applications today, we can use a polyfill. Francois Remy has created a very nice polyfill that mimics the modern spec syntax that can be found on GitHub if you want to go that route. The bottom line is both flexbox and grid are the future of the web. Flexbox support is already here, and while browser support for grid may not be here just yet, it's coming. So now that we have browser support out of the way, let's take a look at some resources that can help guide us, and help keep us up on these technologies as they evolve.
I always recommend finding good resources and references to follow in order to stay on top of your game, so modern web layout is really no different. Here's a few that I recommend. First up, there is web layout expert and enthusiast, Rachel Andrew. Co-founder of Perch CMS, Rachel has been writing about, presenting about, and providing lots of up-to-date details regarding modern web layout tips, trends, and techniques. You can find tons of great information on her website, rachelandrew.co.uk. You can also subscribe to her weekly CSS layout newsletter at csslayout.news. This is one of my favorite resources. It automatically arrives in my inbox every week, it's loaded with tons of great info, and it really helps keep me informed. Rachel also provides the most comprehensive site on the web devoted to CSS grid layout, gridbyexample.com. Here you can look at many great examples that she has put together to demonstrate how grid works, and many different things you can do with it, and the stuff to look out for when using it. She even provides many code examples that you can play with yourself on code bend. It's really great. Next, there's a really nice flexbox resource, Visual Guide to Flexbox Properties. Here, you can see a series of illustrations that clearly demonstrate how the various flexbox properties work. It can be very handy to return to over and over again as you use flexbox, as a refresher, or perhaps as a reference. Next, there's Philip Walton's Solved by Flexbox. This is a great resource that showcases things that were once very difficult to solve with CSS, but are now much easier to solve with flexbox. And of course, what is a course about new CSS technology without mentioning css-tricks.com. Chris Coyier at css-tricks.com has created two wonderful posts, A Complete Guide to Flexbox, and a Complete Guide to Grid. Both of these articles serve as an excellent place to begin to familiarize yourself with the inner workings of both technologies, as well as a reference to return to over and over again when you're stuck or not sure how something works. Of course there's many more resources out there, but these are a few of my favorites. I'm sure you'll find many of your own as you work. Next, we'll recap all that we have covered in this course, and we'll wrap it all up.
So that's about it for this course. The main takeaway is that the future of web layout is here. Gone are the days of using floats and display tables to mimic a true layout system as a new era of web development is ushered in. We are now able to more easily lay items out in a flexible manner and distribute extra space. We are now able to align items in many different ways with greater ease than ever before. We can now easily visually reorder items with ease without positioning or other crazy hacks. We can now very easily flow items in rows and columns and reverse their flow direction if needed. We will soon be able to use a native grid system that will allow us to position and float items in two dimensions. It'll be a flexible grid system that's been developed with modern web applications in mind. We will have the ability to define simple or complex systems of columns and rows, and then place items into these systems contained within their cells or spanning across them or even overlapping each other. The future of web layout is here, and now you know how you can harness its power.
Brian Treese is the Chief Designer at SoCreate, a company building a fun and easy way to turn great ideas into movie & TV show scripts. Technically a Web Designer (he's always loved the aesthetic...
Released15 Jan 2016