Skip to content

component :: Pagination

Two navigation patterns for content sites: .pagination is the numbered kind for blog indexes, .prevNext the pair of cards at the bottom of a post. Both are pure HTML and CSS.

File Description Source
component.pagination.css Numbered pagination styles Github
component.prevNext.css Prev/next styles Github
Pagination.astro, PrevNext.astro The Astro components Github
icons/chevron-down.svg Arrow icon (rotated in CSS) Github
--pagination-*, --prevNext-* token blocks Interface tokens (see table below) Github

Playground

The numbered pagination’s markup is generated by windowing logic (see HTML), so the playground covers the .prevNext pattern: toggle either link off and the layout holds its columns.

Parts

Copied!
<nav class="prevNext" aria-label="Previous and next"><a class="prevNext_link prevNext_link-prev" href="#"><small>Previous</small><span>Designing with cascade layers</span></a><a class="prevNext_link prevNext_link-next" href="#"><small>Next</small><span>Tokens all the way down</span></a>
</nav>

HTML

The numbers are windowed around the current page, so long lists stay short.

<nav class="pagination" aria-label="Pagination">
<ul>
<li><a class="pagination_arrow pagination_arrow-prev" href="/blog/4" aria-label="Previous page"><svg>[…]</svg></a></li>
<li><a href="/blog" aria-label="Page 1">1</a></li>
<li><span class="pagination_ellipsis" aria-hidden="true">…</span></li>
<li><a href="/blog/4" aria-label="Page 4">4</a></li>
<li><a href="/blog/5" aria-current="page" aria-label="Page 5">5</a></li>
<li><a href="/blog/6" aria-label="Page 6">6</a></li>
<li><span class="pagination_ellipsis" aria-hidden="true">…</span></li>
<li><a href="/blog/12" aria-label="Page 12">12</a></li>
<li><a class="pagination_arrow pagination_arrow-next" href="/blog/6" aria-label="Next page"><svg>[…]</svg></a></li>
</ul>
</nav>

At the ends, the arrows stay in place but become disabled <span aria-disabled="true"> elements instead of links, so the layout never jumps. Every target is at least --pagination-size (36px) square.

<nav class="prevNext" aria-label="Previous and next">
<a class="prevNext_link prevNext_link-prev" href="/blog/layers">
<small>Previous</small>
<span>Designing with cascade layers</span>
</a>
<a class="prevNext_link prevNext_link-next" href="/blog/tokens">
<small>Next</small>
<span>Tokens all the way down</span>
</a>
</nav>

A lone next link keeps its right-hand column.

Custom properties

Property Description
--pagination-size Minimum width/height of a target.
--pagination-border-radius Target border radius.
--pagination-color Number/arrow color.
--pagination-color-current Current page text color.
--pagination-background-color-current Current page background.
--pagination-background-color-hover Hover background.
--prevNext-border-color Card border.
--prevNext-border-color-hover Card border on hover.
--prevNext-label-color “Previous”/“Next” label color.

Astro component

Pagination

Prop Type Default Description
currentPage number The page being rendered. Required.
lastPage number Total number of pages. Required.
baseUrl string Index URL; page 1 is baseUrl, page n is baseUrl/n.
pageUrl (page: number) => string see baseUrl Override the URL scheme entirely.
windowSize number 1 Pages shown on each side of the current one.
ariaLabel string "Pagination" The nav’s accessible name.

With Astro’s paginate(), pass page.currentPage, page.lastPage, and your index route as baseUrl.

PrevNext

Prop Type Default Description
prev { title, href } undefined Previous post link.
next { title, href } undefined Next post link.
prevLabel string "Previous" Small label above the prev title.
nextLabel string "Next" Small label above the next title.
ariaLabel string "Previous and next" The nav’s accessible name.

Renders nothing when both links are missing.

Examples