CSS Grid Layout Mastery

1. Grid Container Setup and Properties

Property Values Description Default
display grid | inline-grid Creates grid container (block or inline level) -
grid-template-columns track-size ... Defines column tracks (widths) none
grid-template-rows track-size ... Defines row tracks (heights) none
grid-template-areas "area names" Named grid areas for item placement none
grid-template rows / columns Shorthand for rows, columns, areas none
gap / grid-gap row-gap column-gap Spacing between rows and columns 0
row-gap length Spacing between rows 0
column-gap length Spacing between columns 0
justify-items start | center | end | stretch Align items horizontally within cells stretch
align-items start | center | end | stretch Align items vertically within cells stretch
place-items align justify Shorthand for align-items and justify-items stretch
justify-content start | center | end | space-between | space-around | space-evenly Align entire grid horizontally in container start
align-content start | center | end | space-between | space-around | space-evenly Align entire grid vertically in container start
place-content align justify Shorthand for align-content and justify-content start
grid-auto-columns track-size Size of implicit columns (auto-created) auto
grid-auto-rows track-size Size of implicit rows (auto-created) auto
grid-auto-flow row | column | dense Auto-placement algorithm direction row
Track Sizing Syntax Description Example
Fixed px, rem, % Fixed size tracks 200px 300px
fr Unit 1fr 2fr Flexible fraction of available space 1fr 2fr (1:2 ratio)
auto auto Size based on content auto 1fr auto
min-content min-content Smallest possible without overflow min-content 1fr
max-content max-content Largest content size without wrapping max-content 1fr
minmax() minmax(min, max) Size range between min and max minmax(200px, 1fr)
fit-content() fit-content(limit) min(max-content, max(min-content, limit)) fit-content(300px)
repeat() repeat(count, tracks) Repeat track pattern count times repeat(3, 1fr)
auto-fill repeat(auto-fill, size) Creates as many tracks as fit repeat(auto-fill, 200px)
auto-fit repeat(auto-fit, size) Like auto-fill but collapses empty tracks repeat(auto-fit, minmax(200px, 1fr))

Example: Basic grid setup

/* Simple grid - 3 equal columns */
.grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    /* Or shorter: */
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

/* Fixed and flexible columns */
.layout {
    display: grid;
    grid-template-columns: 250px 1fr 200px; /* Sidebar, main, aside */
    grid-template-rows: auto 1fr auto; /* Header, content, footer */
    gap: 20px;
    min-height: 100vh;
}

/* Responsive grid with auto-fit */
.responsive-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
    /* Items wrap automatically when space is insufficient */
}

Example: Track sizing functions

/* minmax() for flexible constraints */
.grid {
    grid-template-columns: 
        minmax(200px, 300px)  /* Between 200px and 300px */
        minmax(0, 1fr);       /* Grows but can shrink to 0 */
}

/* auto-fill vs auto-fit */
.auto-fill {
    /* Creates empty tracks if space available */
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.auto-fit {
    /* Collapses empty tracks, items grow to fill */
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

/* Complex patterns */
.complex {
    grid-template-columns: 
        200px              /* Fixed sidebar */
        repeat(3, 1fr)     /* 3 equal flexible columns */
        minmax(150px, 20%); /* Constrained column */
}

2. Grid Item Placement and Spanning

Property Values Description Example
grid-column-start line | span n Start column line number grid-column-start: 1;
grid-column-end line | span n End column line number grid-column-end: 3;
grid-column start / end Shorthand for column start and end grid-column: 1 / 3;
grid-row-start line | span n Start row line number grid-row-start: 1;
grid-row-end line | span n End row line number grid-row-end: 4;
grid-row start / end Shorthand for row start and end grid-row: 1 / 4;
grid-area row-start / col-start / row-end / col-end Shorthand for all placement properties grid-area: 1 / 1 / 3 / 4;
span keyword span n Span n tracks from start position grid-column: span 2;
-1 (negative) -1, -2, -3... Count from end (right/bottom) grid-column: 1 / -1;
justify-self start | center | end | stretch Horizontal alignment within cell justify-self: center;
align-self start | center | end | stretch Vertical alignment within cell align-self: center;
place-self align justify Shorthand for align-self and justify-self place-self: center;

Example: Item placement with line numbers

/* Grid with 3 columns, 3 rows */
.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 100px);
    gap: 10px;
}

/* Place item from column 1 to 3 (spans 2 columns) */
.item1 {
    grid-column: 1 / 3;  /* Start at line 1, end at line 3 */
    grid-row: 1 / 2;     /* First row */
}

/* Alternative: using span */
.item2 {
    grid-column: span 2;  /* Span 2 columns from auto position */
    grid-row: 2;
}

/* Full row span */
.header {
    grid-column: 1 / -1;  /* From first to last column */
}

/* Complex placement */
.featured {
    grid-column: 2 / 4;  /* Columns 2-3 */
    grid-row: 1 / 3;     /* Rows 1-2 (spans 2 rows) */
}

Example: Spanning and negative indices

/* Span multiple columns/rows */
.wide {
    grid-column: span 3;  /* Span 3 columns */
}

.tall {
    grid-row: span 2;  /* Span 2 rows */
}

/* Negative line numbers (count from end) */
.full-width {
    grid-column: 1 / -1;  /* First to last column */
}

.last-column {
    grid-column: -2 / -1;  /* Second-to-last to last */
}

/* Shorthand grid-area */
.box {
    /* row-start / col-start / row-end / col-end */
    grid-area: 1 / 2 / 3 / 4;
}

/* Self-alignment */
.centered {
    place-self: center;  /* Center in both directions */
}

3. Grid Template Areas and Named Lines

Feature Syntax Description Use Case
grid-template-areas "area1 area2" "area3 area4" Visual ASCII-art layout definition Semantic page layouts
grid-area (name) grid-area: name; Assign item to named area Place items in template areas
. (dot) "header . sidebar" Empty cell (no content) Gaps in layout
Named Lines [name] size [name] Name grid lines for reference Semantic line references
Line Name Syntax grid-column: name-start / name-end; Reference named lines Readable placement code

Example: Grid template areas

/* Visual layout definition */
.page {
    display: grid;
    grid-template-columns: 200px 1fr 150px;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "header  header  header"
        "sidebar content aside"
        "footer  footer  footer";
    gap: 1rem;
    min-height: 100vh;
}

/* Assign items to areas */
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside   { grid-area: aside; }
.footer  { grid-area: footer; }

/* Empty cells with dot */
.layout-with-gap {
    grid-template-areas:
        "logo  nav    nav"
        "main  main   ."
        "footer footer footer";
}

Example: Named grid lines

/* Define named lines */
.grid {
    display: grid;
    grid-template-columns: 
        [main-start] 1fr 
        [content-start] 2fr 
        [content-end] 1fr 
        [main-end];
    grid-template-rows:
        [header-start] auto
        [header-end content-start] 1fr
        [content-end footer-start] auto
        [footer-end];
}

/* Use named lines for placement */
.header {
    grid-column: main-start / main-end;
    grid-row: header-start / header-end;
}

.main-content {
    grid-column: content-start / content-end;
    grid-row: content-start / content-end;
}

/* Multiple names for same line */
.grid-multi {
    grid-template-columns:
        [sidebar-start] 250px
        [sidebar-end main-start] 1fr
        [main-end];
}
Note: Grid template areas create a visual representation of layout in code. Named lines provide semantic meaning to grid structure. Both improve code readability.

4. Implicit Grid Behavior and Auto-placement

Property Values Description Use Case
grid-auto-flow row | column | dense Direction for auto-placed items Control placement algorithm
row (default) grid-auto-flow: row; Fill rows first, then create new row Horizontal reading order
column grid-auto-flow: column; Fill columns first, then create new column Vertical reading order
dense grid-auto-flow: row dense; Fill gaps with smaller items (reorder) Masonry-like layouts
grid-auto-rows size Size of implicitly created rows Auto-generated row height
grid-auto-columns size Size of implicitly created columns Auto-generated column width

Example: Auto-placement behavior

/* Explicit grid: 3 columns, 2 rows */
.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: 100px 100px;
    gap: 10px;
}

/* If more than 6 items, implicit rows are created */
.grid {
    grid-auto-rows: 100px;  /* Size for auto-created rows */
}

/* Column flow instead of row */
.column-flow {
    display: grid;
    grid-template-rows: repeat(3, 100px);
    grid-auto-flow: column;  /* Create new columns as needed */
    grid-auto-columns: 200px; /* Size of auto columns */
}

/* Dense packing (fills gaps) */
.masonry {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-flow: dense;  /* Fill gaps with later items */
    gap: 10px;
}

.item-large {
    grid-column: span 2;  /* Takes 2 columns */
}

Example: Implicit vs explicit tracks

/* Explicit: defined tracks */
.grid {
    display: grid;
    grid-template-columns: 200px 1fr 200px;  /* 3 explicit columns */
    grid-template-rows: auto 1fr;            /* 2 explicit rows */
    
    /* Implicit: auto-created when items overflow */
    grid-auto-rows: minmax(100px, auto);     /* Auto rows grow with content */
    grid-auto-columns: 200px;                /* Auto columns fixed */
}

/* Items beyond explicit grid create implicit tracks */
.item {
    grid-column: 1;   /* Uses explicit column */
}

.item-overflow {
    grid-column: 5;   /* Creates implicit columns 4 and 5 */
}

/* Auto-fit with implicit rows */
.responsive {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    grid-auto-rows: 200px;  /* All rows (implicit) are 200px */
}
Warning: grid-auto-flow: dense can change visual order from DOM order, which may confuse screen readers and keyboard navigation. Use carefully for accessibility.

5. Subgrid Implementation and Use Cases NEW

Feature Syntax Description Use Case
subgrid grid-template-columns: subgrid; Inherits parent's column tracks Nested grids aligned to parent
subgrid rows grid-template-rows: subgrid; Inherits parent's row tracks Vertical alignment across nested items
Both axes grid-template: subgrid / subgrid; Inherits both rows and columns Complete parent grid alignment
Named lines Inherited from parent Subgrid can use parent's named lines Semantic line references

Example: Subgrid basics

/* Parent grid */
.parent {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
}

/* Child item spans multiple columns and becomes subgrid */
.child-grid {
    grid-column: span 4;  /* Spans all 4 parent columns */
    
    display: grid;
    grid-template-columns: subgrid;  /* Inherits 4 columns from parent */
    gap: 0.5rem;  /* Can override gap */
}

/* Grandchildren align to parent grid */
.grandchild {
    /* Automatically placed in parent's column tracks */
}

/* Practical: Card with aligned content */
.card-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
}

.card {
    display: grid;
    grid-template-rows: subgrid;  /* Align card sections vertically */
    grid-row: span 3;  /* Card spans 3 rows: image, title, description */
}

Example: Subgrid for consistent alignment

/* Product cards with aligned prices */
.products {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    grid-auto-rows: auto auto auto 1fr auto;  /* image, title, desc, spacer, price */
    gap: 1rem;
}

.product-card {
    display: grid;
    grid-template-rows: subgrid;  /* Inherit parent's 5 rows */
    grid-row: span 5;  /* Span all 5 rows */
    border: 1px solid #ddd;
    padding: 1rem;
}

/* All cards' prices align horizontally */
.product-image { grid-row: 1; }
.product-title { grid-row: 2; }
.product-desc { grid-row: 3; }
.product-price { grid-row: 5; }  /* Always at same height */

/* Form with label/input alignment */
.form {
    display: grid;
    grid-template-columns: [labels] 150px [inputs] 1fr;
    gap: 1rem;
}

.form-row {
    display: grid;
    grid-template-columns: subgrid;  /* Inherit label/input columns */
    grid-column: 1 / -1;  /* Span all columns */
}
Note: Subgrid enables alignment across nesting levels. Nested grid items can align with parent grid tracks. Browser support: Firefox 71+, Safari 16+, Chrome 117+

6. Grid vs Flexbox Decision Matrix

Criteria Use Flexbox Use Grid Reason
Dimension 1-dimensional (row OR column) 2-dimensional (rows AND columns) Grid handles both axes simultaneously
Content-driven ✓ Items control layout ✗ Container controls layout Flexbox better for variable content sizes
Layout-driven ✗ Content-first approach ✓ Structure-first approach Grid better for defined layouts
Wrapping Limited control (flex-wrap) Full control (grid-auto-flow, areas) Grid provides precise wrapping control
Alignment Single axis at a time Both axes independently Grid aligns items in both directions
Gap control Simple gap property Row-gap and column-gap separately Grid offers more granular spacing
Browser Support Excellent (IE10+ with prefixes) Good (IE11+ with prefixes, limited) Flexbox has wider legacy support
Overlapping Not native (needs absolute positioning) Native (grid items can overlap) Grid naturally supports overlays
Use Case Best Choice Why Alternative
Navigation bar Flexbox 1D horizontal layout, variable content Grid works but overkill
Page layout Grid 2D structure (header, sidebar, content, footer) Flexbox requires nesting
Card grid Grid Equal heights, precise columns/rows Flexbox with wrapping works
Button group Flexbox Content-driven sizing, simple alignment Grid is more complex
Form layout Grid Label/input alignment, multiple rows Flexbox needs nesting
Media object Flexbox Image + text, simple horizontal layout Grid works but simpler with Flex
Image gallery Grid Precise rows/columns, equal sizing Flexbox can work with wrap
Centering Either Both excellent for centering Flexbox slightly simpler
Dashboard Grid Complex 2D layout, overlapping panels Flexbox too complex
Responsive columns Grid auto-fit/auto-fill, precise control Flexbox with calc() more complex

Example: When to combine both

/* Grid for page structure */
.page {
    display: grid;
    grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
    grid-template-columns: 250px 1fr;
}

/* Flexbox for navigation inside header */
.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* Grid for card layout */
.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 1rem;
}

/* Flexbox for card content */
.card {
    display: flex;
    flex-direction: column;
}

.card-footer {
    margin-top: auto;  /* Push to bottom with flexbox */
}

Grid Best Practices

  • Use fr units for flexible, proportional sizing
  • Use repeat(auto-fit, minmax(...)) for responsive grids without media queries
  • Use grid-template-areas for readable, semantic layouts
  • Use gap instead of margins for consistent spacing
  • Use grid-column: 1 / -1 to span full width
  • Use minmax() to constrain track sizes while maintaining flexibility
  • Use subgrid to align nested grids with parent tracks
  • Combine Grid for page structure, Flexbox for component layout
  • Use Grid for 2D layouts, Flexbox for 1D layouts