</>Jonathan Harrell

Main Menu

Site Tools

Contextual Callouts with CSS Grid

At long last, contextual callouts are possible with CSS grid. Contextual callouts are small paragraphs that sit beside primary text and offer secondary information to a reader. They have long been a feature of books, magazines and other printed materials. I particularly enjoy coming across these small asides when reading, as they add texture and interest to the content.

I have been searching for a while now for a way to bring this to the web with pure CSS. The solutions in the past have typically been fairly messy, requiring annoying floating and clearing, or manual absolute positioning. That is changing now, thanks to CSS grid.

I haven’t found a complete solution to these callouts, but the example here will hopefully work in several situations.

CSS grid can be used to create a blog post layout that accommodates contextual callouts containing secondary information. At earum odio provident quod voluptatibus Amet assumenda atque beatae Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid aspernatur dolore est eveniet facilis fugiat incidunt magni molestias nisi, nulla repellat tempore voluptates. At earum odio provident quod velit voluptatibus! Amet assumenda atque beatae consequatur deserunt eveniet exercitationem labore maiores minus natus neque, officia possimus quasi quia quibusdam quisquam sapiente ut. Amet animi corporis cupiditate eaque iure quis, tempora veniam? Consectetur, doloremque eum exercitationem perferendis ratione rerum vero. Amet assumenda atque beatae consequatur deserunt eveniet exercitationem labore maiores minus natus neque, officia possimus quasi quia quibusdam quisquam sapiente ut. Amet animi corporis cupiditate eaque iure quis. Consectetur, doloremque eum exercitationem perferendis ratione rerum vero voluptatum. Accusamus ad beatae consectetur, ea esse eum eveniet facere hic id illo itaque labore magni molestias nemo numquam sed suscipit unde. A aperiam aut beatae commodi consectetur corporis cum debitis eligendi enim error excepturi harum illo in ipsum modi numquam omnis, praesentium quae quos ratione similique totam, vel vitae voluptatibus voluptatum! Adipisci autem consequuntur cupiditate dicta dolore dolorem doloribus dolorum eum, id ipsum labore libero minus nemo provident quasi quidem recusandae repellat sequi, tempore ut? Eveniet ipsum necessitatibus praesentium quod voluptas! A aperiam aut beatae commodi consectetur corporis cum debitis. AUGUST 12, 2017

The Grid Markup

Link to this section

Say I’m building a blog post template. I’ll need a header to contain the title and date, and a section for share links. Then I’ll need the primary blog content, consisting of headings, paragraphs, images, and, yes, callouts. First let’s write some semantic markup:

<article class="blog-post">
  <header class="blog-post-header">
    <h1 class="blog-post-title">...</h1>
    <time datetime="..." class="blog-post-date">...</time>
  </header>
  <aside class="blog-post-share">...</aside>
  <p>...</p>
  <h2>...</h2>
  <p>...</p>
  <aside>
    <p>...</p>
  </aside>
  <p>...</p>
  <p>...</p>
  <aside>
    <p>...</p>
  </aside>
  <figure>
    <img src="..." alt="...">
    <figcaption>...</figcaption>
  </figure>
</article>

The article element contains the header, share links aside, and all post content as direct children. This will be important as we apply CSS grid styles to the post. Callouts are written as aside elements, perfect for content that is connected tangentially to the rest of the document, and appear in the document directly after the paragraph they are connected to.

Fallback Styling (if no CSS Grid support)

Link to this section

First, we’ll apply some basic styles for browsers that don’t yet support CSS grid. We’ll add some margin, padding and set a max-width of 70 characters using the ch unit:

.blog-post {
  max-width: 70ch;
  margin: 3rem auto;
  padding: 1.5rem;
}

The Fun Part: Using CSS Grid!

Link to this section
CSS grid can be used to create a blog post layout that accomodates contextual callouts containing secondary information. At earum odio provident quod voluptatibus Amet assumenda atque beatae Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquid aspernatur dolore est eveniet facilis fugiat incidunt magni molestias nisi, nulla repellat tempore voluptates. At earum odio provident quod velit voluptatibus! Amet assumenda atque beatae consequatur deserunt eveniet exercitationem labore maiores minus natus neque, officia possimus quasi quia quibusdam quisquam sapiente ut. Amet animi corporis cupiditate eaque iure quis, tempora veniam? Consectetur, doloremque eum exercitationem perferendis ratione rerum vero. Amet assumenda atque beatae consequatur deserunt eveniet exercitationem labore maiores minus natus neque, officia possimus quasi quia quibusdam quisquam sapiente ut. Amet animi corporis cupiditate eaque iure quis. Consectetur, doloremque eum exercitationem perferendis ratione rerum vero voluptatum. Accusamus ad beatae consectetur, ea esse eum eveniet facere hic id illo itaque labore magni molestias nemo numquam sed suscipit unde. A aperiam aut beatae commodi consectetur corporis cum debitis eligendi enim error excepturi harum illo in ipsum modi numquam omnis, praesentium quae quos ratione similique totam, vel vitae voluptatibus voluptatum! Adipisci autem consequuntur cupiditate dicta dolore dolorem doloribus dolorum eum, id ipsum labore libero minus nemo provident quasi quidem recusandae repellat sequi, tempore ut? Eveniet ipsum necessitatibus praesentium quod voluptas! A aperiam aut beatae commodi consectetur corporis cum debitis. AUGUST 12, 2017

Now, progressively enhance for browsers that do support CSS grid using an @supports query:

@supports(display: grid) {
  .blog-post {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-column-gap: 2rem;
  }
}

Here I’m setting up the .blog-post article as a 12-column grid, each with a width of 1 fraction unit and a gap between each column of 2rem. Now it’s time to start placing content on the grid:

.blog-post-header {
  grid-column-start: 2;
  grid-column-end: span 3;
}

.blog-post p,
.blog-post h2 {
  grid-column-start: 5;
  grid-column-end: span 6;
}

.blog-post-share {
  grid-column-start: span 1;
  grid-column-end: -2;
}

Now, the post header, post paragraphs and headings, and share links all sit next to each other in a row. Pretty cool. The callouts are up next:

.blog-post aside {
  grid-column-start: 3;
  grid-column-end: 5;
}

The asides are now pulled to the left of the paragraph immediately preceding them, looking exactly like callouts. If you wanted more control over the positioning of these callouts (say you wanted one at the bottom of the row, rather than at the top), you could apply some targeted styling with the align-self property, but for this exercise, I’m assuming a more generic approach for content generated from a CMS.

And that’s pretty much all it takes to set up contextual callouts with CSS grid. No sweat.

Bonus: Full-Width Figures

Link to this section

Here’s my styling for figures within a post, causing them to stretch the full width of the grid container. The rest of the content is still fit to a narrower width.

.blog-post figure {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-column-gap: 2rem;
  grid-column-start: 1;
  grid-column-end: -1;
}

.blog-post figure img {
  grid-column-start: 1;
  grid-column-end: -1;
}

.blog-post figure figcaption {
  grid-column-start: 5;
  grid-column-end: span 6;
}

I set the figure up to span across all 12 columns of its parent grid. I set up a nested grid within the figure with the same number of columns and spacing as the parent. This allows me to have the img element to span the full width, while the figcaption is aligned with the rest of the primary text in the blog post.

There is one primary caveat to the approach outlined here. Because row height is determined by the content within the row, it is possible that a caption that is longer than the paragraph to the right of it could elongate that row and create some odd blank space to the right.

Essentially, it is required that all callouts be of equal length or shorter than their preceding paragraphs.

That wraps up this one. I’d love to see what other people do with callouts!

Go to experiment

Contextual Callouts with CSS Grid

Click here to view the experiment on Codepen

More Articles

Go to article

System-Based Theming with Styled Components

Learn how to support system-based theming in Styled Components, while allowing a user to select their preferred theme and persist that choice.

Go to article

Implicit State Sharing in React & Vue

Learn to use React’s Context API and provide/inject in Vue to share state between related components without resorting to a global data store.

Go to article

Component Reusability in React & Vue

Learn how to use render props in React and scoped slots in Vue to create components that are flexible and reusable.

Go to article

What’s the Deal with Margin Collapse?

Learn about margin collapse, a fundamental concept of CSS layout. See visual examples of when margin collapse happens, and when it doesn’t.