Opt In CSS Resets At Selector Level

In an Astro project, there are a few different approaches you can take with styling but the main ways are via global styles or scoped styles.

In a world where you are happy with user agent styles as your defaults you could just use scoped styles, indeed, the first time I worked with Astro this is what I did. But there’s only so many times you can write margin: 0 before you get a little irritated. Now don’t get me wrong, I have the mindset that you should be the browser’s mentor rather than enslave it, but when you’re building custom UI, a blank canvas and complete control often make sense.

So this time around I wanted to explore how I could combine a range of sensible defaults with some user-agent styles, but have an escape hatch as and when I need it.

I was recently examining the current state of CSS resets and came across the following selector that Andy Bell uses in the reset he uses at Set Studio.

/* A elements that don't have a class get default styles */
a:not([class]) {
  text-decoration-skip-ink: auto;
  color: currentColor;
}

I thought this was a great way to apply default styles to ‘regular’ links, but I wondered whether this idea could be taken further. I wanted to know if there was a way we could use the :not([class]) selector to opt in to a more aggressive reset on an element when needed.

With that in mind, let’s see how we might apply this idea to the <a> tag.

/* Reset */
a {
  color: inherit;
  -webkit-text-decoration: inherit;
  text-decoration: inherit;
}

/* Sensible defaults */
a:not([class]) {
  text-decoration: underline;
  text-decoration-skip-ink: auto;
  text-decoration-color: palevioletred;
  color: grey;
}

What we’re doing here is setting a relatively aggressive reset on the element selector (these are the styles used in Tailwind’s Preflight), then using the :not([class]) selector to apply our sensible defaults i.e. the styles we want applied in most cases i.e. when we want a link to just be a link.

By doing this, we can now use scoped styles with classes in our Astro components without having to override all of our defaults

<a href="#" class="container">
  <h2>My Linked Component</h2>
  <p>I'm using the 'a' tag in a very different way to normal</p>
</a>

<style>
  .container {
    /* Yay! The act of adding a class resets the styling */
    display: block;
    background-color: salmon;
  }
</style>

In theory, this could be a really nice way to work in Astro, but it’s just a theory at this stage, so I’ll report back my findings once I’ve put it into practice 🫡