DevPath · Learn to code ESPTEN

Modern CSS, accessibility and architecture

Accessibility and CSS architecture

Visible and accessible focus

Here's a mindset shift: until now you wrote CSS so it would look good. Now you'll write it so everyone can use it, no matter how they navigate. That's accessibility, and it separates people who make websites from people who make websites properly.

Focus indicates which element will receive the keyboard. ⚠️ Classic trap: killing it with outline: none "because it's ugly". If you remove it without an alternative, you blindfold everyone who navigates with a keyboard, and that's a lot of people. :focus-visible solves the age-old dilemma: it shows the focus ring when navigating with the keyboard, but not on every mouse click. Best of both worlds.

.button:focus-visible {
  outline: 3px solid #2563eb;
  outline-offset: 2px;
}

Respecting user preferences

The operating system exposes preferences that CSS can read with media queries:

/* Reduce or remove animations for whoever asks for it (dizziness, vestibular) */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
/* Adapt the theme to the system's dark mode */
@media (prefers-color-scheme: dark) {
  :root {
    --background: #0f172a;
    --text: #e2e8f0;
  }
}

Contrast

⚠️ Classic trap: that light gray on white that looks so elegant on your brand new screen in broad daylight is, for many people, unreadable. Text must have enough contrast against its background. The WCAG AA guidelines ask for a minimum ratio of 4.5:1 for normal text and 3:1 for large text. Don't eyeball it: always check the contrast with a tool.

Architecture: BEM

As CSS grows, the biggest difficulty is not writing it but maintaining it without it collapsing on top of you. ⚠️ Classic trap: magic names like .blue2 or .finalBox that even you can't decode a week later. BEM (Block, Element, Modifier) is a naming convention that makes your CSS predictable and readable at a glance:

.card { }              /* Block: the component */
.card__title { }       /* Element: a part of the block (double underscore) */
.card--featured { }    /* Modifier: a variant (double dash) */
<article class="card card--featured">
  <h2 class="card__title">Hello</h2>
</article>

Controlling specificity

Specificity decides which rule wins when several affect the same element. A good architecture keeps it low and flat:

BEM, by using flat single-level classes, keeps specificity constant and spares you the !important wars (the ones where only you lose).

And with this you close the Web track. Stop for a second and look back: you started with an <h1> and now you handle semantics, layout, forms, animations, accessibility and maintainable modern CSS. You can build complete, well-made interfaces. Genuinely, congratulations. 🎉

The only thing they're missing is motion: reacting to a click, validating, updating data without reloading the page... that's JavaScript, and it's exactly what comes next. You're halfway there, and the best part is just starting.

Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Modern CSS: clamp(), aspect-ratio, :has() and moreView the module →