Grid Layout Fundamentals

Module 6: Modern CSS & Layouts - Tuesday (Lecture 1)

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.

graph TD A[CSS Layout Systems] --> B[Table Layouts] A --> C[Float-Based Layouts] A --> D[Flexbox] A --> E[CSS Grid] B --> F[Limited, not semantic] C --> G[Complex to manage] D --> H[One-dimensional layouts] E --> I[Two-dimensional layouts] style E fill:#f9f,stroke:#333,stroke-width:2px

"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:

In practical terms:

graph LR subgraph "Use Flexbox For" A[One-dimensional layouts] B[Content-first designs] C[Small-scale layouts] D[Distributing space/aligning items in a row or column] end subgraph "Use Grid For" E[Two-dimensional layouts] F[Layout-first designs] G[Overall page layout] H[Precise control of both rows and columns] end

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:

graph TD subgraph "Grid (Page Layout)" A[Header] --- B[Main Content] B --- C[Footer] B --- D[Sidebar] end subgraph "Flexbox (Component Layout)" E[Nav Items in Header] F[Form Controls] G[Card Elements] end

Grid Terminology

Understanding Grid starts with learning its terminology:

A helpful mental model is to think about city planning:

Grid Container 1 2 3 4 5 1 2 3 4 Track 1 (Row 1) Track 2 (Row 2) Track 3 (Row 3) Track 2 (Column 2) Track 3 (Column 3) Grid Area (2, 2) to (3, 4) Grid Cell

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:

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.

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.

column-gap row-gap

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:

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:

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:

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:

Exercise 2: Responsive Image Gallery

Create an image gallery with these requirements:

Exercise 3: Dashboard Layout

Create a dashboard layout with:

Challenge Exercise: Holy Grail Layout

Implement the classic "Holy Grail" layout with CSS Grid:

Summary and Next Steps

In this lecture, we've introduced the fundamentals of CSS Grid:

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: