The Making of “You Might Not Need JavaScript”

10 September 2015

Last week, I had the pleasure of presenting at the JavaScript Austin meetup. For this month’s meetup, I gave my “stateful CSS” talk (titled “Form with Function” or “You Might Not Need JavaScript“, depending on how trolling I feel at the time). If you haven’t seen it yet, there’s a video of it on Vimeo:

There’s a bit of a plot twist at the end of the talk that I get a lot of questions about (watch the video above first if you don’t want spoilers). In this post, we’ll look at how this plot twist was created.

Spoiler Alert

If you’re reading this, I assume you’ve either watched the above video, or you don’t care about spoilers (you monster). Okay, here’s the big plot twist:

My entire presentation—the slides, the inline CSS editing, everything—was built without a single line of JavaScript.

Let’s take a look at how to pull that off.

Thinking without JavaScript

A slide deck doesn’t have many “features” beyond showing one slide at a time (and having some way to switch between those). As it happens, we have access to an HTML element that also shows one thing at a time: a radio button.

<input name="slide" type="radio" checked>
<label ><!-- Slide 1 --></label>
<input name="slide" type="radio">
<label ><!-- Slide 2 --></label>
<input name="slide" type="radio">
<label ><!-- Slide 3 --></label>

Now, if we could somehow link the “checked” state of a radio button to the visibility of another element, we’d have the beginnings of a slide deck right there. Select the radio buttons in the following pen to see what happens:

See the Pen LppWpY by Tim G. Thomas (@TimGThomas) on CodePen.

So far, we’ve got a passable—albeit boring—slide deck, and all it took was some very basic HTML and a little clever CSS. Turns out styling elements is pretty straightforward thanks to the :checked pseudo-class and the + (adjacent) selector:

/* Hide all slides by default. */
.slide {
display: none;
/* But show the currently-selected one. */
input[name='slide']:checked + .slide {
display: block;


You’re more than welcome to stop here, as what we’ve covered so far is technically all you need to make your own JavaScript-less styles, but there’s more we can do.

Seeing all of those radio buttons sucks, so let’s get rid of them:

input[name='slide'] {
display: none;

That’s better, but now we have no way of moving through the slides. Fortunately, this is already (partially) solved for us: browsers will let you switch between radio button values with your keyboard. Try it out below: click on a radio button, then use your arrow keys to select different options. Obviously, this won’t work if you’re on a device without a keyboard, so keep that in mind if your slides’ consumers will be on their phones:

See the Pen xwwqRK by Tim G. Thomas (@TimGThomas) on CodePen.

Next, we’ll have to link each slide to its radio button. If we’re hiding the inputs, we need some way of giving them focus so that the browser can work its keyboard magic. This is as easy as either giving each input an ID and changing each slide to be a <label>

<input id="slide_1" name="slide" type="radio">
<label for="slide_1"><!-- ... --></label>

…or wrapping each combination in its own <label>:

<input name="slide" type="radio">
<div><!-- ... --></div>

Either technique will make each slide “clickable” to set the focus on the radio buttons, thus enabling keyboard movement.

Give each slide some CSS that makes it look like a real slide deck, and you’re good!

Inline CSS Editing

My slide deck also included the ability to edit CSS on the fly and see it instantly update. This is actually a very old CSS Trick that works well to this day. Just move your <style> block inside your <body>, set its style to display: block, and give it the contenteditable attribute: browsers will use it for styling and you can use it for CSS demos. The CSS Tricks site has a great demo page for playing around with this feature.

That’s all there is to it! A few lines of HTML per slide, a sprinkling of CSS, and a little <style> block trickery, and you’ve got yourself a modern—and JavaScript free!— slide deck! If you’d like to learn more about (mis-)using CSS for behavior, read my blog series on “stateful CSS”, watch the presentation video, and check out the code for my slides on GitHub.

If you’ve seen or built any great functionality with little or no CSS, share in the comments!