- Use CSS Grid
- Define grid with columns and rows
- Map elements to grid cells
- Use media queries
https://www.youtube.com/playlist?list=PLoN_ejT35AEhF_M9vBuZgW0E4PiDb19oX
Watch videos: lesson 05 1-5
Grid Example: https://github.com/Tech-at-DU/grid
In design, a grid is used to create a system that arranges things on a page. Think of this as visually organizing your content.
The first thing that comes to mind when you talk about a grid is graph paper. A grid in design looks a little different. A vertical grid is the space between each line and is based on the font size. Horizontally the grid is based on the column width.
Here is a good article describing grid systems:
https://www.oozlemedia.com/advantages-of-grid-systems-in-web-design/
-
Q: What does the CSS grid do?
-
A: CSS Grid arranges elements in rows and columns.
-
Q: How is this different from Flex?
-
A: Flex is a one-dimensional arrangement. When using flex you choose an axis either horizontal or vertical. CSS grid on the other hand arranges elements on both the horizontal and vertical axis.
-
Q: Why use CSS grid over one of the CSS grid systems like Bootstrap?
-
A: CSS Grid is simple enough it doesn't need an abstraction. It's more flexible and doesn't require all of the extra markup needed by a grid system like the one used in Bootstrap.
-
Q: Can you use CSS Grid and Flex together?
-
A: Yes! They both work together. You can use flex to arrange elements on a grid cell or use a grid inside an element arranged with flex.
CSS Grid works similar to Flex, you set an element's display property to grid
and all of the element's children will be arranged in a grid.
Grid is also different from Flex. A grid has two axes and allows you to define cells that make up the grid. It's more complex than Flex.
Vocabulary
Columns
Columns are the horizontal divisions of the grid. Picture these as vertical bars that define the horizontal space. These are the most important measurement!
Gap/Gutter
The grid gap or gutter is the space between the columns.
Rows
These are the vertical divisions. Picture these as the horizontal bars that are stacked vertically.
When you put them together you get a grid,
Grid Cell
A grid cell is a rectangular area that maps across any number of rows and columns. It has to be a rectangle! The edges must stop at the borders defined by the rows and columns.
Generally speaking, you can ignore the height of rows since the row height will be set by the height of the content, though sometimes you will set this.
Imagine you have the following markup:
<div class="container">
<div class="box a">One</div>
<div class="box b">Two</div>
<div class="box c">Three</div>
<div class="box d">Four</div>
<div class="box a">Five</div>
<div class="box b">Six</div>
<div class="box c">Seven</div>
<div class="box d">Eight</div>
</div>
With this arrangement, you can use div.container
to arrange all of the div.box
in a grid. The following would arrange these elements into three columns with a 1em
gap.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1em;
}
Let's take that apart.
.container {
display: grid; /* .container arranges its children on a grid */
...
}
.container {
...
/* Creates three columns, which are each one fraction */
grid-template-columns: 1fr 1fr 1fr;
...
}
.container {
...
gap: 1em; /* adds 1em space between columns and rows */
}
The fr
is a unit that represents a fraction. A fractional unit takes up a fraction of the available space. In this each we have three fractions they should each be 1/3 or 33.333% of the space.
If you had 1fr 1fr 1fr 1fr
each fraction would be 1/4 or 25%.
Fraction can be any number. For example: 1fr 1fr 2fr
is a total of 4 fractions and would give us: 1/4, 1/4, and 1/2 or 25%, 25%, and 50%.
The code above is all you need for a simple grid where each cell is the same size.
CSS Grid provides more tools for creating more-complex grids. One of the best tools is grid-areas
. This property allows you to define cells that span rows and columns and map elements to those cells.
This time start with four divs.
<div class="container">
<div class="box header">Header</div>
<div class="box side">Sidebar</div>
<div class="box main">main</div>
<div class="box footer">Footer</div>
</div>
These elements represent the areas of the page and will be mapped to the grid.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 1em;
grid-template-areas:
"h h h h"
"s m m m"
"s m m m"
"f f f f"; /* Note the ; here! */
This time we have 4 columns each one fraction.
The grid-areas
property is where you will define your grid areas. The letters assign a name and the space used for a cell.
The cells will map like this. Imagine h
represents the header, s
is the sidebar, m
is the main content, and f
is the footer.
"h h h h"
"s m m m"
"s m m m"
"f f f f";
This arrangement creates four rows and four columns. Notice the syntax. You must use quotes on each line and end the last line with a semicolon.
Mapping Elements to Grid Areas
Notice above that we have given each element a class name: header
, side
, main
, and footer
. Map each of these elements to one of the defined grid areas like this:
.header {
grid-area: h;
}
.side {
grid-area: s;
}
.main {
grid-area: m;
}
.footer {
grid-area: f;
}
Notice each element is assigned to a grid area by the letter assigned in the template.
In other words div.header
maps to the area defined by the h
.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Grid_template_areas
Above I showed two ways to use CSS Grid. These examples work with only three properties: grid-template-columns
, grid-template-areas
, grid-gap
, and grid-area
. CSS Grid has a few more properties.
Explore some more features of CSS Grid here:
Using the CSS Zen Garden HTML try to recreat the following grid arrangement.
Step 1
The goal of step 1 is to arrange the main elements of the page into header, main and sidebar.
Declare .page-wrapper
as display: grid
. All of the children of page-wrapper can now be arrrnaged on a a grid. Identify the children.
Declare three columns each 1fr
with grid-template-columns: 1fr 1fr 1fr
.
Now map the children to grid cells shown with the colors with grid-template-areas
. Something like this:
grid-template-areas:
"h h h"
"m m s"
"m M s";
Last, map each child elements to the grid areas defined above.
.main
togrid-area: m
.intro
togrid-area: h
.sidebar
togrid-area: s
Step 2
The goal is arrange the paragraphs in the .preamble
section in three equal columns.
Take a look at preamble. This div has four children. You want the header at the top and the three paragraphs in columns below.
- Declare
.preamble
display: grid
. - Define three fractional columns with
grid-template-columns
- You can use
grid-template-areas
again. The same as above. It might be good to use different letters here to be clear. - Formulate selectors for each of the four children of
.preamble
and assign each to a grid area.
Step 3
The goal for this step is to arrange the two paragraphs here into two equal columns and have the heading span both columns.
To do this:
- Declare
.explanation
display grid. - Define template columns with two fractions
- Define template areas with two columns and two rows.
- Map the elements to their grid areas.
Stretch goal
Use media queries to change the arrangement of the grid.
Currently your page-wrapper grid is:
"h h h"
"m m s"
"m m s"
This works well when the page is wider but when the page gets narrow this doesn't leave enough room for the sidebar.
When the page is smaller than 800px move the grid to the bottom of the page. You can use this media query to define rules that apply in that situation.
@media screen and (max-width: 800px) {
}
In the media query redefine the grid-template-areas to something like this:
"h h h"
"m m m"
"s s s";
Notice the sidebar has been moved to the bottom!
The Zen Garden page has three main sections: intro, main, and sidebar. You can use a grid to arrange these but you'd need to define another grid to arrange the children of each of these sections. For example main contains the children: explantion, participation, benefits, requirements, and footer.
The power of grids fro design is that it gives everything a visual reference to work from. To align nested elements you'd need to define a new grid and make sure that grid used the same column structure as the parent grid.
This probably can be more easily solved with subgrid. Subgrid inherits the grid-template-columns and grid-template-rows from the parent grid.
CSS subgrid is a feature of CSS Grid Layout that allows a nested grid item (a grid inside a grid) to inherit the rows and columns from its parent grid, making it easier to create complex layouts that are aligned with the outer grid structure. When using subgrid, the child grid aligns its rows or columns with the parent grid, which can help maintain consistent alignment and spacing across nested elements without duplicating grid definitions.
For example:
.parent {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: auto;
}
.child {
display: grid;
grid-template-columns: subgrid; /* Inherits columns from the parent */
}
This lets the child grid align directly with the parent’s grid lines, making it especially useful in designs where you want inner items to follow the parent grid’s structure.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Subgrid
CSS Grid relies on the line numbers generated automatically by the grid structure, rather than custom names. Here’s an example of the same layout but using numbered lines instead of named ones.
.container {
display: grid;
grid-template-columns: 1fr 2fr;
}
.item {
grid-column: 1 / 2; /* Positions the item from column line 1 to line 2 */
}
In this setup, grid-column: 1 / 2;
positions .item
between the first and second column lines. While this is straightforward for simple grids, it can become less readable in more complex layouts where specific sections are better referenced by name.
When mapping a grid items to columns you can specify the columns. For example: grid-column: 1 / 3
creates an item that starts at line 1 and ends at line 3, spanning two columns.
Use the span
keyword to specify the number of columns. For example: grid-column: 1 / span 2
, works same as the previous example, creating an item that starts at line 1 and spans two columns.
This can be used in reverse also. For example: grid-column: span 2 / 3
. This creates a two column item, ending at grid line 3.
span
can also be used with grid-area
, for example: grid-area: span 6 / span 4;
here the element spans 6 columns and 4 rows!
https://css-tricks.com/almanac/properties/g/grid-column/
In CSS Grid, named columns let you assign names to grid lines, making it easier to position items within the grid. You can name grid lines in the grid-template-columns
or grid-template-rows
properties by placing names in square brackets. This helps you reference specific lines by name rather than by number, improving readability and maintainability.
For example:
.container {
display: grid;
grid-template-columns: [start] 1fr [middle] 2fr [end];
}
.item {
grid-column: start / middle; /* Positions the item from 'start' to 'middle' */
}
Here, the item
spans from the start
line to the middle
line, making it clear where it should be positioned without relying on numeric line indexes.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Grid_layout_using_named_grid_lines
The grid-auto-flow
property in CSS Grid controls how items are placed in the grid when there's no specific placement defined for them. It determines both the direction items flow and how they fill available spaces.
row
: This is the default value. Items are placed in rows from left to right, wrapping into new rows as needed.column
: Items are placed in columns from top to bottom, creating new columns as needed.dense
: Works as an add-on torow
orcolumn
. Withdense
, the grid tries to fill in any gaps left by larger items, making the layout more compact by backfilling available spaces with smaller items.
.container {
display: grid;
grid-auto-flow: row dense; /* Fills gaps in row-wise placement */
}
In this example, items are laid out row by row, with the grid attempting to fit smaller items into any open spaces, optimizing the grid's compactness.
Here's a simple HTML file that demonstrates grid-auto-flow
with row
, column
, and dense
. This example uses some basic CSS to show how items flow and fill in the gaps when grid-auto-flow: row dense
is applied.
Try this example.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Grid Auto Flow Example</title>
<style>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
gap: 1rem;
margin: 2rem;
}
/* Toggle this line for different grid-auto-flow effects */
/* grid-auto-flow: row; */
/* grid-auto-flow: column; */
.container.row-dense {
/* grid-auto-flow: row dense; */
grid-auto-flow: row;
/* grid-auto-flow: column; */
/* When auto columns is set extra columns are generated! */
/* grid-auto-flow: column dense; */
}
.container.column-dense {
grid-template-rows: 100px 100px 100px 100px;
grid-auto-flow: column dense;
}
.item {
background-color: #4CAF50;
color: white;
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
}
/* Larger items for gaps illustration */
.item-1 { grid-row: span 2; }
.item-4 { grid-row: span 3; }
</style>
</head>
<body>
<h1>CSS Grid Auto Flow Example</h1>
<h2>Grid with <code>grid-auto-flow: row dense</code></h2>
<div class="container row-dense">
<div class="item item-1">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item item-4">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
<h2>Grid with <code>grid-auto-flow: column dense</code></h2>
<div class="container column-dense">
<div class="item item-1">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item item-4">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
</body>
</html>
row dense
: In the first example (.row-dense
), items are placed row by row. Thedense
keyword backfills gaps created by the larger items (like 1 and 4), so smaller items can fill in those spaces.column dense
: In the second example (.column-dense
), items are placed in columns, filling each column top to bottom before moving to the next. Thedense
keyword again helps fill gaps when possible, optimizing space vertically.
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-auto-flow