Image of a container yard showing hundreds of shipping containers

Griddy griddy bang bang

One of the best things about working for Valtech is bench time. This is time between projects where consultants get the opportunity to learn, assist with sales pitches or write an article. Bench time gives me the opportunity to revisit CSS Grid after a few failed attempts to learn the basics.

I find it difficult to learn anything without having a practical use cases to get my head into. In order to have a practical use case I need to be working on a project which has the flexibility to experiment with some of the modern CSS properties. So I decided to experiment with my own website. I am going to make this my playground to learn and write. So that is what you are seeing here, an article within an experiment, how very meta. Feel free to inspect the page. What I have realised is that CSS Grid is huge, I am not going to be able to learn the lot in one sitting. I am starting off with this great codepen from Brenda Storer. My plan being to recreate this CodePen and step through the code and understand each part as I do so.


Containers and items

CSS Grid is all about creating containers and placing items into the containers. Before I crack on with styling up the CSS I need some HTML markup to play with. Firstly we need to put together the markup for the article, breaking it into a masthead image, a header which would contain the article title and meta information and a main body section for the article content.

<article class="article">
	<figure class="article__image-container">
		<!-- image to add -->
	</figure>
	<div class="article__header">
		<!-- header to add -->
	</div>
	<div class="article__content">
		<!-- content to add -->
	</div>
</article>

The grid layout for this page kicks in at 768px. Anything narrower than that breakpoint will see a simple stacked layout. Anything above 768px will get the grid layout. The entire wrapper for this article gets set to display: grid;. We split the grid into 3 parts, a main centre column and two remaining parts on the left and right of the screen. The main column is set to be a maximum width of 72ch using the ch unit. When using the ch unit, it is important to remember that the browser doesn't count the number of characters on any given line, its value is equal to the width of the 0 (zero) character. Read more about the ch unit.

Pouring in some content

Next we need to add in the content, choosing a beautifully tenuous container image from Unsplash. We give the image a class to hook into for later styling. Then drop in the title and article date information.

My articles tend to be quite organic and change as I write and even after I have published them. I planned to add in the content as I went along so at this point the HTML looked like the following, ready to be styled up.

<article class="article">
	<figure class="article__image-container">
		<img alt="Image of a building divided into a grid" src="/images/screens/rawpixel-539830-unsplash.jpg" class="article__image u-img-responsive" />
	</figure>
	<div class="article__header">
		<time class="article__meta">December 2018</time>
		<h1 class="article__title">Getting griddy with it</h1>
	</div>
	<div class="article__content">
		<!-- content to add -->
	</div>
</article>

Creating a grid container

As previously mentioned all the grid action happens when there is enough available space on the screen to play around with the layout. The first thing I am doing is setting the article class to be a grid container. Then we'll want to add in the columns, the center column being as wide as 72ch.

.article {
  display: grid;
  grid-template-columns: 1fr minmax(auto, 72ch) 4fr;
  grid-template-rows: 100vh auto;
}

Doing this gives us a few new features associated with CSS grid to digest. The value of grid is a new value that can be used with the display property. It defines a grid container. We are saying that every direct child of this container is an item in the grid and therefore can have grid properties defined on it.

Using grid-template-columns

This new CSS property allows us to define how many columns there are in the grid. Columns run left to right across the screen on the X axis. In the example there are 3 columns. If you wish you can also name the grid rows and columns. By default the browser will number them and it is these numbers we use later to position the grid items onto the grid.

Using grid-template-rows

This new CSS property works the same way as grid-template-columns except rows run top to bottom across the screen on the Y axis. The example has 2 rows. The first row uses the vh (viewport height) unit. Here, we are essentially saying that we want the first row which in this case is the image to fill 100% of the viewports height. The second row will be as tall as its content (auto).

The fr unit

The fr unit is a fraction unit, 1fr is 1 part of the available space. The available space is calculated by the browser after any other measurement is calculated. So in the example the browser first calculates the main column, here using the minmax() function. Once this has been calculated the browser splits the remaining space into 1 part on the left and 4 parts on the right of the main column.

Using minmax()

The minmax() function. It takes 2 values, the minimum size of a row or column and the maximum size. In our example the minimum size is auto, this means the smallest the column can get is whatever is defined by its content. The maximum size in our example is 72ch. Read more about the minmax() function.


Grid item placement

Now we have a grid container, it is time to place the items within it. Firstly we want the main image to have a bit of impact so we want it to fill the width and height of the viewport. The image is already within a containing element.

.article__image {
  display: block;
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: cover;
}

This CSS isn't recent or related to CSS grid but it is worth noting the object-fit property when it comes to CSS grid. This CSS property behaves similarly to the background-size property which is used when applying an image as a background to an element. It allows designers to apply the same logic directly to elements within the DOM such as <img> or <video>. Read more about object-fit.

Now the image will always proportionately scale with its parent container. We can now place the parent container on the grid.

.article__image-container {
  grid-column: 1 / -1;
  grid-row: 1 / 2;
  height: 100%;
  max-width: 100%;
}

So this snippet of CSS gives us a few more new properties to look into, namely grid-column and grid-row.

Using grid-column

This property is shorthand for grid-column-start and grid-column-end. It works across the X axis. Here we are declaring both grid line values in the grid-column shorthand declaration. The / (slash) character splits the start and end values. As we already know from using grid-template-columns, the browser will number the grid lines (columns and rows) by default. So grid-column: 1 / -1; is telling the browser that this column will start on the first column and end on the -1 column. When we declare negative integers the browser counts in reverse. In our case from the right of the container. So we know this grid item will be placed to fill the full width of the parent grid container. The grid lines can also be named and referenced in the same way. See Rachel Andrew's great demos for more on this.

Using grid-row

This property works in much the same way as grid-column but works accross the Y axis. In the example we are telling the browser that this item will start on the first row and end on the second row.

Placing the article header

This is where things start to get a little more interesting for anyone who already works with CSS flexbox. The article header has been placed onto the grid just as the image container was. CSS flexbox properties also work with CSS grids, beautiful! Take this CSS from the article header.

.article__header {
  align-self: end;
  grid-row: 1 / 2;
  grid-column: 2 / -1;
}

Here as previously, we tell the browser where we want the header to be placed on the grid using grid-column and grid-row. Note that the article header is placed on the same row as the image container as well as being told to span to the -1 column (all the way to the end). This means that the article header is sitting over the top of my image container. As the initial value of align-self is auto the browser is stretching the header over the top of the image container. This can be easily fixed by setting the value of align-self to end. The browser now renders the header only as big as the header content and neatly overlays the image container.

Placing the article content

Finally all that is left to do is to place the item we want the article content to be displayed in.

.article__content {
  grid-row: 2 / 3;
  grid-column: 2 / 3;
}

As before we just need to define values for the rows and column start and ending points. If we wanted to define more rows or if we wanted to make this layout more robust, we could make the content always end on the last row. This could be done by changing the grid-row: 2 / 3; declaration to be grid-row: 2 / -1;


Wrapping up

As I originally mentioned CSS Grid is huge, I tried to keep this article relatively short and follow Brenda's CodePen which only includes enough know-how to get going. I already feel that this could have been broken down further.

Something that really helped me when picturing a grid layout is to draw it first. This way you can design your layouts first without getting too bogged down in the code.


Kudos

Huge thanks to Brenda Storer for this layout and to Rachel Andrew for her high quality CSS grid resources. This article is just a rehash of the hard work already put in by people like Brenda and Rachel. I find a great way to learn is to write an article like this. It makes me focus and step through each line of code methodically, adding my own understanding of the properties and what they do. I hope it is helpful for you.

Fin 🏁