Gary Byrne

Posted on

# Fizzbuzz with CSS and Pug

Back in 2017, I entered a frontend interview and I was asked to write some code on a whiteboard. I was given the Fizzbuzz problem. Without thinking I immediately went for JavaScript. Recently I learned about CSS counters and that got me thinking. What if we can do it with CSS?

In this article, I am going to show you two easy ways to solve the Fizzbuzz problem with CSS.

## What is the Fizzbuzz question?

Write a program that prints the numbers from 1 to 100.
For multiples of `3` print `Fizz` instead of the number,
for the multiples of `5` print `Buzz` and for
multiples of both `5 and 3` print `FizzBuzz`

## Solution 1: Using CSS Counters

### We can loop in Pug

Loop for 1 to 100 and create an HTML element. In this example, we are creating a div. We will use each div to hold the counter.

``````- const range = 100;
- for(let i = 1; i <= range; i++)
.fizz

``````

We are using a for loop here. We could also write an each
iteration such as `each _ in Array(100)` instead.

### Using CSS counters

To get started, we must first create a `counter-reset`. This will initialize our CSS counter, giving it a name and setting its value. By default, the value is 0.

``````body {
counter-reset: fizz;
// counter initialized with value of 0, same as saying "counter-reset: fizz 0;"
}

``````

Once a counter has been created, we can use `counter-increment` to increment its value.
For every `fizz` div, let's update the counter.

``````.fizz {
counter-increment: fizz;
}

``````

Next, we will set the content for our divs. We can utilize CSS `before` and `after` pseudo-elements to set the content of the div.

If the div is a multiple of 3, set its `::before` content to 'Fizz '. If the div is a multiple of 5, set is `::after` content to 'Buzz'. If a div is a multiple of both 3 and 5, the before and after pseudo-elements will combine to form `Fizz Buzz`.

``````.fizz:nth-child(3n)::before {
content: 'fizz ';
}

.fizz:nth-child(5n)::after {
content: 'buzz';
}

``````

Now we want to set the counter value for those other divs that are not a multiple of 3 or 5. To set the `::before` content of the div to use the counter value, we use `counter`.

``````
.fizz::before {
content: counter(fizz);
}

.fizz:nth-child(3n)::before {
content: 'fizz ';
}

.fizz:nth-child(5n)::after {
content: 'buzz';
}

``````

This gives us the following:

Note how the divs with a multiple of 5 and not a multiple of 3 still get the number applied. To fix this we can use the not pseudo-class. When the div is `not` a multiple of 5, then set the before content to the counter number.

``````.fizz:not(:nth-child(5n))::before {
content: counter(fizz);
}
.fizz:nth-child(3n)::before {
content: 'fizz ';
}

.fizz:nth-child(5n)::after {
content: 'buzz';
}

``````

Here is a working example in codepen:

### Refactoring our Pug

In some cases, an interviewer might ask to change your code to work for a different range instead of 1 to 100. We can write a Pug mixin to take a min and max value.

``````mixin fizzbuzz(min, max)
- for(let i = min; i <= max; i++)
.fizz

+fizzbuzz(1, 100)

``````

Here is a working codepen example:

### Browser Support

At the time of writing, CSS Counters are supported in most major browsers. See Can I Use for more information.

## Solution 2: Using an Ordered List

Let's copy the same pug from the last example.

``````mixin fizzbuzz(min, max)
ol
- for(let i = min; i <= max; i++)
li

+fizzbuzz(1, 100)

``````

So we have an ordered list here which returns a list of numbered elements. So if we render 100 list items in that ordered list, we have the numbers already available to view. Although it makes no sense semantically, it is just to show how we might do this.

In this ordered list, we can set the list-style-position of each list item to `inside`. This will set the position of everything inside, relative to the list which created the nice alignment. We then just set the list style to none to remove the numbering on those items that need the text.

``````//scss

li {
list-style-position: inside;

&:nth-child(3n), &:nth-child(5n){
list-style-type: none;
}

&:nth-child(3n)::before {
content: 'Fizz';
}

&:nth-child(5n)::after {
content: ' Buzz';
}
}

``````

Here is a working example:

Joel Patrizio

With CSS? You're not allowed to do that! ... oh

Gary Byrne

Haha. That is so true. I would love to know if anyone has done this before.

Joel Patrizio

And if anyone has done this in an actual interview. I guess you can nail any frontend interview if you solve a JS problem with just CSS 😁

Gary Byrne

Not to mention the pressure you are already under when in an interviewing environment.

Felix Wittmann • Edited

That is the proof, so css is finally turing complete :)

Gary Byrne

👍 It also makes you think about other common interview questions. Maybe it's possible for others