惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
O
OpenAI News
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
罗磊的独立博客
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
雷峰网
雷峰网
V
Visual Studio Blog
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
博客园 - 【当耐特】
G
Google Developers Blog
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
AI
AI
Google Online Security Blog
Google Online Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

Ahmad Shadeed

Better fluid sizing with round() Use Cases for Field Sizing The Basics of Anchor Positioning Item Flow CSS Relative Colors Balancing Text In CSS Should masonry be part of CSS grid? CSS display contents CSS Grid Areas CSS Cap Unit An Interactive Guide to CSS Container Queries CSS :has() Interactive Guide CSS Nesting UX in DevTools CSS Nesting Future CSS: State Container Queries Rebuilding a comment component with modern CSS Conditional CSS with :has and :nth-last-child CSS Text balancing with text-wrap:balance CSS Masking Do we need CSS flex-wrap detection? My CSS Wishlist Conditional CSS CSS Style Queries Inside the mind of a frontend developer: Article layout Inside the mind of a frontend developer: Hero section CSS container queries are finally here The CSS behind Figma First Look At The CSS object-view-box Property CSS :has Parent Selector Aligning Content In Different Wrappers Flexbox Dynamic Line Separator Hello, CSS Cascade Layers Building UI Components With SVG and CSS A Deep CSS Dive Into Radial And Conic Gradients Defensive CSS Building Real-life Components: Facebook Messenger Conditional Border Radius In CSS CSS Container Query Units Less Absolute Positioning With Modern CSS Aligning a Button Label Vertically Comparing Design Mockups To Code Result Using HSL Colors In CSS Custom Scrollbars In CSS Let CSS Container Queries For Designers The State of CSS Cross-Browser Development Overflow Issues In CSS Inspect Element As A Way To Increase Your Curiosity Handling Text Over Images in CSS Digging Into CSS Logical Properties Clipping Scrollable Areas On The inline-start Side Understanding Clip Path in CSS The Art of Building Real-life Components Handling Short And Long Content In CSS CSS Scroll Snap A Deep Dive Into CSS Grid minmax() CSS Variables 101 Finding The Root Cause of a CSS Bug Learn CSS centering How to detect browser support for Flexbox Gap CSS Mistakes While On Autopilot Digging Into the Flex Property Understanding CSS Multiple Backgrounds Aligning Logo Images in CSS Grid for layout, Flexbox for components Colors in CSS Thinking About The In-between Design Cases min(), max(), and clamp() CSS Functions Image Techniques On The Web Everything About Auto in CSS Learn Box Alignment Let Learn CSS Positioning Intrinsic Sizing In CSS CSS Grid Template Areas In Action Hiding Elements On The Web Creating a Variable Color Font From Scratch Building a Football Ticket With CSS and SVG Blending Modes in CSS CSS Variables With Inline Styles Implementing Dark Mode For My Website Rebuilding Apple Music Header in HTML & CSS Accessible Checkbox Layout Flickering On Browser Resize Enhancing The Clickable Area Size Custom Underlines with SVG Part 3: The Process of Implementing A UI Design From Scratch Part 2: The Process of Implementing A UI Design From Scratch Building An Old Nav Design CSS Flexbox: 5 Real World Use Cases I Used CSS Inline Flex For The First Time The Process of Implementing A UI Design From Scratch Common CSS Issues For Front-End Projects Handling Long and Unexpected Content in CSS How to Build Web Form Layouts With CSS Grid Grid Layout Ah-ha Moment Enhancing Our Components with CSS :empty Building Resizeable Components with Relative CSS Units CSS Writing Mode The Journey of Learning Front End Web Development on a Daily Basis
Learn CSS Subgrid
Ahmad Shadeed · 2022-05-06 · via Ahmad Shadeed

The Layout Maestro

I spent years teaching CSS layout on this blog. I put everything I know into The Layout Maestro course: 70+ lessons and 150+ interactive examples that teach you how to think CSS layouts, not just memorize syntax.

Get the course

Even though CSS grid is one of the greatest additions to CSS, it was lacking one important thing, which is to make an element inherit the columns or rows from its parent. CSS subgrid can help us in doing that. It has been requested for years and now that both Firefox and Safari Technology Preview support it, I thought about giving it a chance.

In this article, I will try to highlight the problem that subgrid is expected to solve, how it works, and a few potential use-cases for it.

Browser support

Before diving into anything, I want to highlight that subgrid is supported in Firefox v71+ and Safari Technology Preview. We can use it as an enhancement with CSS @supports or to provide a fallback.

The problem

Let’s suppose that we have the following design. There is a title, description, and image. When both the title and description text are equal in length, both images will line up correctly.

However, when the description gets longer, it will push the image down and as a result, the images are no longer aligned.

This is where CSS subgrid comes in handy! Let’s explore the solution.

The solution: using subgrid

We want to divide the content into three rows and make sure they’re aligned with each other. Let’s suppose that we have the following markup.

<div class="wrapper">
  <div class="item">
    <!-- Title, description, and image -->
  </div>
  <div class="item">
    <!-- Title, description, and image -->
  </div>
</div>

In CSS, we will divide the section into two columns and three rows, like this:

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 1rem;
}

.item {
  grid-row: 1 / 4;
}

Here is a visual explanation of what the above looks like.

You might think that the grid lines are for the inner items (title, description, and image). However, those grid row lines are for the main wrapper, and only the .item element can access them. That means the title, description, and image are not accounted for with these rows.

Still not convinced? Here, I added two lines for the description text, and the alignment got broken.

We need to pass the grid rows to the inner items, and this is where CSS subgrid shines. To apply it, we need to add the following to the .item element.

.item {
  /* Make sure that each .item spans from row 1 to 4 */
  grid-row: 1 / 4;

  /* Creates a grid container */
  display: grid;

  /* Applying subgrid, kinda like telling .item to inherit
     * the grid from .wrapper
     */
  grid-template-rows: subgrid;
}

When using subgrid, it’s a kind of letting the .item inherit the grid-template-columns value from its parent (The .wrapper). With that, the grid will look like this.

Now, each inner item is placed within a row. That means, if the content of any inner item gets longer, its row will expand to fit the content. That row is responsible for both the direct child items of the .wrapper element.

This is very useful and will provide us with even more ways to achieve what hasn’t been possible before with CSS grid.

That’s enough theory. Let’s get into a few use-cases!

Use cases and examples

An editorial layout: part 1

In this example, we have a 3-columns layout that contains the following:

  • Headline
  • Featured card
  • Normal card

Here is the basic markup.

<section class="section">
  <h2>Headlines</h2>
  <div class="card card--featured"></div>
  <div class="card"></div>
</section>

As per the following figure, the design was made to take 5 columns in mind. All main elements take one column except for the middle one which is taking 3 columns.

.section {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-gap: 20px;
}

.card--featured {
  grid-column: 2 / 5;
  display: grid;
  grid-template-columns: 1fr 2fr;
}

Here is the result so far. It’s still not perfect. The featured card’s thumbnail isn’t aligned with the start of the third column.

This is where subgrid comes in. Here is the featured card markup:

<div class="card--featured">
  <div class="card--featured__content"></div>
  <div class="card--featured__thumb"></div>
</div>

In order to gain much control over the card--featured element, we need to pass the grid columns to the content and thumb elements.

First, we need to make sure that the featured card spans from columns 2 to 5. Then, we add display: grid and subgrid as the value for grid-template-columns.

.card--featured {
  grid-column: 2 / 5;
  display: grid;
  grid-template-columns: subgrid;
}

Voila! Now the .card--featured element inherited 3 columns from the main wrapper. With that, we can lay out the thumbnail and content based on these columns.

Given that, we can now position the featured card’s thumbnail based on the subgrid columns.

.card--featured {
  grid-column: 2 / 5;
  display: grid;
  grid-template-columns: subgrid;
}

.card--featured__thumb {
  grid-column: 2 / 4;
}

Now the thumbnail is aligned perfectly with the main’s wrapper columns, thanks to subgrid!

CSS subgrid can be inherited

This is the same as the previous example, but with an additional section. In the centered block, I added a list of three mini-articles. I called them “mini” since they only have a title.

Consider the following figure.

As you see, there is a list of three articles which is positioned directly under the featured card. Each list item lives in a column.

Working on this update will require some markup changes. Let’s review it below.

<div class="featured-section">
  <div class="card--featured">
    <div class="card--featured__content"></div>
    <div class="card--featured__thumb"></div>
  </div>
  <ul class="list"></ul>
</div>
.featured-section {
  grid-column: 2 / 5;
  display: grid;
  grid-template-columns: subgrid;
}

.card--featured {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / 4;
}

.card--featured__thumb {
  grid-column: 2 / 4;
}

.list {
  grid-column: 1 / 4;
}

To recap:

  • I moved the grid-column: 2 / 5 to the .featured-section since it’s the direct child of the main grid.
  • Added grid-column: 1 / 4 to the .list element to make it take the full space of its parent (The subgrid).

Next step, we need to apply a subgrid on the inner items of .list, so we can position them perfectly with the featured card thumbnail.

.list {
  grid-column: 1 / 4;
  display: grid;
  grid-template-columns: subgrid;
}

While exploring the potential use-cases for subgrid, I came across an interesting one for a website footer. Here is the markup:

<footer class="site-footer">
  <div class="wrapper">
    <div class="site-footer__item">
      <h2><!-- Title --></h2>
      <ul>
        <!-- Nav items -->
      </ul>
    </div>
    <div class="site-footer__item"></div>
    <div class="site-footer__item"></div>
    <div class="site-footer__item"></div>
  </div>
</footer>

In the figure above, I want the section titles to be aligned. If a title gets too long, then all grow in height to match their sibling that got longer. Without a subgrid, we will end up with something like this:

By default, CSS grid will create an implicit rows that we can take benefit of. In our case, we have two rows. Let’s have a look at the basic CSS:

.site-footer .wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  grid-gap: 2rem;
}

.site-footer__item {
  grid-row: span 2;
}

To apply subgrid, all we need is the following:

.site-footer__item {
  grid-row: span 2;
  display: grid;
  grid-template-rows: subgrid;
  grid-gap: 1rem;
}

Notice that grid-gap is inherited from .site-footer .wrapper but I need to override it to have a smaller space.

Another interesting use-case for subgrid is a photo gallery. In this example, I have a grid of six columns, and a wrapper that contains two main sections (The content and photos).

Design requirements:

  • Align the photos with the parent grid
  • Consistent spacing between the photos and the two main sections

Consider the following markup.

<div class="section">
  <div class="wrapper">
    <div class="start"></div>
    <div class="end">
      <img src="thumb.jpg" alt="" />
      <img src="thumb.jpg" alt="" />
      <img src="thumb.jpg" alt="" />
      <img src="thumb.jpg" alt="" />
      <img src="thumb.jpg" alt="" />
    </div>
  </div>
</div>

With the above, we need to do the following in CSS:

.start {
  grid-column: span 3;
}

.end {
  grid-column: span 3;
  display: grid;
  grid-template-columns: subgrid;
  grid-gap: 1rem;
}

img:nth-child(3) {
  grid-column: 3 / 4;
  grid-row: 1 / 3;
}

img:nth-child(4) {
  grid-column: 1 / 3;
}

Note that the subgrid child items are now positioned according to a new grid line (From 1 to 4).

Replicating the grid

If you don’t already know, we can show the grid lines of a container by using the browser DevTools. I prefer to use Firefox for such things.

The interesting part is that we can create a fake container with empty elements, and place it behind our grid. You might be wondering why? Well, we can do different things with it like visual effects, toggling the grid for debugging purposes, and many more.

Consider the following figure:

Do you see those small squares? Those represent the grid we have, and I created them on purpose.

Before exploring how I made them, let’s have a look at the HTML and CSS:

<section class="section">
  <div class="content content-1"></div>
  <div class="content content-2"></div>
  <div class="fake-grid">
    <!-- Lots of <span>s -->
  </div>
</section>
.section {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-gap: 3px;
}

.content-1 {
  grid-column: 1 / 3;
  grid-row: 1;
}

.content-2 {
  grid-column: 5 / 7;
  grid-row: 1 / 3;
}

First, I needed a way to position the fake grid under the content. Thankfully, with CSS grid, we don’t need absolute positioning for that. By using 1 / -1 for both columns and rows, we’re telling the browser to make the fake grid take the full width and height of the parent.

.fake-grid {
  --debug-mode: 1;
  display: grid;

  /* Applying subgrid on the fake grid */
  grid-template-columns: subgrid;
  grid-template-rows: subgrid;

  /* To make the fake grid take the full width and height */
  grid-column: 1 / -1;
  grid-row: 1 / -1;

  /* optional: use a variable to toggle the grid visiblity */
  opacity: var(--debug-mode);
}

Finally, we need to add z-index: 1 for the content to make sure it will always be above the fake grid.

This is an example of how a subgrid is useful in mimicking a grid and positioning it under the content either for visual or debugging reasons. With Javascript, we can toggle the value --debug-mode to show or hide that grid!

Even better, we can do the same in CSS :has!

:root {
  --debug-mode: 1;
}

html:has(option[value="on"]:checked) {
  --debug-mode: 1;
}

You can learn more about CSS :has in this article.

Conclusion

That’s not the end. CSS subgrid will open up a lot of possibilities that weren’t possible before. I can’t wait to try it with container queries. It’s like a dream coming true. And as I’ve said before, there is no time now to learn CSS.

Thank you for reading.