Blog Post

Templating Classes in Astro

April 16, 2022

Category: Astro

Tags: web dev

Astro is a new static site generator that I’m quite taken with. Whenever I have time, I’d like to redo this blog in Astro.1 Like React, Vue, and other JS frameworks, Astro is built on components, which you can use to template out a site.

Dymnaic values in components

When creating components, you’ll quickly find you want to pass in dynamic classnames into components. For instance, a simple button component using Tailwind CSS might look like this:

---
const { bkg, color, btnText, link } = Astro.props;
---

<a href={link} class={`inline-block font-sans text-sm uppercase tracking-wider font-bold no-underline bg-${bkg} text-${color} py-2 px-8 rounded-sm cursor-pointer max-w-max shadow-md transition-shadow hover:shadow-none focus:outline-none focus:shadow-none focus-visible:ring-4 focus-visible:ring-offset-4 focus-visible:ring-${bkg}`}>{btnText}</a>

Calling the component would look like this:

---
import Button from "../components/Button.astro"
---

<Button bkg="neutral-900" color="neutral-200" btnText="Read more" link="/blog/post-1/"/>

Notice how we’re passing in dynamic values for the color and background color. While this is a simple example, sometimes you’ll want to pass in an array or object full of classes.

Astro has a built-in directive (class:list) meant for taking in arrays, sets, objects, strings, and more. Whatever array you pass in is flattened and added in the class attribute.

Class:list syntax

When advancing beyond passing in basic strings, you may have objects, arrays, etc. that contain groups of classes you want to dynamically pass into your button Astro component.

The class:list documentation explains that the class:list={…} directive “takes an array of class values and converts them into a class string.”

The documentation lists four examples:

  • string: Added to the element class
  • Object: All truthy keys are added to the element class
  • Array: flattened
  • Set: flattened

Any duplicate values are removed automatically.

Here’s the example from their docs:

<!-- This 👇 -->
<span class:list={[ 
  'hello goodbye',
  { hello: true, world: true },
  new Set([ 'hello', 'friend' ])
  ]} 
/>
<!-- Becomes 👇 -->
<span class="hello goodbye world friend"></span>

Like most things Astro, I continue to be impressed with the attention to the dev experience all while giving such care to the client-side result.


  1. The entire site needs to be rebuilt from start to finish. It’s a total mess. 🤣 It’s a solid 1.5 years old and was hacked together back then with my limited abilities! ↩︎