How to make a Snake on checkboxes and more

In pre-pandemic 2020, Brian Brown went to the Recurse Center for a week and developed Checkboxland… This JavaScript library displays text and animation on a grid of checkboxes.

For a funny little project, the author did several demos, wrote about it, and in the end put the project on the shelf and did not touch it for about a year. In the end, I desperately wanted to have fun with programming, and the author took up Checkboxland again. I wanted to make a better and more complex animation, so it all started with a ripple effect – and got hooked. Yes, on KDPV you see a frame from the video on the checkboxes.

Until we begin Frontend development course, we share two materials about checkboxes at once.

Math animations

Ripple animation.  See my ripple article for more details
Ripple animation. See my ripple article for more details

The ripple creation got me going deeper into the math of animation. I soon realized that I could use similar techniques to create other animations, including these:

When I showed someone an animation like this, people often tried to click on the checkboxes to see what happened. The click did nothing – the animation just canceled their clicks, which was quite frustrating, so I wanted to do a click-responsive animation.

Interactive animations

“Laser” -animation. Try it here
Pulse animation.  Try it here:
Pulse animation. Try it here:

The more interactive demos I did, the more ideas I came up with. I can create games! Snake, ping pong, tetris! But before I got too far down this path, a new thought struck me.

If I could display any image, then I wouldn’t have to go through the laborious process of manually defining each checkbox or coming up with an algorithm for the scene I want.


Converting images seemed like a daunting task, so I put it off for a long time until I came across this See a great article on converting images to ASCII text. After a while, I converted the images:

I soon realized that converting images is 90% of the way to converting videos. And here’s the result.


The mp4 video (left) serves as the basis for the animation of the checkbox (right).  Try other videos or upload your own
The mp4 video (left) serves as the basis for the animation of the checkbox (right). Try other videos or upload your own

I soon extended the Checkboxland API to be able to load any video (from giphy or gifer, for example) and instantly generate a checkbox version. Animating flags has become trivial.

This means I can display webcam data, which has garnered a lot of attention on Twitter:

Finally, my colleague Reed told me about a problem where people are trying to reproduce the “Bad Apple” animation in various obscure computing environments. a bunch of examples here). It sounded funny, so I went and recorded a Youtube video.

This whole process was fun, but I really need to stop.

I was hit in the head by the project, I gave up everything because of it. Sure, it’s harmless entertainment, but I start to feel guilty about spending months fiddling with these things when I have the tools and skills to release something really useful.

I AM feel himself as Superman using his super powers to fry an egg. If I continue like this, I will become known as the “tick-off guy.” It’s not very sellable, but I think it gets worse.

Luckily, I seem to be starting to exhaust all the interesting ideas I could do in this format. Sometimes it looks like “dude, we got it, you can do anything with the flags.”

I have a few more protracted ideas, although … maybe it’s like a controlled wildfire, and I should just allow myself to keep doing this until the ideas burn out by themselves.

While the author is deciding what to do with the ideas, you can start exploring the frontend or just read the following material.

Five techniques for styling checkboxes

Original… Author: Preethi

We could leave a text input field or a link without styling, even a button. But checkboxes … no, we won’t leave them alone. And while the design of checkboxes is not that complicated, we shouldn’t be limited to changing the background color or adding / removing borders to indicate state changes. And we don’t need any special design skills (which we don’t have) to make this all work.


In the following demos, almost all checkboxes have a three-level layout: at the bottom there is a checkbox, and at the top there are two elements or pseudo-elements. The state of the checkbox depends on which one is visible, that is, whether it is checked or not.

Look at the CSS in pen: all layouts there (including checkboxes) are grids. Try other options that suit your case and find out more at guide by CSS Grid. Additional notes on code and design alternatives are at the end of the source code inside pen.

Any elements above the checkbox have a property pointer-events: noneso they don’t make it difficult to click on the checkbox.

And here’s the first styling method.

1. Mixed backgrounds as a checkbox state

Blending is a generic CSS technique. Manipulating the colors of two or more elements or backgrounds is useful in unexpected contexts, including checkboxes:

<input id="un" type="checkbox"> <label for="un">un</label>
<!-- more checkboxes --> 
input[type=checkbox]::after {
  mix-blend-mode: hard-light;
  pointer-events: none;
  /* more style */
input[type=checkbox]::before {
  background: green;
  content: '✓';
  color: white;
  /* more style */
input[type=checkbox]::after {
  background: blue;
  content: '⨯';
  /* more style */
input[type=checkbox]:checked::after {
  mix-blend-mode: unset;
  color: transparent;

Here, the pseudo-elements located one under the other are stylized in green and blue, each is assigned a value mix-blend-mode… This means that the background of each element merges with the background behind it.

The hard-light value is used, which simulates multiply or screen depending on whether the top color is darker or lighter. More about the various modes mixing can be read on MDN. When the checkbox is checked, the mix-blend-mode value of the :: after pseudo-element is not set and the visual display is slightly different.

2. 3D animation

Animating colored blocks is a great idea. Let’s make them like in 3D: it will be even more spectacular. CSS provides a means of rendering elements in emulated 3D space. Using them, create a 3D checkbox and rotate it to indicate a change in state:

<div class="c-checkbox">
  <input type="checkbox" id="un">
  <!-- cube design -->
<label for="un">un</label>
<!-- more checkboxes -->
.c-checkbox > div {
  transition: transform .6s cubic-bezier(.8, .5, .2, 1.4);
  transform-style: preserve-3d;
  pointer-events: none;
  /* more style */
/* front face */
.c-checkbox > div > i:first-child {
  background: #ddd;
  transform:  translateZ( -10px );
/* back face */
.c-checkbox > div > i:last-child {
  background: blue;
  transform:  translateZ( 10px );
/* side faces */
.c-checkbox > div > i:nth-of-type(2),
.c-checkbox > div > i:nth-of-type(3) {
  transform: rotateX(90deg)rotateY(90deg);
  position: relative;
  height: 20px;
  top: 10px;
.c-checkbox > div > i:nth-of-type(2) {
  background: navy;
  right: 20px;
.c-checkbox > div > i:nth-of-type(3) {
  background: darkslategray;
  left: 20px;

<div> becomes a container of 3D space – its children are positioned along the x, y and z axes – after being given transform-style: preserve-3d

Using the transform property, place two elements (gray and blue) on the z-axis at some distance from each other. And two more – between them, covering the left and right sides. It’s like a cardboard box with no edges at the top and bottom.

When the checkbox is checked, the gray-blue box rotates. The rotation is animated by adding a transition to the :

input:checked + div { 
  transform: rotateY( 180deg ); 

3. Changing the border radius

Let’s change not only the radius of the border of the checkbox marked with a tick, but also the radii of the borders of adjacent checkboxes:

<input type="checkbox" id="un"> <label for="un">un</label>
<!-- more rows of checkboxes -->
input {
  background: #ddd;
  border-radius: 20px;
  /* more style */
input:not(:first-of-type)::before {
  content: '';    
  transform: translateY(-60px); /* move up a row */
  pointer-events: none;
input:checked + * + input::before,
input:last-of-type:checked {
  border-radius: 20px;
  background: blue;
input:checked + * + input:checked + * + input::before {
  border-top-left-radius: unset !important;
  border-top-right-radius: unset !important;
input:checked::before {
  border-bottom-left-radius: unset !important;
  border-bottom-right-radius: unset !important;
/* between the second-last and last boxes */ 
input:nth-of-type(4):checked + * + input:checked {
  border-top-left-radius: unset;
  border-top-right-radius: unset;

When you click on a checkbox, not only its own borders change, but also the borders of the checkboxes to and after him.

There are no selectors to select previous elements, only subsequent ones. To control the appearance of the previous checkbox, its pseudo-element is used. All checkboxes except the first receive pseudo-elements that move to the top of the previous checkbox. Now let’s assume that checkboxes A, B and C are positioned one after the other:

  • By clicking on B, you can change the appearance of A by styling pseudo-element B.

  • Also, by styling pseudo-element C, you can change the appearance of B,

  • The appearance of C can be changed by styling the pseudo-element D.

  • From element B, pseudo-elements B, C, and D are available as long as the next element selector is used between them in the layout.

The four corners of each checkbox are initially rounded when the checkbox is unchecked. But when a checkbox is checked, the top corners of the next checkbox and the bottom of the previous one are straightened (by overriding and removing their border radii).

4. CSS mask

Toggle switches and switches can also be implemented as checkboxes, which are styled with a CSS mask. This is a technique where an image is used to filter part of the background:

<input type="checkbox">
<div class="skin one"></div>
<div class="skin two"></div> {
  background: no-repeat center -40px url('photo-1584107662774-8d575e8f3550?w=350&q=100');
} {
  background: no-repeat center -110px url('photo-1531430550463-9658d67c492d?w=350&q=100');
  --mask: radial-gradient(circle at 45px 45px , rgba(0,0,0,0) 40px, rgba(0,0,0,1) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);

Both skin elements that display landscape photos sit on top of the checkbox. The topmost one gets a mask-image in the form of a normal toggle switch – this is a transparent circle on the left, and the rest has a completely transparent color. The photo is visible through the transparent circle, the remaining mask image shows the photo above.

When you click on the checkbox, the transparent circle moves to the right and the image above is visible through the circle; the rest shows the photo below:

input:checked ~ {
  --mask: radial-gradient(circle at 305px 45px, rgba(0,0,0,1) 40px, rgba(0,0,0,0) 40px);
  mask-image: var(--mask); -webkit-mask-image: var(--mask);

5. Reception with box-shadow

In conclusion – something simplest, but also, in my opinion, the most spectacular – animated box-shadow insertion:

<input id="un" type="checkbox"> <label for="un">un</label>
input {
  transition: box-shadow .3s;
  background: lightgrey;
  /* more style */
input:checked { 
  box-shadow: inset 0 0 0 20px blue;

One of the CSS properties that can be animated by default is box-shadow. It goes well with minimalism.

That’s all for today. You can upgrade your skills or start mastering the frontend from scratch on our courses:

You can also go to the course pages from catalogto see how we train specialists in other areas.

Professions and courses

Data Science and Machine Learning

Python, web development

Mobile development

Java and C #

From the basics to the depth


Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *