CSS Best Practices Before You Add JavaScript
· 5 min read
This is the final lesson of this course, and it's intentionally a step back rather than a new technique.
This is the final lesson of this course, and it's intentionally a step back rather than a new technique. You now know enough CSS to build real, responsive, polished interfaces. Many learners at this point jump straight into JavaScript to add interactivity, which is a reasonable next step, but there are a handful of CSS habits worth locking in first, because sloppy CSS foundations make everything you build on top of them, including JavaScript, harder to maintain.
Organizing Your Stylesheet
First: keep a consistent, intentional file structure. Even a single stylesheet should be organized in a predictable order: resets and base element styles first, variables next, then layout components, then smaller UI components, then utility or override classes last. This mirrors the general order used throughout this course's final project lesson. When a project grows beyond one file, splitting into multiple files by purpose (a layout file, a components file, a variables file) and combining them with multiple <link> tags, or a build tool, keeps things navigable as it scales.
Consistent Naming Conventions
Second: name things consistently, not cleverly. Lesson two already advised naming classes by what elements ARE rather than how they look. A broader version of this discipline is picking one naming convention and sticking to it across an entire project. A widely used one, called BEM (Block, Element, Modifier), names classes like card, card__title, and card--highlighted, making relationships between related classes obvious just from reading the name.
<div class="card card--highlighted">
<h2 class="card__title">Iron Man</h2>
<p class="card__subtitle">Genius, billionaire, playboy, philanthropist</p>
</div>
.card { padding: 16px; border-radius: 8px; }
.card__title { font-size: 1.25rem; }
.card__subtitle { color: #666; }
.card--highlighted { border: 2px solid gold; }
You don't have to use BEM specifically, but adopting some consistent convention (rather than inventing naming on the fly per component) makes a codebase dramatically easier for you, or anyone else, to read six months later.
Selectors And Magic Numbers
Third: avoid deeply nested, over-specific selectors. It's tempting to write something like .page .sidebar .widget ul li a, but this creates the exact specificity problems covered in lesson thirteen, making styles painfully hard to override later, and tightly coupling your CSS to one specific HTML structure that becomes fragile to change. A single well-named class, like .widget-link, almost always achieves the same result with far less fragility.
Fourth: lean on your variables and utilities rather than repeating magic numbers everywhere. If 24px appears as a spacing value in fifteen different places across your file, that's fifteen places to remember and update if the design changes; a --spacing-lg: 24px variable from lesson twelve turns that into one place.
Decoupling Styles From Scripts
Fifth, and this matters a lot once JavaScript enters the picture: separate styling classes from behavioral hooks. If JavaScript needs to find and manipulate a specific element, it's common practice to give that element a distinct attribute or class specifically for scripting, rather than reusing a purely visual class, so that a future redesign (changing visual classes) doesn't accidentally break JavaScript that was relying on them, and vice versa.
<button class="button-primary" data-action="submit-form">Launch, Iron Man</button>
Here, .button-primary is purely a visual styling class, while data-action="submit-form" is what JavaScript would actually look for to attach its behaviour. Changing the button's visual style later never risks breaking the JavaScript, because they're deliberately decoupled.
Sixth: validate your work across real conditions, not just your own default browser window at your own default zoom level. Check your page at a narrow phone width, with your browser's text zoomed in, and ideally in both a light and dark operating system theme if you've used prefers-color-scheme. CSS that only looks right under one narrow set of conditions tends to fall apart the moment a real, unpredictable user visits.
Accessibility As Css Responsibility
Seventh, and often overlooked: accessibility is not a separate add-on skill from CSS, it's partly a CSS responsibility. Sufficient color contrast between text and background, visible focus states for keyboard users (never remove outline on focus without providing a clear visual replacement), and respecting prefers-reduced-motion (lesson fourteen) are all CSS-level decisions that meaningfully affect real users, not cosmetic nice-to-haves.
a:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
This keeps a clear, visible focus ring for anyone navigating by keyboard, while :focus-visible (rather than plain :focus) is smart enough to generally skip showing that ring for an ordinary mouse click, giving keyboard users clarity without adding visual noise for mouse users.
Letting Css Own Appearance
Finally, remember what CSS is actually for, which is where this whole course started: CSS controls appearance, not behaviour or data. When you move into JavaScript next, resist the temptation to control visual states (like showing or hiding a menu, or highlighting an active tab) by having JavaScript write individual style properties directly onto elements. The far more maintainable pattern is: JavaScript toggles a class name (like .is-open or .is-active), and CSS, which you already know thoroughly, defines what that class actually looks like. This keeps your visual logic in one place, written in the language actually designed for it.
.menu { display: none; }
.menu.is-open { display: block; }
Try it yourself, as a closing exercise for this whole course: take the responsive profile card you built in the previous lesson, rename its classes using a consistent convention like BEM, move every repeated color and spacing value into :root variables, add a visible :focus-visible style to its button, and confirm the card still looks and behaves correctly at a narrow phone width. That one exercise touches nearly everything covered across all eighteen lessons, and it's exactly the kind of habit that will make your future JavaScript-powered interactivity sit on a solid, maintainable foundation.
KEEP READING