180 Days of Frontend Development Challenge: Day 34 CSS Advanced Grid Layouts



This content originally appeared on DEV Community and was authored by CodeWithDhanian

Welcome back, coding companions! You’ve successfully navigated the basics of CSS Grid, and today, on Day 34, we’re kicking things up a notch with CSS Advanced Grid Layouts. If yesterday was about setting the foundation, today is about building the multi-story masterpiece!

We’ll dive into some powerful Grid features that give you even more granular control and flexibility, allowing you to create complex, adaptive designs with surprisingly little code.

Beyond the Basics: Advanced Grid Capabilities

You’ve learned to define rows and columns, place items by line numbers or named areas, and manage gaps. That’s a solid start! But what if you need more dynamic sizing, automatic placement, or tighter alignment control within cells? That’s where advanced Grid concepts come into play.

Key Concepts We’ll Master Today:

  1. repeat() Function: Tired of typing 1fr 1fr 1fr 1fr for 10 columns? The repeat() function lets you define a pattern of tracks that repeats a specified number of times. This saves you a ton of typing and makes your CSS much cleaner.
  * **Syntax**: `repeat(number_of_times, track_size)`
  * **Example**: `grid-template-columns: repeat(4, 1fr);` creates four equal columns.
  * You can also mix it: `grid-template-columns: 50px repeat(3, 1fr) 50px;`
  1. minmax() Function: This is a powerhouse for responsive design. minmax() defines a size range for a grid track. The track will be no smaller than min and no larger than max.
  * **Syntax**: `minmax(min_size, max_size)`
  * **Example**: `grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));` is a common pattern for responsive grids. It says: create as many 200px columns as can fit, but if there's extra space, make them grow equally to fill it.
  1. auto-fill and auto-fit Keywords: Used with repeat(), these keywords control how many columns or rows are created based on the available space. They’re game-changers for truly fluid layouts.
  * **`auto-fill`**: Fills the row with as many columns as possible, even creating empty tracks if content doesn't fill them. This can leave empty spaces if you have fewer items than would fit.
  * **`auto-fit`**: Similar to `auto-fill`, but it *collapses* any empty tracks if there aren't enough grid items to fill them. This ensures your items stretch to fill the available space without empty gaps when the number of items changes.
  * **Common use**: `grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));`
  1. Implicit Grid (Grid Flow): What happens if you have more grid items than explicitly defined rows or columns? CSS Grid automatically creates an “implicit grid” to hold them.
  * **`grid-auto-rows` / `grid-auto-columns`**: These properties define the size of any *implicitly created* rows or columns.
  * **`grid-auto-flow`**: Controls how auto-placed items fill the grid. Default is `row` (fills row by row). You can set it to `column` (fills column by column) or add `dense` to try and fill any holes in the grid.
  1. Alignment within Grid Cells: Just like Flexbox, Grid gives you alignment control, but it applies to items within their own grid cells.
  * **`justify-items` (horizontal)** and **`align-items` (vertical)** on the grid *container*: Aligns all items within their respective cells.
  * **`justify-self` (horizontal)** and **`align-self` (vertical)** on individual *grid items*: Overrides the container's alignment for a single item.
  * Values: `start`, `end`, `center`, `stretch` (default)

Let’s Get Our Hands Dirty (Code Examples):

Imagine building a dynamic photo gallery or product listing.

HTML:

<div class="gallery-container">
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x150?text=Photo+1" alt="Photo 1">
        <h3>Sunset View</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x180?text=Photo+2" alt="Photo 2">
        <h3>Mountain Peaks</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x160?text=Photo+3" alt="Photo 3">
        <h3>City Lights</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x200?text=Photo+4" alt="Photo 4">
        <h3>Forest Path</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x170?text=Photo+5" alt="Photo 5">
        <h3>Beach Escape</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x190?text=Photo+6" alt="Photo 6">
        <h3>River Bend</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x150?text=Photo+7" alt="Photo 7">
        <h3>Desert Dunes</h3>
    </div>
    <div class="gallery-item">
        <img src="https://via.placeholder.com/200x180?text=Photo+8" alt="Photo 8">
        <h3>Volcano Ridge</h3>
    </div>
</div>

CSS (Basic Grid Setup):

.gallery-container {
    display: grid;
    gap: 15px; /* Consistent spacing */
    padding: 20px;
    background-color: #f0f0f0;
}

.gallery-item {
    background-color: white;
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 10px;
    text-align: center;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.gallery-item img {
    max-width: 100%;
    height: auto;
    border-radius: 4px;
    margin-bottom: 8px;
}

Example 1: Responsive Columns with repeat(), auto-fit, and minmax()

This is one of the most powerful patterns for responsive grids. It creates as many columns as can fit, with each column being at least 250px wide but growing to fill available space.

.gallery-container {
    display: grid;
    gap: 15px;
    padding: 20px;
    background-color: #f0f0f0;

    /* Magic happens here! */
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

Explanation: Resize your browser window! You’ll see the columns fluidly adjust.

  • repeat(auto-fit, ...): As many columns as possible will be created.
  • minmax(250px, 1fr): Each column will be at least 250px wide. If there’s more space available, they’ll expand evenly (due to 1fr) to fill it. If the screen is too narrow for even one 250px column, it will still shrink below 250px because minmax defines a preferred minimum, but the 1fr allows for shrinking to fit. To strictly prevent shrinking, you might use a fixed value or min-content instead of minmax or combine with grid-auto-columns.

Example 2: Using auto-fill vs. auto-fit (and grid-auto-rows)

Let’s adjust the minmax to something smaller to easily see the difference between auto-fill and auto-fit when you have fewer items than fit. We’ll also define how implicitly created rows behave.

.gallery-container {
    display: grid;
    gap: 15px;
    padding: 20px;
    background-color: #f0f0f0;

    /* Try switching auto-fill to auto-fit and observe! */
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    grid-auto-rows: 200px; /* Any rows created implicitly will be 200px tall */
    /* Try adding fewer .gallery-item elements than can fit to see the difference */
}

Explanation:

  • auto-fill: If your container is wide enough for, say, 5 columns of 150px, but you only have 3 .gallery-item elements, auto-fill will still create those 5 columns, leaving 2 empty grid tracks. This can be useful for maintaining a consistent visual rhythm even with dynamic content.
  • auto-fit: In the same scenario, auto-fit would collapse those 2 empty tracks, allowing your 3 items to expand and fill the entire row. This is generally preferred for fluid, content-driven layouts where you want items to stretch.
  • grid-auto-rows: 200px;: If you add a 7th, 8th, or 9th item, and the grid automatically creates new rows for them (because you haven’t explicitly defined 3 rows), these new rows will each be 200px tall.

Example 3: Controlling Implicit Flow and Dense Packing

Let’s say we define a 3-column grid, and then we have items of different sizes, and we want Grid to fill in the gaps.

<div class="grid-container-dense">
    <div class="item wide">Wide Item</div>
    <div class="item tall">Tall Item</div>
    <div class="item">Item 3</div>
    <div class="item">Item 4</div>
    <div class="item tall">Tall Item 5</div>
    <div class="item">Item 6</div>
    <div class="item wide">Wide Item 7</div>
</div>
.grid-container-dense {
    display: grid;
    grid-template-columns: repeat(3, 1fr); /* Explicitly 3 columns */
    grid-auto-rows: minmax(100px, auto); /* Implicit rows will be at least 100px, or auto for content */
    gap: 10px;
    padding: 20px;
    background-color: #e6e6fa;
    height: 600px; /* Give container some height to see flow */

    /* The magic! */
    grid-auto-flow: dense; /* Tries to fill empty spaces with smaller items */
}

.grid-container-dense .item {
    background-color: #a0d9e8;
    border: 1px solid #7cb1c4;
    padding: 15px;
    text-align: center;
    font-weight: bold;
    border-radius: 5px;
}

.grid-container-dense .wide {
    grid-column: span 2; /* Span across 2 columns */
    background-color: #8ed6bb;
}

.grid-container-dense .tall {
    grid-row: span 2; /* Span across 2 rows */
    background-color: #f7b76e;
}

Explanation: grid-auto-flow: dense; is fantastic for “masonry” like layouts or dashboards where items might have different sizes and you want to pack them as tightly as possible, minimizing white space. Without dense, items would flow strictly in order, potentially leaving larger gaps if a wide item comes after a tall one that leaves a space. dense allows the algorithm to backfill.

Example 4: Aligning Items within their Cells (justify-items, align-items, justify-self, align-self)

Let’s create a small grid and control the placement of its contents within each cell.

<div class="alignment-grid">
    <div class="align-item">Top Left</div>
    <div class="align-item">Center</div>
    <div class="align-item specific-align">Bottom Right</div>
    <div class="align-item">Stretch</div>
</div>
.alignment-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr); /* 2 equal columns */
    grid-template-rows: repeat(2, 100px); /* 2 rows, each 100px tall */
    gap: 5px;
    padding: 20px;
    background-color: #f9f9f9;
    height: 250px;
    width: 400px;

    /* Align all items in the grid to the center */
    justify-items: center; /* Horizontally center contents within their cells */
    align-items: center;   /* Vertically center contents within their cells */
}

.alignment-grid .align-item {
    background-color: #b0e0e6;
    border: 1px solid #87ceeb;
    padding: 10px;
    font-size: 0.9em;
    display: flex; /* Using flex to align text within the item if needed, but grid applies to the item itself */
    justify-content: center;
    align-items: center;
}

.alignment-grid .specific-align {
    /* Override for a single item */
    justify-self: end; /* Place content at the end of its column cell */
    align-self: end;   /* Place content at the bottom of its row cell */
    background-color: #ffb6c1;
}

Explanation: justify-items and align-items set the default alignment for all grid items inside the container. justify-self and align-self then allow you to override this default for specific items. This is crucial for precise positioning of individual components within your grid structure.

Your Challenge for Day 34:

  1. Create a main layout container using CSS Grid.
  2. Implement a responsive column structure using repeat(), auto-fit, and minmax() that ensures items are at least 280px wide but fill the available space.
  3. Add at least 8 grid items to this container. Make some of them span multiple columns (grid-column: span X;) or rows (grid-row: span Y;).
  4. Experiment with grid-auto-flow: dense; to see how Grid tries to fill in any empty spaces created by spanned items. Observe the difference if you remove dense.
  5. Define a grid-auto-rows value to control the height of any implicitly created rows (e.g., if you add more items than initially fit into the explicit grid definition).
  6. Apply justify-items and align-items to your grid container to set a default alignment for all items.
  7. Override the default alignment for at least two specific grid items using justify-self and align-self.
  8. Bonus: Add a media query to your layout. At a smaller screen size, change the grid-template-columns to something simpler (e.g., 1fr) and observe how your advanced grid adapts.

This day’s concepts unlock the true power of CSS Grid for building highly flexible and maintainable layouts. It might take a bit of mental juggling initially, but the payoff in simplified, robust CSS is immense.

Keep pushing forward! Each day brings you closer to becoming a front-end layout master. What intricate layouts are you starting to envision with these new Grid powers?


This content originally appeared on DEV Community and was authored by CodeWithDhanian