A Button That Links to a Random Post in HTML & CSS Only
A Button That Links to a Random Post in HTML & CSS Only êŽë š
I was reading a post by Jim Nielsen where he was Making a Shuffle Button. It was for a static site, so there was no server-side code to hit to redirect to a random post. PHP, for instance, could query for all posts and select one pseudo-randomly, and redirect there. But no such language on a static site.
Take One
Instead, Jim did this (at first):
<!-- In the site navigation -->
<button id="js-shuffle">Shuffle</button>
<!-- Way down at the end of the HTML -->
<script>
// All 974 note IDs injected by my SSG
const noteIds = ['id-1', 'id-2', id-3', 'id-4', '...'];
document.querySelector("#js-shuffle")
.addEventListener('click', () => {
// randomly grab an item in `noteIds`
const randomId = '...';
window.location.href = `/n/${randomId}/`
})
</script>
The issue with this approach is that Jim inlined it on every single HTML page and thus every page had to be re-built during deployment if a new post was published. I do feel like saying JIM THIS COULD HAVE BEEN A WEB COMPONENT and built as a single file and imported, but Iâll refrain.
Then Jim went through 3-4 other techniques that also worked, each with its ups and downs. I like the technique Jim landed on, which was making a single page that handled the job and redirected away. Basically like the solution above, just at a shuffle.html page and ran automatically.
Iâm afraid I donât have an improvement for Jim, per se, but it made me think of another potential solution.
What if it depended on where you clicked the random button?
I mean, weâre talking about a physical button here, right? So Iâm talking literally what pixel you clicked on on the button would determine which random post you go to.

We could get these coordinates in JavaScript, but I donât think we need to. We can just fill the area with <a> links that go to the posts. So itâs not a single button, itâs just a button-like shape full of tiny buttons (links, actually).
To this, we could do like:
<div class="random-button">
<a href="/post/1">Post 1</a>
<a href="/post/2">Post 2</a>
<a href="/post/3">Post 3</a>
...
<span>Random Post</span>
</div>
Then we just let the links lay out naturally within the button space:
.random-button {
display: flex;
flex-wrap: wrap;
align-content: stretch;
position: relative;
overflow: hidden;
/* make it look like a button */
inline-size: 300px;
border-radius: 14px;
> a {
/* whatever sizing works */
flex: 1 1 30px;
}
> span {
pointer-events: none;
position: absolute;
inset: 0;
display: grid;
place-items: center;
}
}
This flexbox setup, with the stretchy alignment and flex-grow allowance, should fill the space nicely.
See how the last row always fills the space there no matter how many links there are? A âbuttonâ should probably respond no matter where it is clicked, and now we can do that.
If you want this implementation to be a secret, you could set opacity: 0; on the links, and the behavior will be the same and the whole thing will just look like a single button.
Gettinâ More Random
With one line, we can make this all a bit more random. Iâd say itâs still pretty random without this, as where you click exactly will essentially be random. But this is better.
And check it out, itâs a one linerâŠ
.random-button {
...
reading-flow: flex-visual;
> a {
order: random(1, 9999);
}
}
Flexbox supports the order property. Sometimes itâs a finger-waggle thing because youâre messing with the visual tabbing order when you use it, which can be an accessibility issue. ButâŠ
- These are kinda hidden secret links so maybe it doesnât matter?
- We can fix it with
[<VPIcon icon="fa-brands fa-firefox"/>reading-flow](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/reading-flow): flex-visual; on the button anyway.
Now, with CSS alone, the link placement is random. That random() function works in Safari and Chrome-with-flag, so I did up some colors with it too to make it clearer.
Thatâs client-side randomization. Every page load will be different.
Demo
The demo has some bonus stuff like setting the font-size with container units so things kinda fit nicely in the space. Maybe youâd do some fancy build-time math to size things based on how many links there are. Iâd think this would scale up into the thousands if youâre down to like 1px Ă 1px links.
Iâd tell Jim to give it a shot, but I think the route he landed on, where a single link does the randomization, is probably a little more useful in his case.