Post Navigation

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

.post-navigation {
  display: grid;
  gap: spacer('s') spacer('m');

  @include breakpoint('sm') {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

.post-navigation-item {
  $this: &;
  @include transition($property: 'border-color, background-color');
  align-items: center;
  border: config('border-width-base', $display) solid color('border');
  border-radius: radius('lg');
  display: flex;
  gap: spacer('s');
  padding: spacer('s');
  text-decoration: none;

  &:hover {
    border-color: color('primary');

    #{$this}__icon {
      background-color: color('primary');
      color: color('primary-foreground', 'btn');
    }
  }

  &:focus-visible {
    outline: 2px solid color('focus-ring');
    outline-offset: 2px;
  }

  &--next {
    grid-column: -2;
    justify-content: end;
    text-align: end;
  }

  &__icon {
    @include transition($property: 'background-color, color');
    align-items: center;
    background-color: color-alpha('primary', 0.1);
    block-size: 2.75rem;
    border-radius: radius('md');
    color: color('primary');
    display: flex;
    flex-shrink: 0;
    inline-size: 2.75rem;
    justify-content: center;

    svg {
      block-size: 1rem;
      inline-size: 1rem;
    }
  }

  &__caption {
    display: flex;
    flex-direction: column;
    gap: spacer('xxs');
    line-height: config('line-height-md', $typography);
    min-inline-size: 0;
  }

  &__label {
    color: color('muted');
    font-size: config('font-size-sm', $typography);
  }

  &__title {
    color: color('heading');
    font-weight: 700;
  }
}

// The arrows point toward the reading direction.
[dir='rtl'] .post-navigation-item__icon svg {
  scale: -1 1;
}
<nav class="post-navigation" aria-label="More posts">
    <a class="post-navigation-item post-navigation-item--prev" href="#" rel="prev">
        <span class="post-navigation-item__icon">
            <svg aria-hidden="true" fill="none" focusable="false" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
        </span>
        <span class="post-navigation-item__caption">
            <span class="post-navigation-item__label">Previous post</span>
            <span class="post-navigation-item__title">5 Laravel e-commerce packages</span>
        </span>
    </a>
    <a class="post-navigation-item post-navigation-item--next" href="#" rel="next">
        <span class="post-navigation-item__caption">
            <span class="post-navigation-item__label">Next post</span>
            <span class="post-navigation-item__title">What is the accessibility tree?</span>
        </span>
        <span class="post-navigation-item__icon">
            <svg aria-hidden="true" fill="none" focusable="false" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
        </span>
    </a>
</nav>

Post Navigation

Previous and next links at the end of an article, with the titles of the neighboring posts, so readers can keep going.

Anatomy

  • .post-navigation is a nav with its own label ("More posts"), so it's distinguishable from the main navigation.
  • .post-navigation-item is a link card with --prev or --next; each has an arrow (__icon), a small label (__label) and the title (__title).

Accessibility

  • The visible label ("Previous post") and the title together make the link name, so screen reader users hear where it goes, not just "Previous".
  • The arrows are decorative (aria-hidden="true") and flip in RTL.
  • rel="prev" and rel="next" describe the relation for browsers and tools.

Technical Details

  • A two-column grid from the sm breakpoint; when there's only a next post, it stays in the end column (grid-column: -2).
  • The whole card is the link, which gives a large target; the hover and focus states use the primary color.
  • The colors come from the tokens, so it no longer needs the site's navigation color group.

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.