Introduction to CSS Grid
CSS Grid Layout (Grid) is a two-dimensional layout system designed specifically for the web. It allows developers to create complex, robust layouts with clean, semantic HTML and streamlined CSS. Unlike Flexbox, which is one-dimensional and mainly excels at distributing space along a single axis, Grid enables precise control of both rows and columns simultaneously.
Grid layout was introduced to address the limitations of previous CSS layout methods, which often required complex workarounds and nested containers to achieve sophisticated designs. By providing a systematic way to define rows, columns, and the relationships between them, Grid simplifies the creation of layouts that were previously difficult or impossible to build.
"CSS Grid is the most powerful layout system in CSS. It brings a fundamentally new approach to solving layout problems that we've been hacking around for as long as we've been making websites." — Jen Simmons, Web Standards Advocate
Grid vs. Flexbox: Understanding the Difference
Before diving deeper into Grid, it's important to understand how it differs from Flexbox and when to use each layout system. Think of it this way:
- Flexbox is like organizing books on a shelf. You control how items are distributed along a single line (the shelf), whether that's horizontally or vertically.
- Grid is like organizing books in a bookcase with multiple shelves. You control both the horizontal and vertical positioning of items across the entire structure.
In practical terms:
In many modern websites, you'll frequently use both Flexbox and Grid together: Grid for the overall layout, and Flexbox for alignment and distribution within grid areas.
For example, consider a typical web application layout:
Grid Terminology
Understanding Grid starts with learning its terminology:
- Grid Container: The element on which
display: gridis applied. - Grid Items: The direct children of the grid container.
- Grid Lines: The dividing lines that make up the grid structure. They can be horizontal (row lines) or vertical (column lines).
- Grid Track: The space between two adjacent grid lines. These are your rows and columns.
- Grid Cell: The intersection of a row and a column - the smallest unit of the grid.
- Grid Area: A rectangular area on the grid that contains one or more grid cells. Areas are defined by their bounding grid lines.
- Grid Gap: The space between rows and columns (also called "gutters").
A helpful mental model is to think about city planning:
- The grid container is like a city's boundaries
- Grid lines are like streets dividing the city
- Grid tracks are like the blocks between streets
- Grid cells are like individual properties or lots
- Grid areas are like city districts or neighborhoods
- Grid gaps are like the width of the streets themselves
Creating a Grid Container
To start using CSS Grid, you first need to establish a grid container by applying display: grid or display: inline-grid to an element:
.container {
display: grid;
}
Just as with Flexbox, this transforms the element into a grid container and its direct children into grid items. However, unlike Flexbox, simply applying display: grid doesn't immediately change the layout's appearance. You need to define the grid's structure using properties like grid-template-columns and grid-template-rows.
Creating Grid Tracks
The fundamental building blocks of a Grid layout are the rows and columns, collectively known as "grid tracks." Define them using the grid-template-columns and grid-template-rows properties:
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 400px auto;
}
This creates a grid with:
- Three columns: A 200px column, a flexible column that takes up the remaining space (1fr), and another 200px column
- Three rows: A row that sizes to its content, a 400px row, and another auto-sized row
The fr unit (fraction) is unique to Grid and represents a fraction of the available space. It's similar to using flex-grow in Flexbox.
Basic Grid Example
Here's a simple 3×2 grid layout:
/* CSS */
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* Three equal columns */
grid-template-rows: 100px 200px; /* Two rows of different heights */
gap: 20px; /* Space between grid items */
}
/* HTML */
<div class="grid-container">
<div class="grid-item">Item 1</div>
<div class="grid-item">Item 2</div>
<div class="grid-item">Item 3</div>
<div class="grid-item">Item 4</div>
<div class="grid-item">Item 5</div>
<div class="grid-item">Item 6</div>
</div>
This creates a grid with six cells arranged in three columns (each taking up one fraction of the available width) and two rows (100px and 200px tall, respectively).
Grid Track Sizing Options
CSS Grid provides several units and functions for defining the size of your tracks:
Fixed Sizes
grid-template-columns: 100px 200px 300px;
Creates three columns with fixed pixel widths. While straightforward, fixed sizes are less flexible for responsive design.
Percentage-Based Sizes
grid-template-columns: 25% 50% 25%;
Creates three columns that take up 25%, 50%, and 25% of the container width, respectively. Percentages are more responsive than fixed pixels, but need to be manually calculated to account for gaps.
Flexible Units (fr)
grid-template-columns: 1fr 2fr 1fr;
The fraction unit (fr) distributes available space proportionally. In this example, the middle column gets twice as much space as the others. The fr unit is calculated after accounting for fixed-size tracks and gaps.
Think of fr units like dividing a pizza: if one person gets 1fr and another gets 2fr, the second person gets a slice twice as large.
Mixing Units
grid-template-columns: 200px 1fr 20%;
Creates a grid with a 200px column, a flexible column that takes the remaining space, and a column that's 20% of the container width.
The auto Keyword
grid-template-columns: auto 1fr auto;
The auto keyword sizes tracks based on their content. This pattern is common for layouts where sidebars should be as wide as their content, with the main content taking up the remaining space.
The repeat() Function
grid-template-columns: repeat(3, 1fr);
The repeat() function creates a repeating pattern of tracks. This example is equivalent to grid-template-columns: 1fr 1fr 1fr;
You can also repeat patterns:
grid-template-columns: repeat(3, 100px 200px);
This creates six columns: 100px, 200px, 100px, 200px, 100px, 200px.
The minmax() Function
grid-template-columns: minmax(100px, 200px) 1fr 1fr;
The minmax() function defines a size range, establishing both a minimum and maximum size for a track. In this example, the first column will be at least 100px wide but won't exceed 200px.
This is similar to how a balloon expands when filled with air but has a maximum size it can reach before popping.
The min-content and max-content Keywords
grid-template-columns: min-content 1fr max-content;
min-content makes a track as small as possible while still fitting its content (like text wrapping to its smallest possible width), while max-content makes it as large as necessary to fit the content without wrapping.
The auto-fill and auto-fit Keywords
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
These keywords enable responsive layouts without media queries. They determine how many tracks can fit based on the container size.
auto-fill: Creates as many tracks as possible, even empty onesauto-fit: Creates tracks for content and collapses empty tracks
Think of auto-fill as reserving seats at a theater, even if some remain empty, while auto-fit only sets up the seats needed for actual attendees.
Grid Gaps
Grid gaps (also called "gutters") create space between rows and columns without affecting the outer edges of the grid.
/* Individual properties */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 20px; /* Space between columns */
row-gap: 30px; /* Space between rows */
}
/* Shorthand property */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px 20px; /* row-gap column-gap */
}
/* Uniform gaps */
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px; /* Both row and column gaps are 20px */
}
Gaps are not margins—they create space only between tracks, not around the outer edge of the grid. This allows for cleaner layouts without the need for complex margin calculations.
Implicit Grid and Auto Rows/Columns
When you define a grid with grid-template-columns and grid-template-rows, you're creating an "explicit grid." However, if you place items outside this defined grid or have more items than cells, Grid automatically creates additional rows and columns, forming an "implicit grid."
You can control how these implicitly created tracks are sized:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* Explicit columns */
grid-template-rows: 100px 100px; /* Explicit rows */
/* Control the size of implicitly created rows */
grid-auto-rows: 200px;
/* Control the size of implicitly created columns */
grid-auto-columns: 50px;
/* Control the direction of auto-placement */
grid-auto-flow: row; /* Default: fills rows before creating new ones */
/* Alternative: grid-auto-flow: column; */
}
This is similar to how a restaurant might have planned seating arrangements (explicit grid) but adds extra tables (implicit grid) when more guests arrive than expected.
The grid-auto-flow property determines how grid items are automatically placed when they don't have an explicit position:
row(default): Items are placed by filling each row, adding new rows as neededcolumn: Items are placed by filling each column, adding new columns as neededdense: Attempts to fill holes earlier in the grid if smaller items come later
Creating a Basic Responsive Grid
One of Grid's most powerful features is the ability to create responsive layouts without media queries. Let's look at how to create a simple image gallery that adapts to different screen sizes:
/* CSS */
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
}
.gallery-item {
height: 200px;
background-size: cover;
background-position: center;
}
/* HTML */
<div class="gallery">
<div class="gallery-item" style="background-image: url('image1.jpg');"></div>
<div class="gallery-item" style="background-image: url('image2.jpg');"></div>
<div class="gallery-item" style="background-image: url('image3.jpg');"></div>
<!-- More gallery items... -->
</div>
In this example, repeat(auto-fill, minmax(250px, 1fr)) dynamically determines how many columns can fit based on the container width. Each column will be at least 250px wide and will expand evenly to fill any extra space.
As the viewport resizes, the number of columns adjusts automatically without media queries. This is similar to how a bookstore might reorganize shelves based on available wall space without changing the size of the books themselves.
Alternative Approach with auto-fit
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
Using auto-fit instead of auto-fill will behave the same when the container is filled with items, but if there are fewer items than would fill the container, auto-fit will expand the items to fill the available space rather than creating empty columns.
Real-World Application: Dashboard Layout
Let's explore a practical example of CSS Grid in action—a responsive dashboard layout with a sidebar, header, main content, and widgets:
/* CSS */
.dashboard {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
.widgets {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
}
/* Responsive adjustment */
@media (max-width: 768px) {
.dashboard {
grid-template-columns: 1fr;
grid-template-rows: auto auto 1fr auto;
grid-template-areas:
"header"
"sidebar"
"main"
"footer";
}
}
/* HTML */
<div class="dashboard">
<header class="header">Dashboard Header</header>
<aside class="sidebar">Sidebar Navigation</aside>
<main class="main">
<div class="widgets">
<div class="widget">Widget 1</div>
<div class="widget">Widget 2</div>
<div class="widget">Widget 3</div>
<div class="widget">Widget 4</div>
</div>
</main>
<footer class="footer">Dashboard Footer</footer>
</div>
This example demonstrates several Grid concepts:
- Named grid areas for intuitive placement
- Nested grids (the widgets container is itself a grid within the main area)
- Responsive design using media queries to redefine the grid layout for smaller screens
The dashboard layout is like the floor plan of a house: on a large lot (desktop), you might have rooms side by side, but on a smaller lot (mobile), you'd stack the rooms vertically to maintain usable space.
Browser Support and Fallbacks
CSS Grid is now supported in all modern browsers, including:
- Chrome 57+ (March 2017)
- Firefox 52+ (March 2017)
- Safari 10.1+ (March 2017)
- Edge 16+ (October 2017)
For projects that need to support older browsers, you can implement fallbacks using feature detection:
/* Fallback for browsers without Grid support */
.container {
display: flex;
flex-wrap: wrap;
}
.item {
width: calc(33.33% - 20px);
margin: 10px;
}
/* Modern Grid layout for supporting browsers */
@supports (display: grid) {
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.item {
width: auto;
margin: 0;
}
}
The @supports rule allows you to apply CSS conditionally based on feature support. This approach is similar to having backup routes when traveling—if the main highway (Grid) isn't available, you take alternate roads (Flexbox or other methods).
Practice Exercises
Exercise 1: Basic Grid Layout
Create a simple 3×3 grid with these requirements:
- Equal-width columns
- The first row should be 100px tall
- The second row should be twice as tall as the first row
- The third row should size to its content
- Add 20px gaps between all cells
Exercise 2: Responsive Image Gallery
Create an image gallery with these requirements:
- The gallery should display a minimum of 3 images per row on large screens
- Images should be at least 200px wide
- The layout should adjust automatically to screen size without media queries
- Images should maintain a 16:9 aspect ratio
Exercise 3: Dashboard Layout
Create a dashboard layout with:
- A header that spans the full width
- A sidebar on the left that's 250px wide
- A main content area that takes up remaining space
- A footer that spans the full width
- The layout should adjust for mobile: header on top, followed by sidebar, main content, and footer, each taking the full width
Challenge Exercise: Holy Grail Layout
Implement the classic "Holy Grail" layout with CSS Grid:
- Header and footer spanning the full width
- A main content area flanked by two sidebars
- On mobile, all sections should stack vertically
- All sections should have minimum height
Summary and Next Steps
In this lecture, we've introduced the fundamentals of CSS Grid:
- Grid terminology and concepts
- Creating a grid container and defining tracks
- Various sizing options for rows and columns
- Working with gaps
- Understanding implicit grid behavior
- Building responsive layouts with Grid
- Real-world applications and browser support
Grid is a powerful tool that may take some practice to master. As you work with it more, you'll discover new ways to solve layout challenges that previously required complex workarounds. In our next lecture, we'll dive deeper into Grid Container Properties, exploring more advanced features and techniques.
Additional resources to explore: