#207: Psychedelic CSS, Eleventy, and a quick guide to Emotion

[Robin]: I found this psychedelic TikTok where an artist overlaps a collection of words on top of each other and then rotates them around the center, creating this extremely cool effect:

Whoa, right? I wanted to try and replicate this effect in the browser. To begin, I switched on the Haml language in CodePen since it handles loops and I knew I’d need hundreds of copies of the same line of text. I started with a really high number, like 120, then kept incrementing it later until I found the effect I was looking for:

Beautiful. Next, we need to style all this text and position each sentence in the middle of the screen and on top of one another. I found the Modak typeface on Google Fonts and imported that into the of the HTML. I needed just a few lines of CSS to do the rest:

html, body {
  height: 100%;
  background-color: black;

body {
  position: relative;
  display: grid;
  place-items: center;

div {
  position: absolute;
  font-size: 6vw;
  color: white;
  text-transform: uppercase;
  font-family: "Modak", cursive;

Okay, so now we can start to do all the fancy animating parts of this thing. I knew I wanted two effects: I wanted to spin the text around just like that TikTok above, but I also wanted to make the text sort of start more dull then become brighter. This encouraged me to split up the animations into two separate keyframes:

div {
  // other text styles go here
  animation: spin 8s linear infinite, opaqueness 14s linear forwards;

@keyframes spin {
  0% {
    transform: rotate(0deg);
  } 100% {
    transform: rotate(360deg);
    animation-fill-mode: forwards;

@keyframes opaqueness {
  0% {
    opacity: 0.3;
  } 50% {
    opacity: 0.1;
  } 100% {
    opacity: 0.4;

We get something like this:

…which is extremely funny, but it isn’t ideal. All of the 188 absolutely positioned elements are rotating and fading in/out at the same time. So! We need to make a delay for each element, which thankfully we can do easily with Sass and the animation-delay CSS property:

@for $i from 1 through 188 {
  div:nth-child(#{$i}n) {
    animation-delay: (0.05 + $i) * 0.15s;

There’s no real fancy math going on here, I just kept smashing numbers into it until I started to like the visual effect I was seeing. Which was this kinda neat thingy:

Okay so now there’s one last step: color! But how do we give each sentence a different rainbow color that’s slightly different from the last? Well, after a bit of searching on CodePen I found this rainbow table by Cristen Jones:

Isn’t this just lovely? What we want to do is use the same sort of technique that Cristen used here — Sass’s adjust-hue() function. This takes in a value and then increases or decreases it depending on what you want. So, after punching in some completely arbitrary numbers, I came up with the following:

// This next bit is almost entirely stolen from Cristen Jones and this pen: https://codepen.io/thecristen/pen/ZOBYZx

$base-color: #ffccb7;

@for $i from 1 through 188 {
  $angle: $i * 2500/100;
  $this-color: adjust-hue($base-color, $angle);

  div:nth-child(#{$i}n) {
    animation-delay: (0.05 + $i) * 0.15s;
    color: $this-color;

And there we have it! A completely perfect use of a weekend where I was bored and stuck indoors all day:

An Introduction to CSS Specificity

Sarah Chima has written this great intro to specificity in CSS where she writes that:

…we can see that CSS specificity is an important topic to understand because it can save you hours of debugging. With this knowledge, you can easily find out why your styles are not being applied.

Sarah talks about how there’s a weighting system in CSS — certain types of styles will override others depending on the circumstance. Now at first this appears to be extremely complex and confusing but I think that once you sit down and try to wrap your head around it it really does start to make sense.

One tiny note I’d add here is that learning about CSS specificity will actually be great for writing less code. A project I’m working on right now is basically doing just that, removing CSS so we can let the cascade do its job and style elements automatically without us having to declare them.

Become an MVP member of CSS-Tricks

For $20 a year, you can support the work that we do around here: gathering, writing, and editing posts all about front-end development. But! You also get a bunch of cool stuff from us:

  • No Advertising on CSS-Tricks dot com
  • Extra content, such as the digital books that Chris is writing
  • Easier commenting
  • Good feels for knowing that you support us

You can sign up now!

Also, side note: if you want to learn about how to setup your own subscription and membership access for your own website then Chris wrote about how he built all this with WordPress and WooCommerce.

A Beginner’s Guide to Eleventy

Tatiana Mac has started writing a guide all about Eleventy that walks through what it is, how it works, and why it can be so useful for you if you’re making a personal site.

This first piece is focused on what a static site generator is (that’s what Eleventy is if you’re unfamiliar) compared to other kinds of websites. Tatiana also writes about why she adores Eleventy:

I favour Eleventy for most smaller projects because the way it was built aligns with my personal developer ethos. I do not like serving the user a bunch of unnecessary JavaScript to serve what will inevitably be static content.

Eleventy’s mission seems to possess some similar biases to me. In the end, this is a huge factor in what we look for as developers, whether we admit it or not.

Oh, speaking of which….

An Eleventy Starter with Tailwind CSS and Alpine.js

Greg Wolanski writes about how to get started with Eleventy but from the perspective of combining it with two interesting front-end tools:

  • Tailwind: a utility-based CSS framework that lets you add CSS classes such as text-gray-600 to a HTML element and not have to worry about writing CSS yourself.
  • Alpine.js: a JavaScript framework that lets you avoid the larger frameworks in the space but sweetens the pot by sprinkling JavaScript on top of your HTML.

If this is news to you then it might be worth checking out our post about getting started with Alpine.js.

WordPress + React = ♥️

That is not a buzz catchy title, but sort of the magic that is possible when using Frontity. Chris wrote about just how darn quickly he used it to take data from the CSS-Tricks WordPress REST API and create a React-based front-end out of it:

I’m always very happy building sites with WordPress, and doubly so now that we have the block editor to use. I really like having an editor experience that helps me write and craft the kind of pages I want to create.

But I also like working with component-based architectures that have fast, easy-to-use, hot refreshing local development environments. Once you work in this kind of dev environment, it’s hard to use anything else! Beautiful DX.

Getting started with Emotion

Last week, I made a List component with Emotion which is a library that lets you write CSS within JavaScript, then it effectively changes the cascade by replacing classes such as “.active” with something like “.active-a30953059.” This is good and also maybe sometimes bad for a whole bunch reasons.

But if you’ve yet to get started with Emotion and React, or would like to see what it takes to make a very simple component without any state or complex styles, then this is the place to start. It certainly took me a while to get my head around all this stuff and there were some aha! moments and some uhuh?? moments, too. Here is the final thing, in all its visual splendor:

5-minute web design tutorials from Ethan Marcotte

Ethan is infuriating, except in a good way. His work is always straightforward and, even if he’s talking about the very basics of web design, I tend to listen because there’s something I missed years ago or there’s an old technique I can apply to my work today.

This is true even of Ethan’s new videos about design and accessibility, where each video is roughly five minutes long. That feels like the perfect length for videos of this sort.

Oh, and I just spotted this rather lovely detail on Ethan’s website: if you hover over a link and click it then you get this effect to confirm your click.

It’s not clear how nice it feels from the gif but I do like it a whole bunch. It gives you immediate feedback that your input has been registered by the browser, which is nice.


Fast authoring of AI-stabilized cross-browser tests. Edit tests in your IDE, sync branches with Git, run in CI. Coded and Codeless. Start Testim Free today!

WooCommerce Day is Coming!

…and it’s literally the biggest sale that WooCommerce offers all year. So, if you’re planning to purchase any WooCommerce products, mark your calendar for July 28th because that’s when the action starts. Until then, start making your shopping list.

[Chris]: Here’s a couple of links about dark mode on websites that were burning a hole in my pocket. They complement our own Complete Guide to Dark Mode, of course:

  • Kilian Valkhof: Your dark mode toggle is broken

    Just like prefers-color-scheme toggles between three states, your dark mode toggle should also toggle between three states: light, dark, system

  • Max Böck: Color Theme Switcher

    I decided to build a new feature on my site:
    dynamic color themes! Yes, instead of two color schemes, I now have ten! That’s eight better than the previous website!

  • Joshua Comeau: The Quest for the Perfect Dark Mode

    The reason that this problem is so dastardly has to do with how frameworks like Gatsby/Next.js work; the HTML is generated ahead of time. If you’re not careful, you’ll wind up with that telltale flicker, where the user sees the wrong colors for a brief moment.

    Today we’ll learn how to build the perfect Dark Mode for Gatsby.js.