Introduction to Grid Container Properties
In our previous lecture, we introduced CSS Grid and explored its basic concepts. Now, we'll dive deeper into the properties that control grid containers—the elements that establish the grid formatting context.
Grid container properties determine the overall structure, behavior, and alignment of the grid. Mastering these properties gives you precise control over your layouts, helping you build more sophisticated designs.
We'll examine each of these properties in detail, exploring their syntax, behavior, and practical applications.
Grid Template Properties
The grid template properties allow you to define the explicit grid—the rows, columns, and areas that form the structure of your layout.
grid-template-columns and grid-template-rows
These properties define the tracks (columns and rows) of the grid, establishing its basic structure:
.container {
display: grid;
/* Three columns: 100px, 1fr (flexible), 200px */
grid-template-columns: 100px 1fr 200px;
/* Two rows: auto-sized and 200px */
grid-template-rows: auto 200px;
}
We introduced these properties in the previous lecture, but let's explore some additional techniques and use cases:
Named Grid Lines
You can assign names to grid lines, making it easier to position items:
.container {
display: grid;
/* Named column lines */
grid-template-columns:
[sidebar-start] 250px
[sidebar-end content-start] 1fr
[content-end];
/* Named row lines */
grid-template-rows:
[header-start] 100px
[header-end content-start] 1fr
[content-end footer-start] 80px
[footer-end];
}
Line names must be in square brackets and can contain any valid identifier. A line can have multiple names, separated by spaces inside the brackets.
Think of named grid lines like street names in a city—they make it easier to navigate and specify locations without having to count blocks from the edge.
The repeat() Function in Depth
The repeat() function streamlines the definition of repetitive track patterns:
/* Basic repetition */
grid-template-columns: repeat(3, 1fr); /* Same as: 1fr 1fr 1fr */
/* Repeating patterns */
grid-template-columns: repeat(2, 50px 1fr); /* Same as: 50px 1fr 50px 1fr */
/* Combining with other values */
grid-template-columns: 100px repeat(2, 1fr) 100px; /* Same as: 100px 1fr 1fr 100px */
/* Auto-fill and auto-fit */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
The last two examples are particularly powerful for responsive layouts, as they dynamically adjust the number of columns based on available space:
auto-fill: Creates as many tracks as can fit, potentially leaving empty tracks if there's roomauto-fit: Creates only the necessary tracks for content, expanding them to fill any remaining space
To visualize the difference, think of arranging books on a shelf:
auto-fillcreates fixed-width slots regardless of how many books you have, leaving empty slotsauto-fitcreates slots only for your books, then spreads them out to fill the shelf
Using calc() with Grid Templates
The calc() function can be combined with grid layout to create precise sizes:
/* Create 3 equal columns with 20px gutters, without using gap */
grid-template-columns:
calc(33.33% - 40px/3)
calc(33.33% - 40px/3)
calc(33.33% - 40px/3);
/* Mix fixed and flexible sizing */
grid-template-columns: calc(100% - 300px) 300px;
The calc() function enables complex sizing calculations that might otherwise be difficult to express.
grid-template-areas
The grid-template-areas property allows you to define named grid areas, creating a visual representation of your layout directly in your CSS:
.container {
display: grid;
grid-template-columns: 250px 1fr 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
This creates a layout with a header and footer spanning the full width, and a sidebar next to a content area that spans two columns.
Named grid areas must form rectangles—you cannot create L-shaped or disjointed areas. Each line in the value represents a row, and each name represents a cell.
Using a Period for Empty Cells
You can use a period (.) to designate empty cells:
grid-template-areas:
"header header header"
"sidebar content ."
"footer footer footer";
This creates a layout with an empty cell in the top-right of the grid.
Visualizing the Layout
One of the most powerful aspects of grid-template-areas is how it visually represents your layout directly in your CSS. This makes it easier to understand and maintain the structure:
It's like creating a blueprint for your layout that's readable by both humans and browsers.
Implicit Line Names from Areas
An often-overlooked benefit of using named areas is that they automatically generate named grid lines. For each area, lines are created with -start and -end suffixes:
/* When you define */
grid-template-areas: "header header";
/* These line names are implicitly created */
/* [header-start] ... [header-end] (column lines) */
/* [header-start] ... [header-end] (row lines) */
This means you can position other items relative to your named areas without having to explicitly name grid lines:
.new-item {
grid-column: header-start / header-end;
grid-row: header-end / sidebar-end;
}
grid-template Shorthand
The grid-template property is a shorthand for setting grid-template-rows, grid-template-columns, and grid-template-areas in a single declaration:
.container {
display: grid;
grid-template:
[header-start] "header header header" auto [header-end]
[main-start] "sidebar content content" 1fr [main-end]
[footer-start] "footer footer footer" auto [footer-end]
/ 250px 1fr 1fr;
}
The syntax pattern is:
- Define each row with optional line names
- Include the area names for that row in quotes
- Specify the row size
- After all rows, use a forward slash (
/) - Finally, list all column sizes
While this syntax is more compact, it can be harder to read for complex layouts. Use it when the visual structure of your grid is relatively simple.
Grid Gap Properties
Grid gaps create space between rows and columns without affecting the grid container's boundaries:
/* Individual properties */
.container {
row-gap: 20px; /* Space between rows */
column-gap: 30px; /* Space between columns */
}
/* Shorthand property */
.container {
gap: 20px 30px; /* row-gap column-gap */
}
/* Same gap for both */
.container {
gap: 20px; /* Both row and column gaps are 20px */
}
Note: The older properties grid-gap, grid-row-gap, and grid-column-gap have been renamed to gap, row-gap, and column-gap as these properties now apply to other layout methods as well (e.g., Flexbox).
Responsive Gaps
Gaps can be sized using any CSS length unit, including responsive ones:
/* Percentage gaps */
.container {
gap: 5% 3%;
}
/* Viewport-relative gaps */
.container {
gap: 2vh 2vw;
}
/* Calculated gaps */
.container {
gap: calc(10px + 1vmin)
}
Responsive gaps help maintain proportional spacing as the viewport changes size, just as the space between shelves in a bookcase might scale proportionally to the height of the wall.
Grid Auto Properties
The "auto" properties control how the implicit grid behaves—that is, how tracks are created when content overflows the explicitly defined grid:
grid-auto-rows and grid-auto-columns
These properties define the size of automatically created rows and columns:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* Explicit columns */
grid-template-rows: 100px 100px; /* Explicit rows */
grid-auto-rows: 200px; /* Size for implicit rows */
grid-auto-columns: 50px; /* Size for implicit columns */
}
In this example, if you have more items than fit in the explicit grid (3 columns × 2 rows = 6 items), additional rows will be created at 200px tall. Similarly, if you explicitly position an item outside the defined columns, new columns will be created at 50px wide.
Using Auto-Sizing Functions
You can use sizing functions like minmax() with auto properties for more responsive behavior:
/* Ensures minimum height while allowing growth for content */
grid-auto-rows: minmax(100px, auto);
/* Creates responsive columns that maintain minimum width */
grid-auto-columns: minmax(200px, 1fr);
This approach is particularly useful for creating dynamic grids that handle varying content gracefully.
grid-auto-flow
The grid-auto-flow property controls how auto-placed items flow into the grid:
/* Items fill rows from left to right, adding new rows as needed (default) */
grid-auto-flow: row;
/* Items fill columns from top to bottom, adding new columns as needed */
grid-auto-flow: column;
/* Attempts to fill in holes earlier in the grid */
grid-auto-flow: dense;
/* Combines direction with dense packing */
grid-auto-flow: row dense;
Think of grid-auto-flow as determining the primary direction of "reading" the grid, like how text flows in different writing systems:
rowis like reading English (left-to-right, then down to the next line)columnis like reading traditional Japanese (top-to-bottom, then to the next column on the right)
The 'dense' Packing Algorithm
The dense value attempts to fill in holes in the grid by taking items out of order. This can be useful for galleries or card layouts where you want to maximize space usage, but it can disrupt the visual order of elements:
/* HTML */
<div class="gallery">
<div class="tall">1</div>
<div>2</div>
<div class="wide">3</div>
<div>4</div>
<div>5</div>
</div>
/* CSS */
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-flow: row dense; /* Fill in holes */
}
.tall {
grid-row: span 2; /* Takes up 2 rows */
}
.wide {
grid-column: span 2; /* Takes up 2 columns */
}
With dense packing, smaller items will attempt to fill spaces earlier in the grid that might otherwise remain empty. This is similar to how a grocery bagger might place smaller items in gaps between larger ones to maximize space usage.
Grid Alignment Properties
Grid provides powerful alignment capabilities through six properties that control how grid tracks and items align within the container and grid areas.
These properties fall into two categories:
- Content alignment: How grid tracks are distributed within the grid container
- Item alignment: How grid items are aligned within their cells
Content Alignment Properties
These properties distribute extra space between grid tracks:
/* Horizontal alignment of grid tracks (columns) */
.container {
justify-content: start; /* Default: align to the start */
/* Other options: end, center, stretch, space-around, space-between, space-evenly */
}
/* Vertical alignment of grid tracks (rows) */
.container {
align-content: center; /* Centers rows in the container */
/* Other options: start, end, stretch, space-around, space-between, space-evenly */
}
/* Shorthand for both properties */
.container {
place-content: center; /* Both align-content and justify-content: center */
/* Can also use two values: place-content: end space-between; */
}
Content alignment properties only have visible effects when the grid tracks don't occupy all available space in the container.
Item Alignment Properties
These properties control the alignment of grid items within their cells:
/* Horizontal alignment of all grid items in their cells */
.container {
justify-items: center; /* Centers items horizontally in their cells */
/* Other options: start, end, stretch (default) */
}
/* Vertical alignment of all grid items in their cells */
.container {
align-items: center; /* Centers items vertically in their cells */
/* Other options: start, end, stretch (default) */
}
/* Shorthand for both properties */
.container {
place-items: center; /* Both align-items and justify-items: center */
/* Can also use two values: place-items: start end; */
}
By default, grid items stretch to fill their cells. These properties allow you to override that behavior for all items in the grid.
Individual items can override these container-level alignment settings using the justify-self and align-self properties, which we'll cover in the next lecture on grid item properties.
Real-World Application: Card Layout with Varying Content
Alignment properties are particularly useful for layouts with varying content sizes, such as a grid of cards:
/* CSS */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 20px;
justify-items: stretch; /* Cards fill width of their cells */
align-items: stretch; /* Cards fill height of their cells */
}
.card {
display: grid;
grid-template-rows: auto 1fr auto; /* Header, content, footer */
place-items: center; /* Center content within each card section */
padding: 15px;
border: 1px solid #ddd;
border-radius: 8px;
}
.card-header, .card-footer {
width: 100%; /* Full width despite centering */
}
/* HTML */
<div class="card-grid">
<div class="card">
<div class="card-header">Card 1 Title</div>
<div class="card-content">Short content</div>
<div class="card-footer">Footer</div>
</div>
<div class="card">
<div class="card-header">Card 2 Title</div>
<div class="card-content">
Longer content that wraps to multiple lines and
would normally cause this card to be taller
</div>
<div class="card-footer">Footer</div>
</div>
<!-- More cards... -->
</div>
This example uses Grid in two ways:
- The
.card-gridcreates a responsive grid of cards - Each
.carduses Grid to structure its internal layout
The alignment properties ensure that regardless of content length, all cards maintain consistent dimensions and alignment.
The grid Shorthand Property
The grid property is a comprehensive shorthand that sets all the following properties in a single declaration:
grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow
It has two distinct syntax forms:
/* Setting template properties explicitly */
.container {
grid: [header-top] "header header header" 50px [header-bottom]
[main-top] "sidebar content content" 1fr [main-bottom]
/ 150px 1fr 1fr;
}
/* Setting auto-flow and track sizes */
.container {
grid: auto-flow dense 100px / 1fr 2fr;
}
The first syntax is focused on creating a grid using the template properties, while the second syntax prioritizes the auto-flow behavior.
While the grid shorthand is powerful, it's often more readable to use individual properties or the more specific shorthands (grid-template, place-content, etc.) for complex layouts.
Note: When using the grid shorthand, any grid properties you don't explicitly set are reset to their initial values. This can lead to unexpected behavior if you're trying to set only some grid properties while preserving others.
Advanced Techniques and Examples
Responsive Dashboard Layout
Let's create a responsive dashboard layout that adapts to different screen sizes:
/* CSS */
.dashboard {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"sidebar widget-a widget-b"
"sidebar widget-c widget-d"
"footer footer footer";
grid-template-columns: 250px 1fr 1fr;
grid-template-rows: auto 1fr repeat(2, auto) auto;
gap: 20px;
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.widget-a { grid-area: widget-a; }
.widget-b { grid-area: widget-b; }
.widget-c { grid-area: widget-c; }
.widget-d { grid-area: widget-d; }
.footer { grid-area: footer; }
/* Responsive adjustments */
@media (max-width: 900px) {
.dashboard {
grid-template-areas:
"header header"
"main main"
"widget-a widget-b"
"widget-c widget-d"
"sidebar sidebar"
"footer footer";
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto auto auto auto auto;
}
}
@media (max-width: 600px) {
.dashboard {
grid-template-areas:
"header"
"main"
"widget-a"
"widget-b"
"widget-c"
"widget-d"
"sidebar"
"footer";
grid-template-columns: 1fr;
grid-template-rows: repeat(8, auto);
}
}
This example demonstrates several powerful Grid capabilities:
- Complex layout definition using named areas
- Mixing of fixed and flexible sizing for both rows and columns
- Responsive redesign of the entire layout at different breakpoints
The layout transforms from a desktop dashboard with sidebar to a mobile layout with stacked sections, all by simply redefining the grid areas without changing the HTML structure.
Masonry-like Layout
While Grid doesn't directly support true masonry layouts (where items flow into available vertical space regardless of row), we can create a reasonable approximation:
/* CSS */
.masonry-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-auto-rows: 20px;
grid-auto-flow: dense;
gap: 15px;
}
.masonry-item {
grid-row: span var(--rows);
background-color: #f5f5f5;
border-radius: 8px;
overflow: hidden;
}
/* JavaScript to calculate spanning */
document.addEventListener('DOMContentLoaded', () => {
const grid = document.querySelector('.masonry-grid');
const items = document.querySelectorAll('.masonry-item');
items.forEach(item => {
const rowSpan = Math.ceil(item.querySelector('img').height / 20);
item.style.setProperty('--rows', rowSpan);
});
});
/* HTML */
<div class="masonry-grid">
<div class="masonry-item">
<img src="image1.jpg" alt="Image 1">
</div>
<!-- More items... -->
</div>
This approach uses small grid rows (20px) and calculates how many rows each item should span based on its content height. While it requires JavaScript for the calculations, it creates a layout with a masonry-like appearance that leverages Grid's placement capabilities.
Calendar Layout
Grid is perfect for calendar layouts, where days of the week form columns and weeks form rows:
/* CSS */
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: auto repeat(5, 1fr);
gap: 2px;
}
.weekday {
font-weight: bold;
text-align: center;
padding: 10px;
background-color: #f0f0f0;
}
.day {
min-height: 100px;
padding: 5px;
border: 1px solid #ddd;
}
.day.empty {
background-color: #f9f9f9;
}
.day.today {
background-color: #e6f7ff;
}
/* HTML */
<div class="calendar">
<div class="weekday">Sunday</div>
<div class="weekday">Monday</div>
<!-- More weekdays... -->
<div class="day empty"></div>
<div class="day">1</div>
<!-- More days... -->
</div>
This creates a traditional calendar grid with equal-width columns for days of the week. The first row contains weekday labels, and the remaining rows represent weeks of the month. Empty cells at the beginning or end of the month can be styled differently.
Best Practices and Common Pitfalls
Best Practices
- Start with grid areas for complex layouts - They provide a clear visual representation of your layout structure
- Use flexible units (
fr) for main content - They adapt better to different screen sizes than fixed units - Combine
minmax()withauto-fill/auto-fitfor responsive grids without media queries - Choose grid naming conventions carefully - Consistent naming makes layouts easier to understand and maintain
- Consider using CSS variables for grid tracks - Makes it easier to adjust sizes across your design
- Avoid magic numbers for track sizes - Use meaningful units or relationships instead
/* Using CSS variables for grid dimensions */
:root {
--sidebar-width: 250px;
--header-height: 60px;
--grid-gap: 20px;
}
.layout {
display: grid;
grid-template-columns: var(--sidebar-width) 1fr;
grid-template-rows: var(--header-height) 1fr auto;
gap: var(--grid-gap);
}
Common Pitfalls
- Forgetting that the
gridshorthand resets properties - Be careful when using it if you want to preserve some properties - Overusing fixed track sizes - This can lead to overflow issues on smaller screens
- Not accounting for grid gaps in calculations - Remember that gap space affects the total width/height
- Creating non-rectangular grid areas - Grid areas must form rectangles; L-shaped or disjointed areas aren't allowed
- Confusing
align-content/justify-contentwithalign-items/justify-items- The former affects track distribution, the latter affects items within cells - Assuming grid-template-rows/columns will create enough tracks - Set explicit track counts or use auto-sizing properties to handle varying content
Common Error: Incomplete grid-template-areas
A common error is creating uneven grid-template-areas, where rows have different numbers of cells:
/* Incorrect - uneven rows */
grid-template-areas:
"header header"
"sidebar content content"
"footer footer";
The second row has three cells while the others have two, which isn't valid. Each row must have the same number of cells.
/* Correct - all rows have three cells */
grid-template-areas:
"header header header"
"sidebar content content"
"footer footer footer";
Practice Exercises
Exercise 1: Named Grid Areas Layout
Create a classic "holy grail" layout with these requirements:
- Header and footer spanning the full width
- Main content area in the center
- Navigation sidebar on the left
- Ad sidebar on the right
- Use named grid areas to define the layout
- Make the layout responsive, stacking all sections vertically on mobile
Exercise 2: Advanced Grid with Auto-Placement
Create a photo gallery with these requirements:
- Photos should be arranged in a grid with 3-5 columns depending on screen size
- Some photos are twice as wide as others (mark these with a class)
- Some photos are twice as tall as others (mark these with a class)
- Use
grid-auto-flow: denseto create a packed layout with no gaps - Add appropriate gap spacing between items
Exercise 3: Dashboard with Alignment
Create a dashboard layout with:
- A fixed header across the top
- A sidebar with navigation
- Four equal-sized widget areas in a 2×2 grid in the main content area
- Use alignment properties to center content within each widget
- Ensure widgets maintain equal height regardless of content
Challenge Exercise: Calendar
Create a monthly calendar layout:
- Days of the week as column headers
- Weeks as rows
- Empty cells for days not in the current month
- Different styling for weekends
- A highlight for the current day
- Bonus: Add support for events that span multiple days
Summary and Next Steps
In this lecture, we've explored the core properties that define and control CSS Grid containers:
- Grid template properties for defining tracks and areas
- Gap properties for creating space between grid items
- Auto properties for controlling implicit grid behavior
- Alignment properties for distributing space and positioning items
- Shorthand properties for more concise grid definitions
- Advanced techniques and real-world applications
These properties give you tremendous control over the structure and behavior of your layouts. By mastering them, you can create sophisticated, responsive designs with clean, semantic HTML.
In our next lecture, we'll focus on grid item properties—the CSS properties that control how individual grid items are placed, sized, and aligned within the grid. This will complete our exploration of CSS Grid fundamentals.
Additional resources to explore: