rid Projection Naming

CSS Grids specification contains a lot of different things. And, for some of them, there exist multiple ways of how you can achieve them. In this article, I’ll write about one trick with grid-template-areas that could help you name your intersecting columns or rows.

For , I wanted to use , but I also wanted to keep the layout that I had come up with for my previous version. It wasn’t that intricate but had its own nuances which I still liked. Overall, grids allowed me to replicate that layout much easier than I thought it would be, even if there were one or two things that didn’t come out as good as I hoped.

In¬†this article, I¬†would tell you about one trick I¬†came up¬†for naming my¬†layout‚Äôs grid columns. Everything else¬†‚ÄĒ how the layout works and what were the problems with it¬†‚ÄĒ I‚Äôll save for another article, otherwise, this one would become too¬†big.

amed Intersecting Columns

When I started developing the layout, I wanted to place the content by using named grid columns, so everything would go into a content column by default, but sidenotes and similar stuff would go into an aside column. I also wanted to have a way to place something to the full width of the grid and also having a way to place something in the place content and aside columns.

While reading the CSS Grid Layout Module specs, I found out that you indeed can have intersecting columns (or rows), by using the explicitly named grid lines with identifiers starting and ending in -start and -end. Basically, by using this method, I could create my columns layout by something like this:

main {
  grid-template-columns:
    [full-start]
      var(--grid-side)
      [both-start
        content-start]
          var(--grid-content)
        [content-end
        aside-start]
          var(--grid-side)
        [aside-end
      both-end
    full-end];
}

Then I could place my content with grid-column: content, place things into a right column with grid-column: aside, make something take the full width of the layout with grid-column: full, or take just the width of both content and aside columns with grid-column: both.

When I explain things like that, you could probably imagine how the layout would look like… Or maybe not? Even while I tried to place everything in the above code as neatly as possible by using indentation to show the nesting of the intersecting columns and so on, I’d say that it is still a bit confusing and too complicated. And, more importantly: it’s unmaintainable. Imagine: what if you’d need to add another named column that would take both the first unnamed column and the second content one? Or if we’d need to add a fourth column somewhere in-between? Or change and move stuff for a narrower layout inside a media query?

While this syntax is powerful, it is very cumbersome. So, I started to dig deeper. I knew that there is a way to mark up grids by using visual string , but didn’t see how they could allow you to intersect multiple areas. It seemed to be impossible.

Until I looked at my layout and noticed that it is not a two-axis layout. I had only named columns, but everything else would be auto-placed, so all the rows are implicit. This leads :

main {
  grid-template-areas:
    " full  full     full   "
    " .     both     both   "
    " .     content  aside  "
    / var(--grid-side)
            var(--grid-content)
                     var(--grid-side);
}

For my purposes, this creates the same exact grid layout. Can you see what the trick is?

he Projection Trick

Whenever you‚Äôre marking up¬†your grids by¬†using the grid-template-areas, what happens is: you‚Äôre not just naming areas. In¬†fact, you‚Äôre naming also columns and rows! And¬†‚ÄĒ the most interesting part¬†‚ÄĒ those rows and columns would get names from all the areas that are projected onto them. So, if¬†we‚Äôd at¬†our template, it¬†could be¬†represented as¬†something like this:

Here you can see where different items are when given grid-area, grid-column, and grid-row.

And then, with rows being auto-placed by default, and with the columns set to one of our named columns, things would always go into correct columns!

All of this allows us to control the column names and their placement much much easier than with the square brackets -start and -end syntax. If we’d want to add another column or change the width of some of those, we could just change the visual representation. And, for example, for my site’s layout, on the narrower screen I replace the above template with this one (by using variables, of course):

:root {
  --grid-ascii--small:
    " full  full     full "
    " .     both     .    "
    " .     content  .    "
    " .     aside    .    ";
}

There everything would go into one column, and full would include the paddings that would be created by the grid-gaps, with the left and right columns being both equal to zero. Very convenient! But about this and other nuances I’ll write in one of my next articles.

Anyway, in this smaller layout you can see the principle even better, and here is the above example with the projection, but using this smaller layout:

In other words, when we have only one axis to think about, we can treat each row of the grid-template-areas as one of the possible of the column layout, and don’t need to think what happens to rows at all. I use this for columns, but this can also be used for rows if you’d find a case.

But I think that for most layouts out there you would maybe want to use this trick, as you most probably would have some defined columns and then everything else auto-placed on the rows. And placing items by using names is much more convenient and readable than using numbers, so I can only recommend you to try this method!

implified Example

Other than my site’s layout, there are, of course, a lot more use cases you can apply all of this. The simplest one you could probably already saw somewhere, as it doesn’t even include intersections:

main {
  grid-template-areas: "left middle right";
}

Yep, that is just your regular three-columns layout, which is rather obvious when you’re looking at it, but there is still useless row names, which exist, but you would never use them:

And with this kind of layout, it is now very easy to add two intersecting combined columns:

main {
  grid-template-areas:
    " left        middle      right     "
    " sans-right  sans-right  .         "
    " .           sans-left   sans-left ";
}

Here, we just added two rows with two new wider intersecting columns: one taking left and middle one, and another taking middle and right.

This kind of layouts can be very helpful when having automated placement inside a grid, whenever you’d want things to go into specific columns.

One important thing to note: as with any other grid placement, all of this only affects the visual layout. The order of the elements in keyboard navigation and for screen readers would be always according to the source, so be cautious if you’d use this method for something where order matters.

reams of the future

The only main problem of¬†this method¬†‚ÄĒ its to¬†use when you need both rows and columns. What could be¬†interesting¬†‚ÄĒ an¬†ability to¬†define multiple templates for a¬†grid layout, which when placed one over another, with a¬†condition of¬†having the same number of¬†rows and columns, would create intersected areas. How cool that would¬†be? Actually, maybe we¬†just need a¬†way to¬†define three-dimensional grids? Hmmm! But I¬†would leave you to¬†think about the prospects of¬†something like that for yourself. For¬†now.

Published on with tags: