Menu Search
Jump to the content X X
Smashing Conf Barcelona

You know, we use ad-blockers as well. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

CSS Grid Gotchas And Stumbling Blocks

In March this year, CSS Grid shipped into production versions of Chrome, Firefox and Safari within weeks of each other. It has been great to see how excited people are about finally being able to use it to solve real problems.

CSS Grid is such a different way of approaching layout that there are a number of common questions I am asked as people start to use the specification. This article aims to answer some of those, and will be one in a series of articles on Smashing Magazine about layouts.

Why Use Grid Instead Of Flexbox? Link

Prior to CSS Grid Layout landing in browsers, many people saw flexbox as the answer to all of our design-related problems. However, flexbox doesn’t provide a grid system any more than floats do, although it does make creating one simpler. A true grid is two-dimensional. The two dimensions are rows and columns, and with grid layout you can control both at once. With flexbox, you choose whether to lay the items out as a row or a column, one or the other and not both.

Here is a simple example which highlights the difference. The first layout uses flexbox to display as many boxes as will fit into the available width. Here we are controlling the layout across the row. We are allowing the flex items to wrap, so they create new rows, but each row is a new flex container. The space distribution happens across the row and so depending on how many items the final row has, they sometimes won’t line up with the items above to make a grid.

Example 1: Flex layout in one dimension

The second example uses Grid to make the same kind of layout, however, you can see that the items in the final row always remain lined up in their columns. This is because with grid we line our items up in rows and columns — two dimensional layout.

Example 2: Grid layout in two dimensions

You can also see in that second example, that with grid layout we don’t need to add anything to the grid item to make the layout. Everything is being set on the container. In a flex layout you have to target the flex item to set the properties of flex-grow, flex-shrink and flex-basis. This is something key to understand about grid layout and is perhaps where much of the confusion people have lies. Grid is mostly about the containing element, whereas all of our previous layout methods have relied on our setting widths on the items in the layout to make something that looks like a grid.

If you take a simplified floated twelve column “grid”, we have to calculate the percentage size of each column, plus the percentage size of each gutter margin. To create items that span multiple columns we need to add up the widths of all the items plus the width of the margins used to separate them.

Example 3: A simple floated grid framework

The same is true for grids created with flexbox. While we create our flex layout on the parent by setting display: flex all of the sizing needs to happen on the individual items. To make a flexbox “grid” we have to stop flexbox doing it’s flexible thing, instead setting percentage widths just as we would be floats. We get some benefit from using flexbox over floats, the ability to use the alignment properties and have full height columns is one of them. However we still don’t have a grid, in both flex and float methods we are creating something that looks like a grid by way of setting the size of items and lining them up.

Example 4: A simple flexbox-based grid framework

With grid all of our sizing happens on the container. Once we have created our grid tracks, we can then tell individual items how many tracks to span, but we have an actual grid. We can completely lose row wrappers as grid already has rows. This also means that we can have items span rows too, in exactly the same way as we span columns. Something that has been very difficult to do before now.

Example 5: A 12-column layout using Grid

Should Grid Be Used For Main Layout And Flexbox For Components? Link

This myth keeps popping up as people start to learn grid layout. Perhaps it comes from the use of grid systems such as those found in Bootstrap or Foundation where we are concerned with placing items on an overall grid. That is certainly one way to use grid layout. I would however move to thinking about the differences I mentioned in the last section. Ask yourself, is this layout one or two dimensional?

If you can take your component and draw a grid over it, with rows and columns. It is two-dimensional — use grid layout for that.

1
A grid has strict rows and columns. Changing the size of an item in a cell in a row or column will change the size of the entire track.

If instead, you want individual items to expand within a row, without respecting what happens in the row above. That’s a flex layout.

2
In this flex layout we want items to arrange themselves by row, and not try to line up as columns.

It doesn’t matter if the item you are trying to lay out is a full page, or a tiny component. What matters is how you want the items inside that layout to distribute space and relate to each other.

Can Grid Track Sizing Be Dictated By Content? Link

We’ve now seen how, when using Grid Layout, we set up the grid and grid sizing on the container. However it is possible for items inside the grid to dictate track sizing. The key thing to remember here is that a change of size in one cell will change the size all along that track. If you don’t want that to happen, you probably want a single dimensional flex layout.

The simplest way in which we see items changing the sizing of their track is when we use auto, which is the default for tracks created in the implicit grid. An auto sized track will expand to contain all of the content placed into it. In the example below I have a two-column layout, adding more content to the right hand column causes the whole row to expand. The second row is also auto sized, again expanding to contain the content.

Exampe 6: A two-column layout with content

We can allow tracks to size within two parameters, for example creating tracks that are at least a minimum size but will still grow to accommodate larger items. We do this with the minmax() function. The first value passed into minmax() being a minimum size for the track, and the maximum the maximum size. Therefore you can form rows that are 200 pixels tall but by setting the maximum as auto ensure that you don’t end up with overflows when there is larger content.

Example 7: minmax() allows fixed height until too much content is entered

We also have some interesting new sizing keywords, that I’ll be having a proper look at in a future article. These work with grid specifically to allow content to change track sizing, and can be found detailed in the CSS Intrinsic and Extrinsic Sizing3 module. The keyword min-content for example, when used for grid track sizing will create a track that displays as small as possible when all soft-wrapping opportunities are taken.

In my example below this means the word opportunities. becomes the widest thing and the track shrinks down to fit that.

Example 8: min-content

The opposite happens if you use max-content — you get a track that stretches as large as possible without wrapping. This may lead to overflow situations, in my example I have set the grid to overflow: scroll so the max-content track is causing a scrollbar.

Example 9: max-content

Once again, the key thing to remember is that this is going to happen right across the track. You need to ensure that items in other cells of that track will also absorb that extra space neatly.

Understanding how to size tracks, and how content will change track sizing is probably one of the things that newcomers to grid layout find most confusing. It’s ok to find this takes a little while to understand — we’ve not had anything that behaves like this before. Play with examples, it is the best way to start to understand how things work.

Can I Do A Masonry Layout With Grid? Link

There is a misconception that grid layout is the same as a Masonry or Pinterest layout. This is generally based on seeing how auto-placement works in grid layout, which at first look seems a bit like Masonry. In this next example I have a layout using auto-placement with grid-auto-flow set to dense. This causes grid to pick items up, take them out of source order and try to backfill gaps in the grid.

Example 10: Using dense packing

However this isn’t really Masonry as we still have a strict grid of rows and columns, and potentially items are taken out of source order. A real Masonry layout would keep things in source order working across the row. Items are pushed up to fill partial spaces left. It’s more like doing flex layout but in both dimensions at once.

4
a Masonry-style Layout currently needs JavaScript, such as this example using macy.js — macyjs.com5. (Large preview6)

You can get the look of Masonry with a grid layout by positioning all of your items but the ability to do an auto-placed Masonry layout isn’t there yet. It is something we are thinking about7 however for future levels of the specification.

How Do I Add Backgrounds And Borders To Grid Areas? Link

While on the subject of things that grid doesn’t do yet, a common request is to style the backgrounds and borders of the grid areas themselves. Can you add borders and visually display the grid? At the current time this isn’t possible, you need to insert an element and style that, this could be an HTML element but could also be some generated content.

In this next example I have added some generated content to the grid, positioned it using line-based placement and then added a background and border to that area.

Example 11: Generated content can be styled to add a background or border to an area

Another thing I sometimes do to get round the lack of backgrounds and borders, is use a single pixel grid gutter — as in this next example.

Example 12: Using a 1px gutter in a contrasting colour to fake cell borders

To be able to have proper styling of areas of the grid we would need to introduce the concept of grid area pseudo-elements, a special sort of generated content. There is an issue raised regarding this8 on the CSS WG GitHub site, so you can follow discussion and add your own thoughts.

Spanning To The End Of The Grid Link

Grid Layout has a concept of the implicit and explicit grid. The Explicit grid is the grid that we define when we use grid-template-rows and grid-template-columns and pass in a track listing. This track listing defines the extent of the explicit grid. The implicit grid is created when we place an item outside of the explicit grid, or when we have more items placed via auto-placement than we have created tracks for.

Tracks created in the implicit grid will be auto sized unless you set a track sizing using grid-auto-rows or grid-auto-columns.

In many cases the implicit and explicit grids behave in the same way, and for many layouts you will find you define columns and then allow the rows be created as an implicit grid. There is a difference however that trips people up, and this is found when you start using negative line numbers to refer to the end line of the grid.

Line -1 is the end of the explicit grid

Grid respects writing mode. In a left to right language, column line 1 is on the left and you can us line -1 to target the right-hand column line. In a right to left language, column line 1 is on the right and -1 will target the left-hand line.

Example 129 — using line numbers on the grid I left to right and right to left directions Link

Where people get caught out is that it is only the explicit grid that can count backwards. If you have added rows in the implicit grid and then try to target the end line with -1, you will find that you get the last explicit grid line and not the actual end of your grid.

Example 13: Line -1 represents the end of the explicit grid

I’m Having Trouble With My Percentages! Link

At the beginning of this article I described how grid is very different to the layout methods that came before it. Due to the limitations of float and flex-based grids, we have needed to become good at calculating percentages in order to do layout and so the first thing that most people do is try and use the same method in their grid layouts. However, before doing so don’t forget our new friend the fr unit. This unit is designed for grid, and works because of the way that grid sets up sizing on the parent element.

The fr unit allows us to distribute a share of available space. It does so by looking at what space is available in the grid container, taking away any space needed for gutters, fixed width items, or content that is defining track sizing and then sharing out the rest according to the proportions we have specified for the tracks. This means that the scenario we have with a floated or flex layout for example, where we have to have flexible gutter tracks so that all of our percentages add up, isn’t the case with grid layout.

Example 14: Using the fr unit, the space needed for fixed sized gutters and tracks is removed before space is distributed.

In most cases the fr unit is a better choice than percentages. A reason you might choose to use percentage would be where you need a grid layout to match up with other elements using some other layout method and relying on percentage sizing. However if that isn’t the case, see if the fr unit will serve your needs before starting down the route of doing all the maths yourself!

Can I Nest Grids? Link

A grid item can also become a grid container, in the same way that a flex item can become a flex container. These nested grids however have no relationship to the parent grid, so you can’t use them to line up internal elements with other nested grids.

Example 15: Grids inside grids

In a future level of grid layout we may well have a method of creating nested grids that do maintain relationship to the parent grid. This would mean that items other than direct children of the grid could participate in an overall grid layout.

Can I Polyfill Grid Layout? Link

I’m often asked if there is a way to polyfill grid layout, with people wanting to know if there is a drop in and forget it way to support older browsers.

My advice would be that this isn’t something you want to do. It is likely to create a very slow and janky experience for those browsers already struggling to render modern websites. If you need older browsers to look identical to modern ones then maybe you should reconsider using grid on this project. However in most cases it is possible to use older methods to create a simpler fallback tailored to non-supporting devices without needing to create two completely different sets of CSS. This really needs an article to cover it in detail, so look out for that on Smashing Magazine soon!

Debugging Grid Layouts Link

As you start to work with grid you will quickly want to be able to see your grid and how the items on it are laid out. I would suggest that you download a copy of Firefox Nightly and use the Grid Inspector in the Firefox DevTools. If you select a grid you can then click the small grid icon — which I like to think of as a waffle — to display the grid.

10
Using the Firefox Grid Inspector. (Large preview11)

Firefox have created an excellent tool here, and while Chrome have begun to implement something into Chrome DevTools, right now the Firefox tool is the best in class and it makes working with grid so much easier.

This Is Still New To All Of Us Link

I know the CSS Grid specification very well, but I’ve only been able to use it in production since March, just like everyone else. As we all move from creating little examples and really start to push the edges of the specification in production work, we will start to find new ways to use grid and of course new problems to solve! I would love to see your own write-ups and demos of the way you are using Grid and other layout methods. I’m also going to be digging into layout issues here at Smashing Magazine over the next few months, so do let us know what you are finding out, and what you would like to know more about.

(yk, vf, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2017/09/grid-preview-opt-1.png
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2017/09/flex-preview-opt.png
  3. 3 https://www.w3.org/TR/css-sizing-3/
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2017/09/macyjs-large-opt.png
  5. 5 http://macyjs.com/
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2017/09/macyjs-large-opt.png
  7. 7 https://github.com/w3c/csswg-drafts/issues/945
  8. 8 https://github.com/w3c/csswg-drafts/issues/499
  9. 9 https://codepen.io/rachelandrew/pen/wqVXjp
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2017/09/grid-inspector-preview-opt.png
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2017/09/grid-inspector-preview-opt.png

↑ Back to top Tweet itShare on Facebook

Rachel Andrew is a web developer, writer and speaker and one of the people behind the content management system, Perch. She is the author of a number of books including The New CSS Layout. She writes about business and technology on her own site at rachelandrew.co.uk.

  1. 1

    Brian Haferkamp

    September 28, 2017 3:31 pm

    The Flexbox fallback is a good way to go for browsers that don’t have full support yet. I’ve found a few things helpful to decrease some of the jankiness when using Grid.

    The first is to use a Flexbox fallback and the @supports feature query (Flexbox goes first, then the feature query for browsers that understand it). It doesn’t provide the optimal experience for non-compliant browsers but that only represents 3-5% of our users on any given site. Maybe it’s different for others. But the experience is good enough for them and immaculate for the rest of the users.

    The other thing I do is not allow Grid or Flexbox to kick in until they need to. In other words, if I don’t need to do any visual reordering or change the layout, then I set the display: grid or display: flex to kick in after 600px (or whatever the break point is). That way, mobile phone browsers don’t have to work too hard when putting the page together. As you get to more powerful devices then things start to shift and change layout. I haven’t checked on speed performance but in terms of debugging and creating a cross-browser site, it’s very helpful. This also helps with a strange Flexbox implementation in Safari that doesn’t allow the use of flex-direction: column for some reason. I’ve found that to be a problem with IE, too. (Maybe you know a workaround for that?)

    Thanks for all the work that you and your team have done on this! It’s been a long time coming but great to finally be able to work with Grid Layout.

    7
  2. 2

    Why is javascript needed for Masonry layouts? I use the following:


    .wrapper {
    columns: 20em;
    column-gap: 1em;
    }

    .wrapper div {
    break-inside: avoid;
    }

    -6
    • 3

      The end result of a layout like this is very masonry-like, but you’re laying your elements out from top to bottom, then left to right. A true masonry layout would lay out elements left to right, then work down the page.

      6
  3. 5

    Is it just me or does ‘grid-gap’ struggle when trying to display 1px? Maybe it’s the CodePen plugin but I’m seeing slight variations in gap widths in the ‘single pixel grid gutter’ example.

    -1
  4. 6

    After reading this, i’m starting to get the feeling i’ll wait a couple more years before moving on to something hopefully better than the Flex or Grid options. Neither are ready in a number of ways. Grid layouts feel like the Vietnam war and responsive design is Communism.

    -17
  5. 8

    hi
    how does this work with bootstrap?

    Would you use this instead of bootstrap?

    -3
  6. 11

    > We are allowing the flex items to wrap, so they create new rows, but each row is a new flex container.

    This should be flex *line*, I think.

    0
  7. 12

    Thanks for the post. I have been using grid for a little while now, enjoying it completely.
    Still getting my head around the quirks but thanks for pointing out some that i may have missed.

    0
  8. 13

    Thanks from me too…

    It got me thinking about pure CSS “masonry” layout again, so I’ve had a play – https://codepen.io/basherkev/pen/QqggwG

    -2
  9. 14

    Thomas Murphy

    October 1, 2017 4:48 pm

    I’d just like to say a quick “thank you” to Rachel for her wonderful Grid By Example website which I am finding invlauable for working out how all this stuff fits together.

    The site is well worth a visit for anyone who wants CSS grid to be explained to them in simple, calm, direct terms with visual examples and short videos.

    No … I’m not married to Rachel!

    3
  10. 15

    Something really jumps out at me: a two dimensional layout controlled by markup over content, with row and column spans…? It sounds like grid is just table 2.0. What am I missing here?

    4
  11. 16

    I’ll bookmark this post for future reading – very useful info.

    I had exactly the same feeling as Andrew Smith – it’s almost like a re-invention of the table based layout – probably because that old nasty method, despite being unintentional, downright ugly and inaccessible, still works!

    Heck, before flexbox, display: table and display: table-cell were hacky solutions to bring back some of the possibilities table based layouts provided.

    However, ignoring the obvious issues with accessibility etc., table based layouts ended up like code soup – fine for static websites, a nightmare for dynamically generated ones.

    I look forward to using grid without having to resort to fallback solutions or ‘not so graceful’ degradation – the browser use percentages need to stack up first.

    2
  12. 17

    Hello, I’m hachi8833, a tech writer and a translator.

    I’d like to translate your recent article “CSS Grid Gotchas And Stumbling Blocks” into Japanese and publish on our tech blog https://techracho.bpsinc.jp/ if you’re OK.

    I make sure to indicate the link to original, title, author name in the case.

    Best regards,
    ——-
    https://twitter.com/hachi8833

    0

Leave a Comment

You may use simple HTML to add links or lists to your comment. Also, use <pre><code class="language-*">...</code></pre> to mark up code snippets. We support -js, -markup and -css for comments.

↑ Back to top