Project: FizzBuzz in CSS

I wanted to try FizzBuzz in CSS. I've written it insert overestimate times in JavaScript so I wanted to try something different.

If by chance you're not familiar, the usual formulation of FizzBuzz is to write a program with these rules:

  1. Print the numbers from 1 to 100 (inclusive) except...
  2. Don't print each number which is divisible by 3, instead print "Fizz"
  3. Don't print each number which is divisible by 5, instead print "Buzz"
  4. Print "FizzBuzz" for those numbers which are divisible by both 3 and 5


This is my best attempt. The "output" immediately follows this style element:

<style contenteditable></style>
<div class="solution">


Fri Sep 22 07:40:06 PM PDT 2023

My first idea was to create a hundred <div>s manually then style them to produce the FizzBuzz output.

I knew I could print incremental integers by styling those elements as list items. I searched mdn increment list item number css and found many useful links. I started with MDN's "Using CSS Counters. I tried a short example, first the CSS:

<style contenteditable></style>

By the way, the contenteditable attribute above means you can edit this to see what happens.

To use the example CSS, I threw 3 spans within this div:

<div class="example1">

It worked! I could see the content with the incrementing counter from my CSS. Nice. Ostensibly if I were to put 100 spans in here, we'd see the numbers 1 to 100. I felt like I had the easy part of FizzBuzz in the bag.

For the next parts, I figured I could use the nth-child CSS tools. I hadn't used them in a while so again I had to go to the MDN page on :nth-child(). It was the "Functional notation" I had in mind specifically, where I could define the polynomial An+B.

For Fizz, my rule would be 3n+0. I needed the +1 since the n count starts at 0, but my list starts at 1. With that, I could override the content from my counter. I made another small example before I tried the whole shebang, to make sure I got it right.

<style contenteditable></style>

This time I used divs instead of spans so they'd flow downward, and I used more to clarify the effect.

<div class="example2">

Okay it almost worked, except I got the polynomial wrong. Of course 3 * 0 + 1 is 4, but I want it to be 3, so I actually didn't need the +1. You can try messing with the above style to see for yourself!

Now I felt ready to try the whole thing:

<style contenteditable></style>
<div class="attempt1">

It worked! I had to make the numerical observation that the only numbers divisible by 5 and 3 would be those divisible by 15.

I actually figured that out by looking at the working result. I had gotten the answer before with more CSS tricks, but I felt that was less straightforward.

If you're interested, the trick was to use ::before for the Fizz numbers and ::after for the Buzz numbers such that if they were both present the content rules wouldn't collide.

This required an extra rule for Buzz numbers to clear the ::before content, in case they weren't Fizz. But that rule had to be placed specifically in the CSS document order so that it wouldn't override the Fizz rule in the case that it was a FizzBuzz number.

Here's a small example:

<style contenteditable></style>
<div class="attempt2">

The way I wrote the output in my examples, divs and spans within pre code containers, had too much line spacing. It was obnoxious on 100 item lists. I wrote some quick CSS to fix it.

<style contenteditable></style>

I wanted to try a trick to change every instance of the word Fizz on this page to Crackle and Buzz to Pop. So FizzBuzz would become CracklePop. This was utterly unrelated to the main goal, just a fun thing. I decided to try a query string toggle first. So if a user accesses this site with the query string ?crackle=pop then this would be a CracklePop page instead.

Luckily I only ever wrote Fizz and Buzz with capitalized first letters. If I ever wrote them lower case, I'd have to find a better solution or add special cases.


You can try it yourself! Just put ?crackle=pop on the end of the current URL and retry.