Fizz Buzz in CSS

Ever heard of FizzBuzz? To developers, it’s a controversial and oft-used problem to give when applying for positions, but to children it’s instead a game to teach them about division and multiplication.

Briefly, the idea is that you count up in 1s starting at 1 and every time you are supposed to say a number divisible by 3 (such as 3, 6, 9…), instead, you say “Fizz”. If it’s divisible by 5 (that’s 5, 10, 15…), you say “buzz” and if both 3 and 5 divide into it exactly (e.g. 15, 30…), you say “FizzBuzz”.

For developers, there isn’t anything peculiar about this task: it simply uses loops/if conditions but that aside, I’d never seen this before:

Wow! That got me wondering…how might it be done? This brief article is going to show you one such implementation. I am sure there are more so do get in touch if you know a better way using standard css.

Let’s start with a blank HTML document; we’ll use this to display our numbers.

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Fizz Buzz</title>
</head>
<body>

</body>
</html>

Now add some numbers in:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
</ul>
</body>

In the browser, all is looking mighty fine.

But what about the rules? Well, we’re going to lean on css pseudo-elements.

A CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s). For example, ::first-line can be used to change the font of the first line of a paragraph.

The first one we’re going to use here is named :nth-child which matches against elements based on their position amongst siblings. In plain speak, it lets you match against things which are alongside one another at the same level such as…you guessed it: <li> elements.

One way to use it is to specify which exact element you want, like the 5th. For that, we would combine all three things (the element), the nth-child and the position, like this:

1
li:nth-child(5)

The problem is, we don’t just want one element - we want to match against every 3rd or 5th element. With a little tweak, we can do just that using the n notation. Here’s how it looks.

1
2
3
4
5
li:nth-child(3n)

or

li:nth-child(5n)

What that means is we want to match against every 3rd or 5th <li> element. Let’s see that in action but turning those elements red and blue, respectively, just for this example. Go to the top of your HTML document, and in the HEAD section, add this chunk of CSS:

1
2
3
4
5
6
7
8
<style>
li:nth-child(3n) {
color:red;
}
li:nth-child(5n) {
color:blue;
}
</style>

Here’s a screenshot showing that.

Moving closer, right? But, we still don’t see any “fizz” or “buzz”. To fix that, we need to incorporate another pseudo-element: :before.

1
2
3
4
5
6
7
8
<style>
li:nth-child(3n):before {
content:'fizz';
}
li:nth-child(5n):before {
content:'buzz';
}
</style>

Here, what we’re telling CSS is that for each third line, place the text “fizz” in front of what is there. Equally, for every fifth line, let’s add the word “buzz”. Here’s the effect of that on our text.

OK…progress. But look what happened at number 15: we lost the “fizz” and overwrote it with a “buzz”. To fix this, we can alter the pseudo-element to use :after; that way, our “fizz” will stay in front of the text for that <li> and “buzz” will buzz to the end. Here’s the new CSS and the result.

Much better, but how do we get rid of those numbers - we don’t need those when we are using “fizz” or “buzz” or “fizz buzz”. The trick here is to wrap the numbers in an element (a <span>, in this case) and then just hide it in a puff of smoke. Head back to the HTML and alter the list of numbers to look like this:

1
2
3
4
5
6
<ul>
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
...and so on

The last thing to do is to add in some CSS to remove the <span> element for any that match our pattern of 3rd or 5th. I’ve provided the whole CSS below and added in those colours from before back in, to make it stand out more:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<style>
li:nth-child(3n):before {
content:'fizz';
color:red;
}
li:nth-child(5n):after {
content:'buzz';
color:blue;
}
li:nth-child(3n)>span,
li:nth-child(5n)>span {
display:none;
}
</style>

And how does that look in shiny Chrome?

That’s it then - one CSS solution to Fizz Buzz.

If you like, as an exercise, you can add in some JavaScript to dynamically create the list of numbers. If you need a hint, take a look at these JavaScript functions:


Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com