Let's get Grid-dy with it!
We think its fair to say that CSS Grid has been a revelation for designers!
Now we know some of you may be thinking grids are nothing new to the design world, as design grids have of course been the fundamental basis to design layouts like forever!
Well yes, you would be right! However since website design has been a thing, designers have been trying to replicate the holy grid grail of compound grid layouts, though often with great difficulty or at least a lot of workarounds and hacking about!!
What is a Design Grid
Grids in design are the frameworks that help designers organise content in a structured and visually appealing way. They create balance, consistency, and alignment in layouts which helps to improve readability, create harmony, and guide the viewer’s eye effectively.
Whether they are working on print or digital projects, grids are a vital tool for maintaining structure while allowing creativity to flourish. A grid framework is made from sets of intersecting horizontal and/or vertical lines that make up either columns, rows or boxes (cells). Here are some common ones:
- Manuscript Grid: A simple single-column grid, often used in books and PDFs.
- Column Grid: Divides content into multiple vertical columns, useful for magazines and newspapers.
- Modular Grid: Divides the page into both columns and rows, providing flexibility for complex designs.
- Baseline Grid: Aligns content to a consistent baseline, ensuring text maintains uniform spacing.
- Hierarchical Grid: Irregular, based on content needs, often used for web design and infographics.
What are compound grids?
Compound grids are a combination of two or more grid systems overlaid together within a single layout. By merging multiples of similar grid types together such as a 3 column and a 4 column grid, or even different grid types, such as column, modular, or hierarchical grids, we create a compound grid. This is a grid with a more complex set of columns, rows and gutters/gaps (as you can see in the diagram below) this helps give us greater flexibility in organizing text, images, and other design elements, making it easier to create more complex compositions.
For example, a magazine layout might use a modular grid for text-heavy articles, while also incorporating a column grid for feature sections with large images. This approach ensures visual harmony while accommodating varied content types.
CSS Grids & Web Design
We already mentioned that designers have had their struggles over the years trying to replicate the compound grid layout. This however changed in 2017 when the CSS Grid Layout model landed, which was created specifically to solve these layout problems.
CSS Grid not only gave us the same layout flexibility and spacing, we get from the one-dimensional row or column system of Flexbox. But with it's two-dimensional, grid-based system of intersecting horizontal and vertical lines, it not only defines both grid track rows and columns at the same time, it also creates grid cells and areas too.
Elements are then placed onto the grid within these column and row track lines, grid areas and cells (grid-items). All of which are created and controlled entirely by CSS.
Though we don't have to follow these set grid lines, columns and rows, as we also have the ability to overlap elements easily too. All this gives us greater control when working on more complex layouts with a diverse set of content, such as images, text, and interactive elements.
But which comes first?
It would seem, that how we go about using CSS Grid's, is a bit of a chicken and egg situation for many of you. Do you start with setting out a compound grid which you then fit your contents into? Maybe you have your design and contents already mapped out either digitally or on paper, in which case you could use this to work out the grid system you need. Or perhaps you already have your contents written up into a HTML page, so should you let your contents dictate the flow of the grid?
To be honest there's really no right or wrong answer here as it all depends on what fits your situation, or feels best for you and your skill set. But we do plan on tackling this question at a later date.
So for now lets look into the basics of how to create and use Grid.
Creating a Grid
Grid Container
To start using CSS Grid we first need to make our parent element a Grid Container, we do this by telling it to display grid or inline-grid.
.parent_element {
display: grid; /* generates a block-level grid */
}
.parent_element {
display: inline-grid; /* generates an inline-level grid */
}
Once our parent element has become a grid container, all direct child elements within it will become Grid Items.
Please note that any elements inside these new grid items (the child elements of the child elements!) will stay as they were and not become grid items too.
Implicit & Explicit Grids
Even though we've now created our grid container, nothing will initially change. This is because by default Grid only creates a single vertical column until we tell it otherwise, while at the same time automatically creating as many rows as necessary to fit our contents, with one row for each child item there is.
This dynamically growing Grid is called an implicit grid, as we have yet to explicitly define how we want our grid to be structured.
Grid Template & Tracks
To start creating an explicit grid we need to specify our Grid tracks, a track is the space between two lines of a grid which can be either a vertical column, horizontal row or named area. This
which we can create by using the following properties:
grid-template-columns&grid-template-rows: Defines column and row track sizes.grid-template-areas: Assigns named areas to simplify layout placement.grid-auto-columns&grid-auto-rows: Sets sizes for automatically generated columns and rows.grid-auto-flow: Controls how new items are placed (row or column-based flow).grid-template: Combinesgrid-template-columns,grid-template-rows, andgrid-template-areas.grid: A shorthand forgrid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns, andgrid-auto-flowall in one.
Each of these are then followed by a string of values, each value is equal to one grid track and defines either the width (columns) or height (rows) of each track.
When creating repeated columns or rows of the same value, we can simplify our string of values by using the repeat() notion.
.parent_element {
display: grid;
grid-template-columns: 10px 2rems 20% 1fr;
grid-template-rows: auto; /* auto is the implicit default value */
}
/* alternative value combinations:
1fr 2fr 3fr 1fr [fraction value]
repeat(4, 1fr) [number of tracks / size value]
minmax(10px, 1fr) 3fr [minmax(minimum track size , maximum track size)]
min-content 1fr min-content
100px 1fr max-content
*/
Fixed or flexible Tracks
As you can see above, a grid track can be defined using a range of CSS values such as pixels, rems, viewport units or percentages, these values will give you fixed width tracks.
But what if we want more flexibility, like we get in Flexbox with flex-grow? Well Grid has introduced a new value the fr unit, which stands for fraction and it is a flexible unit that can freely grow and shrink as required, either to contain their contents and/or take up any spare remaining space within the Grid Container.
It works by first calculating the width of the contents within the tracks and then any remaining space is divided up between the tracks depending on their fr value e.g. 1fr 1fr 1fr will divide the remaining space equally, where as 1fr 1fr 2fr will give one twice as much spare space as the others.
.parent_element {
display: grid;
grid-template-columns: 10px 2rems 20% 1fr;
grid-template-rows: auto; /* auto is the implicit default value */
}
/* alternative value combinations:
1fr 2fr 3fr 1fr [fraction value]
repeat(4, 1fr) [number of tracks / size value]
minmax(10px, 1fr) 3fr [minmax(minimum track size , maximum track size)]
min-content 1fr min-content
100px 1fr max-content
*/
Its also possible to define tracks using intrinsic sizing keywords which help create flexible layouts. They allow grid tracks to adapt based on content size rather than being restricted to fixed values.
auto: The track size is determined by the content inside it.min-content: The smallest possible size where content fits without overflowingmax-content: The largest possible size without breaking into multiple lines or overflowing.fit-content( <length> ): Acts like max-content but allows a maximum constraint.minmax( min, max ): Defines a flexible range between a minimum and maximum size
.grid-container {
display: grid;
grid-template-columns: minmax(100px, auto) max-content;
grid-template-rows: fit-content(200px);
}
/* This ensures the first column can grow beyond 100px depending on content,
while the second column expands to fit its content.
The row adjusts within a 200px limit. */
Mind the gap
Some maybe familiar with the gap property already if you've already used Flexbox (Flex). Though the property works slightly differently in CSS Grid to Flexbox, whilst its core function of creating spacing between elements remains the same. The key difference is that in Grid: gap, row-gap, and column-gap control the spacing between rows and columns, applying it between items in both horizontal and vertical directions.
.grid-container {
display: grid;
grid-template-columns: repeat(3, 100px);
gap: 20px;
}
Grid lines
When we define our grid tracks we also create grid lines at the same time. These lines are numbered starting from the left to right for the columns and top to bottom for rows. Its these numbered lines that help us to position our contents, though if you don't want to use the grid numbering system you can assign names to your grid lines instead.
In an explicit grid we can see the number of grid lines that are in that particular grid from the string of values we have set. Starting with the first grid-line before the first value, followed by one in each space between values, and ending with a line after the last value. This will mean there is always one extra grid line to the number of tracks, as you can see from the code example below a 4 column grid will have 5 grid lines.
.parent_element {
display: grid;
grid-template-columns: 10px 2rems 20% 1fr;
}
/* explicit grid-lines
(line 1) 10px (line 2) 2rems (line 3) 20% (line 4) 1fr (line 5)
note - when we define a grid we define the grid tracks, not the lines*/
.parent_element {
grid-template-columns: [start] 100px [middle] 100px [end];
grid-template-rows: [top] 50px [center] 50px [bottom];
}
/* you can assign names to grid lines using square brackets [] */
Items outside the grid
Even when we have an explicit grid with defined columns and rows the grid itself can create additional implicit grid tracks if necessary. Such as when we have more grid-items than available cells, or when we position grid items outside of the already defined grid tracks. The grid algorithm will then automatically create further implicit grid tracks and cells to accommodate them.
Positioning Grid items
Default positioning
Once we have our grid defined we then need to place our grid-items within it. Now by default each item will fill the first empty grid cell available to it along the row. Once a row is filled it will start filling the next row, if no explicit rows are defined it will create implicit rows until all the grid-items are placed. However we can overide the direction the cells fill with grid-auto-flow: column; so they fill in columns vertically instead.
Though with the superpower of CSS Grids we can actually position each and every item within a grid wherever we choose to! This is done using properties that control their placement within and across the grid tracks (column or row), cells or areas.
Grid Line Numbers
So far we've learnt that we define a grid by its tracks and each grid track then has implicit or explicit numbered lines. Its these line numbers you can refer to when positioning items, instead of the actual tracks themselves. This allows for easier and more precise placement using either line numbers or named lines, though it is also possible to use the column (or row) number if an item only spans one track, or we can use named areas too.
To control the placement of grid-items we can use these properties:
grid-column-start&grid-column-end: defines which column line a grid item starts and ends.grid-row-start&grid-row-end: defines which row line a grid items starts and ends.grid-column&grid-row: shorthand properties that allow you to set both start and end lines at once.
.item {
grid-column-start: 2; /* Starts at column line 2 */
grid-column-end: 5; /* Ends at column line 5 */
}
.item {
grid-row-start: 1; /* Starts at row line 1 */
grid-row-end: 3; /* Ends at row line 3 */
}
.item {
grid-column: 2 / 5; /* Equivalent to start at column 2 and end at 5 */
grid-row: 1 / 3; /* Equivalent to start at row 1 and end at 3 */
}
Named Grid Lines
Instead of numbers, grid lines can be named to make placement more readable.
.container {
display: grid;
grid-template-columns: [start] 100px [middle] 200px [end];
}
.item {
grid-column: start / middle; /* Uses named lines instead of numbers */
}
Spanning Multiple Tracks
Instead of specifying exact lines, you can use span to define how many columns or rows an item should stretch.
.item {
grid-column: 2 / span 3; /* Starts at line 2, spans across 3 columns */
grid-row: 1 / span 2; /* Starts at line 1, spans across 2 rows */
}
Grid areas
Grid areas are named sections within a grid that help structure and position elements more efficiently. They allow you to design complex layouts using readable and intuitive names instead of manually placing items by row and column numbers.
A grid area is a rectangular/square section of a grid, that is formed by spanning one or more grid cells. You define these areas using the grid-template-areas property inside the grid container, and then you assign elements to these areas using the grid-area property.
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 50px 50px;
grid-template-areas:
"header header header"
"sidebar content content";
}
/* "header header header" means the header spans all three columns
"sidebar content content" places sidebar in first column & content in second and third */
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.content {
grid-area: content;
}
Alignment properties
Those familiar with Flexbox will notice the same alignment properties are also used in Grid. Though in grid the properties which begin with justify- are always used on the inline axis (horizontal), and those that begin with align- are used on the block axis (vertical).
justify-content&align-content: distribute additional space in the grid container around or between tracks.justify-self&align-self: are applied to a grid item to move it around inside the grid area it is placed in.justify-items&align-items: are applied to the grid container to set all of the justify-self properties on the items.place-items: is shorthand for align-items (vertical) and justify-items (horizontal), affects how grid items are positioned inside their grid cells.place-content: is shorthand for align-content (vertical) and justify-content (horizontal), affects alignment of the entire grid inside its container.place-self: is shorthand for align-self (vertical) and justify-self (horizontal) lets you position individual grid items within their grid areas.
Alignment Examples:
Align Items Inside Their Grid Areas Use justify-items (horizontal) and align-items (vertical) to control item placement:
.grid-container {
justify-items: center; /* Centers items horizontally */
align-items: start; /* Aligns items at the top */
}
Now all grid items will follow these rules.
Align the Entire Grid Control how the grid itself is positioned within the parent container:
.grid-container {
justify-content: space-evenly; /* Distributes columns */
align-content: center; /* Centers rows */
}
This adjusts the entire grid’s placement.
Customise Individual Items You can override alignment for specific items:
.grid-item {
justify-self: end; /* Moves this item to the right */
align-self: center; /* Centers it vertically */
}
This allows flexibility while maintaining consistency.
Layering grid items
Layering with z-index: If grid items overlap, use z-index to control visibility.
.item {
grid-column: 1 / 3;
grid-row: 1 / 2;
z-index: 10; /* Higher value brings item forward */
}
More Grid
Within this grid intro we have covered the basics to help get you started on your grid journey. Though the world of all things Grid is constantly moving forward, unfortunately like a lot of other features within CSS baseline browser support can often take a while to catch up. So we will be coming back and adding new Grid content and features, when we feel they have enough browser support to be used safely.
Page Last Edited: