Clean Markup

Mastering Nested Layouts and CSS Subgrid Fundamentals

Mastering Nested Layouts and CSS Subgrid Fundamentals

When building a responsive grid of product or article cards, each card typically contains a title, a variable-length description, and a call-to-action footer. Standard CSS Grid only applies to direct children of the grid container, meaning nested elements inside adjacent cards know nothing about the height of their neighbors' headings or body copy.

With the arrival of CSS Grid Layout Level 2 and grid-template-rows: subgrid (shipping in Firefox 71), a nested grid item can span multiple parent rows and adopt those exact shared row tracks for its own children—Combined with a clean display: flex fallback for browsers still implementing the specification.

Example

/* Standard nested grid creates independent row tracks per card */
.card {
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/* Subgrid inherits the shared row tracks from the parent grid */
.card {
  grid-row: span 3;
  display: grid;
  grid-template-rows: subgrid;
}

Input : Multi-column card grid where card titles and descriptions vary in length
Output : Horizontally aligned card headers, body copy, and action footers across every column in a row.

Implementation

<section class="pricing-grid">
  <article class="pricing-card">
    <header class="card-header">
      <h2>Starter</h2>
    </header>
    <div class="card-body">
      <p>Essential analytics and static hosting for personal projects.</p>
    </div>
    <footer class="card-footer">
      <a href="/signup?plan=starter" class="btn">Choose Starter</a>
    </footer>
  </article>

  <article class="pricing-card">
    <header class="card-header">
      <h2>Professional Team Edition</h2>
    </header>
    <div class="card-body">
      <p>
        Automated staging environments, custom domains, role-based access
        controls, and continuous performance auditing for growing teams.
      </p>
    </div>
    <footer class="card-footer">
      <a href="/signup?plan=pro" class="btn">Choose Pro</a>
    </footer>
  </article>
</section>
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  column-gap: 24px;
  row-gap: 0;
}

/* Fallback for browsers without subgrid support */
.pricing-card {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 24px;
  border: 1px solid #d8dee4;
  border-radius: 6px;
  margin-bottom: 24px;
}

.card-body {
  flex: 1 0 auto;
  margin: 16px 0;
}

/* Progressive enhancement with CSS Subgrid */
@supports (grid-template-rows: subgrid) {
  .pricing-grid {
    grid-auto-rows: auto 1fr auto;
    row-gap: 16px;
  }

  .pricing-card {
    grid-row: span 3;
    display: grid;
    grid-template-rows: subgrid;
    margin-bottom: 0;
  }

  .card-body {
    margin: 0;
  }
}

Main Point: Wrap grid-template-rows: subgrid inside an @supports (grid-template-rows: subgrid) feature query paired with a flexbox column fallback so your cards stay resilient across all browsers while gaining strict cross-column track alignment where supported.

Credits

Photo by Hunters Race

← Home