Circular navigation for previous and next articles

A major goal of design and development is to create “sticky” pages that maximize the average user’s time on the site. Engaging users with compelling content increases brand loyalty, and raises the likelihood that they will further engage with the site and its advertisers.

There are many ways to create sticky content and services, but perhaps the most dependable is to offer links to related pages on the site. In the case of this site, that’s done in three places: the random feature bar at the top, relevant words linked in the body text, and a “previous - next” navigation at the bottom, directing the reader to logical destinations after completing the article. On this site, that previous-next arrangement is displayed using flexbox.


Not every article on this site has logical previous and next relationships: for example, the first article in a will have a “next” but no previous, and the last will have a “previous” but no next. The navigation module must be adaptive to each of these possibilities, maintaining a spatial relationship with the user: “next” will always be to the right, and “previous” should always appear on the left.

I’ll start with the simplest case of both a previous and a next article. Each link contains two <span> elements: one <span> surrounding the thumbnail image associated with the article, the other surrounding the title of the piece. Note that these elements appear in reversed order for the “next” link.

<div id="prevnext" class="flex apart">  
    <a class="prev-one flex" href="/.." rel="prev" accesskey=",">
        <span class="thumb">
            <img src="card-shuffle.jpg" alt" srcset="card-shuffle-2x.jpg 2x">
        <span class="articlename">
            Shuffling and Sorting JavaScript Arrays
    <a class="next-one flex" href="/.." rel="next" accesskey=".">
        <span class="articlename">
            JavaScript Fundamentals: Object Literals and Nested Arrays
        <span class="thumb">
            <img src="jet-nest.jpg" alt srcset="jet-nest-2x.jpg 2x">

The markup uses many techniques I’ve discussed in previous articles:


The navigation module is cleared to ensure that nothing “creeps” around it:

#prevnext {
    margin-top: 1rem;
    clear: both;

Since I use extensively throughout the site, I’ve created two generic “helper” classes to set elements into display: flex and push their content apart. (Note that vendor-prefixed code would need to be added to achieve backwards compatibility with older browsers).

.flex {
    display: flex;
.apart {
    justify-content: space-between;

The links also take the flex class, meaning that they’re also set to display: flexbox. This is further modified to ensure that links take up the same amount of horizontal space as each other, and are aligned on their centers:

#prevnext a {
    font-size: smaller;
    align-items: center;
a.prev-one {
    flex: 1;
} {
    flex: 1;
    justify-content: flex-end;

justify-content: flex-end means that the “next” link will always appear at the horizontal end of the available space.

Links take a general style that they also share with body text:

a {
    text-decoration: none;
    color: rgba(0,0,0,0.8);
    border-bottom: 1px solid #edd;

The <span> elements are sized, and the images within them turned into circles using border-radius:

#prevnext a span.thumb img {
    border-radius: 50%;
    overflow: hidden;
    width: 125px;
    min-width: 125px;
    height: 100%;
    border: 1px solid #ccc;

Article names are separated from the thumbnails using margin on the appropriate side. Text on the right will be flush left by default, so we change that to its opposite:

a.prev-one span.articlename {
    margin-left: 1rem;
} span.articlename {
    margin-right: 1rem;
    text-align: right;

The arrows either side of the text links are generated with pseudo-element selectors:

a.prev-one span.articlename:before {
    content: "\2190 ";
} span.articlename:after {
    content: " \2192";

If there’s no “next” link, the “previous” link will appear by itself, with the text running to the right. If the “previous” link is absent, the “next” link will appear on the right.

There’s just one small remaining problem. If the text for either link wraps across two or more lines, the text on the other side is out of vertical alignment with it. Flexbox can’t solve this: it’s great at aligning elements on their centers, but it can’t “look ahead” and determine that because text in one element is across two lines, it should move up the next in a previous element. That can, however, be addressed with , which I’ll look at next.

Enjoy this piece? I invite you to follow me at to learn more.
Check out the CodePen demo for this article at