Adaptive design using grid (CSS).
Part 1: Columns, rows, cells and items




What is it all about?

One of the tools for creating adaptive design is called grid. It is a feature that came with CSS3 and it is highly useful.

The idea with grid is to split the UI up in columns and rows, allocated for different parts of the layout, e.g. header, footer, sidebar, etc. The advantage in using grid instead of the classic table, is that grid is flexible, so the elements in your grid can be moved around and change size. In regards to the challenges with variations in screen sizes, as access the Internet with many different devices, grid has some major advantages in regards to design. Especially if you combine it with flexbox for the inner elements.


The grid elemenst

Grid, like flexbox, is constructed with a container and items, but contrary to flexbox, you have a number of structural elements for which you need to know the name and purpose. So, starting from the beginning:

The container and items
The container is, as the name suggests, the overall container for items, i.e. with a few exceptions, this will be something like a DIV, right after the BODY tag. The variable for this, is display:grid, i.e. something like this:

<BODY>
<DIV STYLE="display:grid">

</DIV>
</BODY>


If needed, you also have display:inline-grid.

Normally you will need quite bit of styling on your container, so normally you would use class, containing display:grid instead. It doesn't have to be a DIV you use for this. Obviously you have to use a tag, capable of containing other elements, but using a DIV isn't mandatory. The child elements inserted in the grid now automatically becomes grid items. For this, the use of DIV is recommended as well. Even if you need e.g. an image or an IFRAME for video, the experience is that it is better to use a DIV and have the image or video in that. Having four items, it looks like this:

<BODY>
<DIV STYLE="display:grid">

<DIV CLASS="Item-1"> </DIV>
<DIV CLASS="Item-2"> </DIV>
<DIV CLASS="Item-3"> </DIV>
<DIV CLASS="Item-4"> </DIV>

</DIV>
</BODY>


Grid line
Grid lines are the lines dividing you grid. If we look at a 3x2 grid, it is the lines between the rows or columns that are formed, and you distinguish between vertical (column grid lines) and horizontal (row grid lines) grid lines. Here a vertical grid line is highlighted in red:



Grid cell
Grid cell is, as the name suggests, a cell. Here we have marked grid cell 2 in the first row:



Grid track
Grid track is what you have between two adjacent grid lines, i.e. a row or a column of cells. Here we have marked the grid track between second and third vertical grid line:



Grid area
Grid area is an area consisting of several connected cells. It may span several rows and columns at the same time, but it isn't a requirement, it may just be a part of a grid track. Here we have a marked grid area between first and third vertical grid line and first and third horizontal grid line:




Spacing between rows and columns

The default value for spacing between cells is zero, but you could easily imagine having some spacing between the cells, equivalent to tables where you specify border-collapse:separate and a dietance between cells using border-spacing.

The variables are called grid-column-gap and grid-row-gap with specification of the size of the spacing you want, e.g.:

.Container {
   grid-column-gap: 10px;
   grid-row-gap: 10px
}

Making the cells separate like this:

Beware that the spacing is only between cells. The distance to the sides of the container remain the same.

The plan is to replace the two variables with column-gap and row-gap i.e the old names without the prefix grid-. The new variable names already works for some browsers in the newer versions. In that case, the syntax is:

.Container {
   column-gap: 10px;
   row-gap: 10px
}


There is a shorthand version of grid-column-gap and grid-row-gap. It is called grid-gap where the values are grid-row-gap grid-column-gap, in that order. The syntax is thus:

.Container {
   grid-gap: 10px 10px;
}

If you only specify one value for grid-gap, grid-row-gap and grid-column-gap are given the same value.


Columns and rows in grid

The variables grid-template-columns and grid-template-rows are where you specify the number of columns and rows you want, i.e. the number of cells and the size of the cells. Inherent in the two variables is also the possibility of assigning a name to the rows and columns. The syntax for both is the name in square brackets followed by the size. When specifying the size, you have several options:

absolute sizeFixed size, e.g. px, mm, etc.
relative sizeFixed fraction of the width/height, i.e. percentage of the total width/height
autoFlexible size, equivalent to the remaining/available space in height and width.
frFraction of the free space in the container


In practice you will combine the types of size specification, as it makes most sense, and this is no problem. Let's have a look at some examples, so it all makes more sense.

Architecture
The number of rows and columns are specified by specifying a height/width, separated by space. Here we have a container consisting of four columns, where the outer columns are 40px wide and the two inner columns are 50px wide. There is two rows, where the first is 20px high and the bottom one is 100px high:

.Container {
   grid-template-columns: 40px 50px 50px 40px;
   grid-template-rows: 20px 100px;
}

Contrary to size, naming isn't required. The name is written in square brackets before the width. Here we name the second column and first row:

.Container {
   grid-template-columns: 40px [column 2] 50px 50px 40px;
   grid-template-rows: [row 1] 20px 100px;
}

With the architecture designed like this, you can encounter cells with two names, and this is no problem.

If you have multiple columns or rows in succession with the same size, you can use repeat(), where you specify the number of repetitions and width/height. Obviously you need to take a little care, when specifying sizes in percent. The code for a container having 3 columns of 40px with, followed by a column 100px wide, will look like this:

.Container {
   grid-template-columns: repeat(3, 40px) 100px;
}

If you specify a name for the column/row being repeated, these will all have the same name. Here we get three columns with the name test_column:

.Container {
   grid-template-columns: repeat(3, [test_column] 40px) 100px;
}

Later, if you need to refer to a specific columns of the three, you do it by writing name and number, i.e. the third of the three columns is called "test_column 3".


Absolute sizes
Absolute sizes are fixed sizes, specified e.g. as px, mm, cm, etc. These days, where we have so many different devices with different screen resolutions, px is usually the most appropriate unit, e.g.:

.Container {
   grid-template-columns: 40px 50px 50px 40px;
}



Relative sizes
Relative sizes is a fixed percentage of height/width. These days, where we have so many different devices with different screen resolutions, px is usually the most appropriate unit, but code using percentage is e.g.:

.Container {
   grid-template-columns: 20% 60% 20%;
}



auto
Flexible specification of size, using auto, is for the remaining height/width on the page. For pages you often combine elements with a fixed width with elements allowed to use the remaining space, depending on the size of the viewport. This could be something like a navigation pane or a column for adds. For WordPress users this is e.g. the log-in pane to the right. A grid having three columns, where the outer two have to be 100px wide and the mid column use the rest of the viewport's width, looks like this:

.Container {
   grid-template-columns: 100px auto 100px;
}

Per se, you can have multiple columns with auto, also next to each other, but if you need this effect, it makes more sense using fraction, fr.


fr
The fraction fr is really a sort of subdivision of auto, as the remaining width/height is separated in fractions. If you need a column that is 100px wide and the remaining space in three columns of equal size, it looks like this:

.Container {
   grid-template-columns: 100px 1fr 1fr 1fr;
}

The columns don't have to be next to each other. Here the 100px column is number two in line:

.Container {
   grid-template-columns: 1fr 100px 1fr 1fr;
}

The size rations don't have to be 1:1 either. Here the column to the right is twice a wide as the other two:

.Container {
   grid-template-columns: 100px 1fr 1fr 2fr;
}