CSS Grid Magic: A practical card example from my An Event Apart talk.

CSS Grid Magic: A practical card example from my An Event Apart talk.

Today I’m speaking at An Event Apart Spring Summit, an online conference featuring some of the best and brightest in the web industry, and myself. In my talk, I’m discussing modern CSS layout modules and how to incorporate them into our practices and workflows. Part of the talk centers on a practical example I built to demonstrate just how different the world of web layouts has become now that we have CSS grid, and I thought I’d share the example and some more details on it here as well. To see the full talk, head on over to An Event Apart (since it’s an online conference, you can buy tickets even after the event and get immediate access to all the content.)

A card

The example is based on a post in a web design forum I follow. There was a card design and a question: How do I make this layout using CSS?

No alt text provided for this image

The standard answer to this is to add some extra nesting <div>s and use various layout hacks like negative margins, positioning, etc.

When I see examples like this, my first questions are always the same:

What is the simplest HTML representation of this content? Can I make this design happen using pure CSS without modifying the HTML?

This is the goal of web development after all: The complete separation of content (HTML) from its presentation (CSS).

Go to Codepen to see the complete live example.

Looking at the design, there is an image, and some text. One way of representing this in HTML is using a <figure> wrapped around an <img> and a <figcaption>. Here’s what that looks like:

<figure class="card">
? <img src="…" width="640" height="640" alt=""/>
? <figcaption>
? ? <blockquote>We shape our tools (…)</blockquote>
? ? <cite>Attributed to Winston Churchill, Marshall McLuhan(…)</cite>
? ? <p><strong>Caju Gomes</strong>, <a href="…">Unsplash</a></p>
        
? </figcaption>
</figure>
        

That solves the content part. Now for the presentation.

Layered layouts

The real challenge in this design is the many layers. There’s a faux shadow, then the card itself which serves as a background image. Then there is the image, the text which overlaps the image, and the image credit.?

No alt text provided for this image

Stacking elements one on top of the other using CSS is traditionally achieved through clever hacks using either positioning, negative margins, or both. However, CSS grid allows us to place any child element of the grid anywhere on the grid, including in the same cell or cells as other elements. So if we need to stack elements on top of one another like in this design, CSS grid lets us do that in a clean and controlled way.

The first step is to figure out what the grid should look like:

No alt text provided for this image

Next, mark up that grid in CSS. The <figure> becomes the grid parent:

figure {
? display: grid;
? grid-template-columns: 3em 9em 1fr 1fr 6em 3em;
        
? grid-template-rows: 3em 9em 1fr 6em 3em;
}
        

With the grid defined, place items on that grid. There are many ways of doing this, the easiest of which is to just position the times based on the grid line numbers. First the image:

img {
? grid-column: 4/5;
        
? grid-row: 3/4;
}
        

Then the text which sits inside the figcaption:

figcaption {
? grid-column: 3/5;
        
? grid-row: 3/4;
}
        

This puts the text in the correct general area of the grid, and on top of the image, but the design calls for more control over the exact placement of the text.

No alt text provided for this image

To achieve this, add a second grid for the <figcaption> element and position the items within on that grid:

No alt text provided for this image
figcaption {
? grid-column: 3/5;
? grid-row: 3/4;
? display: grid;
        
? grid-template-columns:?3fr 1fr 2fr;
}
        

That gives us the image and the text, but the design also calls for a background image and a faux shadow. What to do...

Pseudo elements as grid elements.

An interesting of both grid and flex is pseudo elements become first-level children of these containers. That means if you create a grid container around a single item and then define ::before and ::after pseudo elements for that item, the grid now has three grid items: the element itself and its before and after pseudo-elements, and each will be placed in its own grid cell. This opens up an interesting new possibilities, one of which can be used to solve the current layout problem.

The design calls for both a background image and a faux shadow.

No alt text provided for this image

Using pseudo elements both of these can be added in a non-destructive way that will gracefully degrade to older browsers without grid support.

The background image first. For this I’ll use ::before because it should appear before the actual card content in the DOM order. Place the new (pseudo) grid item on the existing grid, and then fill it with a background image:

figure::before {
? grid-column: 2/7;
? grid-row: 2/6;
? content: "";
? display: block;
? background: white;
? background-image: url(…);
        
? background-size: cover;
}
        

Next, the faux shadow. I’ll have to use ::after for this, which technically places the shadow after the card in the DOM order and therefore ends up on top of the card.

figure::after {
? grid-column: 1/6;
? grid-row: 1/5;?
? content: "";
? display: block;
        
? background: #e0dde4;
}
        

That’s easily solved by moving the item along the z-axis using z-index:

figure::after {
? grid-column: 1/6;
? grid-row: 1/5;
? z-index: -1; ?
? content: "";
? display: block;
        
? background: #e0dde4;
}
        

This last part is another important feature of CSS grid. Because grid allows us to stack things on top of each other, we are effectively working in the 3rd dimension; literally layering content on top of content like a stack of cards. This layering is done based on DOM order, so the last item ends up on top of the stack. We can use the z-index property to change this order to whatever we want. In other words, with Grid we are now for the first time able to lay out content along three axes: horizontal, vertical, and depth.

Backwards compatibility

At this point there’s a good chance you’re thinking something along the lines of “Sure, this is cool, but grid doesn’t work in older browsers, so you need to provide fallback options.”

Surprisingly, the answer is no.

This setup doesn’t require any accommodations for older browsers.

You can test it for yourself. Open the example in your favorite browser, go to the developer tools, and disable the two instances of display:grid.

No alt text provided for this image

What you get is the main image followed by the text. The faux shadow and background image disappear as if by magic, and the visitor gets only the content they are looking for, styled in a way that makes sense in their environment.

The “magic” at play here is basic progressive enhancement: Take advantage of whatever capabilities the current browser has without reducing the experience for those without those capabilities.?

Of course we could use @supports to detect grid support and build out custom styles for browsers without grid support. If I published this on a real website, I would wrap the ::before and ::after rules using @supports to prevent older browsers from downloading the background image. But, as you see this is not necessary unless you want to add specific fallback styles.

The standard argument against this approach is that the result of doing nothing will be different users having different experiences. From my perspective, that's an argument with little substance: We have used responsive web design since 2010, so for the past 10+ years we've been shipping websites that look different on different screens. This is no different, except the responsive axes have been expanded to include not only viewport width and height but also browser capability.

Text reading "Websites should look and function the same in all browsers."? corrected to "Websites should provide the same  information exchange?and functional experience for all people."?

At the very onset of this project I defined semantic HTML, and I said I didn’t want to make any changes to the HTML to accommodate the style. Thus every browser will get semantic parsable content that makes sense. Then I use CSS to progressively enhance the experience when grid is available in the visiting browser.

So what happens to that faux shadow and background image? Inspect your code and you’ll see when grid is disabled, they each collapse to a height of 0px. Normally when we add pseudo elements using ::before and ::after we set their width and height which would result in them showing up when grid is not present, but since I’m using grid, that’s not necessary: Given no instructions, grid’s default treatment of grid items is to stretch them to fit the cell they are presented in. As a result, the faux shadow and background image automatically stretch to fill the grid cells, and collapse to a height of 0 when no grid is present.

CSS layouts are now a platform feature

For as long as I can remember, CSS layouts were always a collection of carefully crafted hacks. That time is now over. Between grid, flex, float, multicol, and table, we have all the layout features we need built into the platform to make the layouts we want without having to modify our markup or employ clever hacks. Now it's our job to realign our way of thinking about layouts to use these modules in our daily practice. I built this example to give you a brief glimpse of what is possible and how these new modules open doors we didn't even know existed before. I invite you to join me as we explore this new future of CSS layouts together.

For more examples, and talks from many of the leading voices of our industry, head on over to An Event Apart and sign up for the 2021 Spring Summit!

--

Morten Rand-Hendriksen is a Senior Staff Instructor at?LinkedIn Learning?(formerly Lynda.com) focusing on?front-end web development and the next generation of the web platform. He spends a lot of his time figuring out how to make complicated things easier using new technology.

The talk in Paris 2017 at WordCamp was amazing! :)

Promise Das

Student at University of Chittagong

3 年

Useful article. ??

回复
Jacob E Siegel

Reporter @ Washington Ledger | Aspiring Full Stack Developer (React) | WordPress

3 年

I thought css grid has been around for a while?

回复
Lolita Druzinina ??

Anv?ndarupplevelse och Produktdesigner | Kravanalytiker | Drivs av en passion f?r att skapa inkluderande och tillg?ngliga designl?sningar

3 年

Thank You! Useful! ??

回复
Caspar Hübinger

Corporate antimatter · Change Management at journaway

3 年

I’m terribly behind on CSS because it isn’t part of my day job anymore, so thanks for this fascinating example! Progressive enhancement still is chronically undervalued imho. Explanations like this one hopefully will help to get the point across to a wider audience.

要查看或添加评论,请登录

Morten Rand-Hendriksen的更多文章

  • After WordPress

    After WordPress

    Today, the head of the WordPress Open Source Project Matt Mullenweg unilaterally locked the gates to wordpress.org, the…

    60 条评论
  • As the Mask Drops, It's Time to Face the Politics of Tech

    As the Mask Drops, It's Time to Face the Politics of Tech

    "Is it really?" She gestured at my hoodie and the bold text across my chest reading "Code is Political." "Profoundly…

    22 条评论
  • Rubicon

    Rubicon

    On Saturday October 12, 2024, a line was crossed in the WordPress open source project that I fear will have a lasting…

    24 条评论
  • As We Break Surface – The AI Transmutation of Web Dev

    As We Break Surface – The AI Transmutation of Web Dev

    "Hey AI, build me a website." It's a matter of time - probably months, before we get here.

    10 条评论
  • It’s time to abandon reckless oil propagandists

    It’s time to abandon reckless oil propagandists

    A response to Dan McTeague’s Financial Post opinion piece “It’s time to abandon reckless EV mandates” published July…

    13 条评论
  • AI Training and the Slow Poison of Opt-Out

    AI Training and the Slow Poison of Opt-Out

    Asking users to opt-out of AI training is a deceptive pattern. Governments and regulators must step in to enforce…

    7 条评论
  • GPT-4o, OpenAI, and Our Multimodal Future

    GPT-4o, OpenAI, and Our Multimodal Future

    OpenAI held up a big shining arrow pointing towards our possible future with AI and asked us to follow them. Beyond the…

    12 条评论
  • Ten Questions for Matt Mullenweg Re: Data Ownership and AI

    Ten Questions for Matt Mullenweg Re: Data Ownership and AI

    Dear Matt. 404 Media tells me you're in the process of selling access to the data I've published on WordPress.

    11 条评论
  • AI Coding Assistants Made Me Go Back to School

    AI Coding Assistants Made Me Go Back to School

    The introduction of graphing calculators didn't remove the need to understand math; they removed the need to do rote…

    13 条评论
  • The Challenge, and Opportunity, of OpenAI's GPT Store

    The Challenge, and Opportunity, of OpenAI's GPT Store

    If you make a useful GPT in the GPT Store, someone else will publish a more popular copy and make yours look like a…

    8 条评论

社区洞察

其他会员也浏览了