Post List

@use 'sprucecss/scss/spruce' as *;

.l-post-list {
  &__inner {
    --columns: 1;
    @include clear-list;

    display: grid;
    gap: spacer('l');
    grid-template-columns: repeat(var(--columns), minmax(0, 1fr));

    @include breakpoint('sm') {
      --columns: 2;
    }

    @include breakpoint('md') {
      --columns: 3;
    }

    > li {
      margin-block: 0;
      padding-block: 0;
    }
  }
}
<div class="l-post-list">
    <div class="container">
        <ul class="l-post-list__inner">
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/8-helpful-sass-mixins-and-functions.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#sass</a>
                        </div>
                        <time datetime="2023-06-29T00:00:00.000Z">June 29, 2023</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">8 Helpful Sass Mixins and Functions</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/cracking-the-theme-switcher-and-dark-mode.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#css</a>
                            <a href="#">#ui</a>
                        </div>
                        <time datetime="2023-05-30T00:00:00.000Z">May 30, 2023</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">Cracking the Theme Switcher and Dark Mode</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/4-areas-where-modern-css-solves-a-lot.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#css</a>
                        </div>
                        <time datetime="2023-04-15T00:00:00.000Z">April 15, 2023</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">4 Areas Where Modern CSS Solves a Lot</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/internationalization-right-to-left-support-with-css-frameworks.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#sass</a>
                        </div>
                        <time datetime="2023-02-05T00:00:00.000Z">February 5, 2023</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">Internationalization (right-to-left support) with CSS Frameworks</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/how-to-03.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#how-to</a>
                        </div>
                        <time datetime="2023-01-04T00:00:00.000Z">January 4, 2023</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">How to Reduce Spruce CSS Size</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
            <li class="post-card">
                <img class="post-card__thumbnail" src="/img/blog/about-modern-sass.png" alt="" loading="lazy" width="640" height="360" />
                <div class="post-card__body">
                    <div class="post-card__meta">
                        <div class="post-card__tags">
                            <a href="#">#sass</a>
                        </div>
                        <time datetime="2022-12-03T00:00:00.000Z">December 3, 2022</time>
                    </div>
                    <h2 class="post-card__title">
                        <a class="post-card__link" href="#">About Modern Sass</a>
                    </h2>
                    <div class="post-author post-author--sm">
                        <img class="post-author__avatar" src="https://secure.gravatar.com/avatar/fd9479a898c593601efd2fe758a86dba?s=96&amp;d=mm&amp;r=g" alt="" width="32" height="32" loading="lazy">
                        <a class="post-author__name" href="https://adamlaki.com" rel="author">Adam Laki</a>
                    </div>
                </div>
            </li>
        </ul>
    </div>
</div>

Post List

A responsive grid of post cards for blogs, news and resource pages: one column on phones, two from the `sm` and three from the `md` breakpoint.

Anatomy

  • .l-post-list follows the block anatomy: .l-post-list > .container > .l-post-list__inner.
  • .l-post-list__inner is a ul, and every Post Card is an li, so screen readers announce the number of posts.

Accessibility

  • The thumbnails have an empty alt: the card title next to them already says what the post is about, and repeating it would read the title twice.
  • Each card has one link (stretched over the card), so the list doesn't create three tab stops per post.

Technical Details

  • The number of columns is the --columns custom property, changed at the breakpoints; set it on .l-post-list__inner to override.
  • The images have width, height and loading="lazy", which prevents layout shifts and saves bandwidth.
  • Pair it with the Pagination component for long lists.

Documentation

Learn about Spruce CSS through our extensive documentation.

Components

Explore our UI library of accessible components built with Spruce CSS.

Blocks and Pages

Full-width page blocks and complete page templates, ready to copy.

Find us on GitHub

Did you find a bug? Have an idea or a question? Please open an issue to help us develop the project.