Generating pagination links is not as straightforward as it may seem. So, while rebuilding my own site with Astro, I released a <Pagination />
component on npm as @philnash/astro-pagination that anyone can use in their Astro site. Read on to find out more.
Pagination
Pagination is something that most content sites need. It is often better to list collections with lots of entries, like blog posts, across multiple pages because a single page would be overwhelming to scroll through.
Astro provides the paginate
function to the callback to getStaticPaths
to make it easy to turn a collection into a number of paths and pages. Once you have turned your collection into a list of pages, you then need to render links that your users can use to navigate through the list.
While this may at first seem straightforward, as with many things on the web, there are hidden depths to it. Not only do you need to write the code that parses the current page and produces links to the previous page, the next page and a window of pages around the current one, you also need to produce accessible HTML that will be easy to use for any of your site’s visitors.
An Astro Pagination component
To make this easy for anyone building with Astro, I released @philnash/astro-pagination on npm. It is a <Pagination />
component that you can use in your Astro site to create pagination links based on a Page
object.
How to use it
Start by installing the package:
npm install @philnash/astro-pagination
Then in a list page, you can import and use the Pagination
component. The component requires two properties, a page
and a urlPattern
. The page
should be an Astro Page
object, typically provided through Astro.props
. The urlPattern
should be the path you are using for your paginated pages, with a {}
where the page number should go. A simplified Astro page might look something like this:
---
import Pagination from "@philnash/astro-pagination";
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
{ /* render the items from the page */ }
<Pagination page={page} urlPattern="/blog/page/{}" />
This will render HTML that looks like:
<nav role="navigation" aria-label="Pagination">
<ul>
<li>
<a
href="/blog/page/4"
class="previous-page"
aria-label="Go to previous page"
>« Prev</a
>
</li>
<li>
<a class="number" href="/blog/page" aria-label="Go to page 1"> 1 </a>
</li>
<li>
<span class="start-ellipsis">…</span>
</li>
<li>
<a class="number" href="/blog/page/3" aria-label="Go to page 3"> 3 </a>
</li>
<li>
<a class="number" href="/blog/page/4" aria-label="Go to page 4"> 4 </a>
</li>
<li>
<em aria-current="page" aria-label="Current page, page 5"> 5 </em>
</li>
<li>
<a class="number" href="/blog/page/6" aria-label="Go to page 6"> 6 </a>
</li>
<li>
<a class="number" href="/blog/page/7" aria-label="Go to page 7"> 7 </a>
</li>
<li>
<span class="end-ellipsis">…</span>
</li>
<li>
<a class="number" href="/blog/page/10" aria-label="Go to page 10"> 10 </a>
</li>
<li>
<a href="/blog/page/6" class="next-page" aria-label="Go to next page"
>Next »</a
>
</li>
</ul>
</nav>
This renders like this:
Well, it renders like that with my site’s CSS applied. You will need to style it yourself.
The generated markup includes a bunch of things, including accessibility features based on research from a11ymatters on accessible pagination. There is:
- a link to the previous page
- a link to the first page
- a window of links around the current page
- ellipses to show where pages exist between the first/last page and the current window
- a link to the last page
- a link to the next page
- a
<nav>
element around the links, with arole
attribute set to “navigation” and anaria-label
attribute to describe it as “Pagination” - a list of links, allowing assistive technology to announce how many items there are in the list and navigate through them
- an
aria-label
attribute on each link to provide a full description of the link’s destination - an
aria-current
attribute on the element representing the current page - a helpful class name on each of the important elements to allow for styling
Advanced usage
There are more properties you can pass to the <Pagination />
component that give you greater control over the output. They include properties like previousLabel
and nextLabel
, that lets you set the text for the previous and next links, or windowSize
, that lets you determine how many pages are shown in the middle of the range. You can see all the the available options in the documentation.
Future improvements
While the <Pagination />
component is ready to be used, and is already in use on my own site, there are definitely some improvements that I will be adding. For example, you should be able to:
- use a component for the
previousLabel
andnextLabel
- style the links like other Astro components
- add class names to the elements, so you can style using utility CSS frameworks
- handle internationalisation
Ultimately, I’d love for this to be a component that every Astro site considers using for pagination, from my blog right here to the Astro blog itself.
Any feedack?
I tried to make this component simple to use and flexible. As I’ve described above, there’s plenty more to do, but it’s always worth asking for feedback too.
So, would you use this component to simplify pagination in your own Astro sites? Is there anything you’d add or change? Let me know on Twitter, another social network of choice, or in the GitHub issues.
Astro Pagination
Check out the source on GitHub (give it a star, if you fancy) and let me know if you use this component.