How I organise my CSS on a project from scratch
No Sass, no Tailwind, no strict BEM. A single CSS file, structured by hand, top to bottom. Here is how it works in practice.
Every time I start a new project, the CSS question comes back. Which preprocessor? Which naming convention? Which file organisation? Community answers vary, trends change, frameworks proliferate.
Over the years I have simplified my answer. A single CSS file. No Sass, no compilation. Custom property variables at the top, commented sections throughout, and one immutable rule: one class, one line.
Variables first
The file always starts with a :root block that centralises all design values: colours, typography, spacing, breakpoints, animation timing. It is the project's design system, readable in a few dozen lines.
The advantage of custom properties over Sass variables is that they are real at runtime. You can modify them in JavaScript, read them in the console, override them in a child selector. They are part of the DOM, not just the compiled stylesheet.
A structure in sections
After the variables, the file follows a logical order that stays consistent from project to project: minimal reset, global typography, base elements (links, images, forms), layout (header, footer, containers), then components page by page.
Each section is separated by a short comment. No folders, no partials, no imports. Everything is in the same file, in the same order. When I look for something, I know where to look.
One class, one line
This is the most constraining rule — and the most useful. Every CSS rule fits on a single line:
.btn_primary { display: inline-flex; align-items: center; padding: 14px 28px; border-radius: 40px; background: var(--color_accent); }
It may seem hard to read at first glance. In practice, the opposite is true. When you look for a property, you look for a line, not a block. The visual density makes the file compact, scrollable, comparable. A ten-property component takes one line instead of ten. The entire CSS of a project often fits in under a thousand lines.
Naming: simple and intentional
I do not apply BEM strictly. Classes reflect the project's semantics rather than a generic convention. A navigation component is called .main_nav, its children .main_nav a or .nav_item depending on their complexity. Underscores separate words; double underscores or hyphens signal a variant.
What matters is that the name is readable and predictable in the context of the project — not that it follows an external standard that was never designed for this specific site.
Media queries at the end, per component
Rather than grouping all media queries at the end of the file, I place them right after the component's rules. This keeps the relationship between desktop and mobile styles in the same place, without having to jump between sections to understand the full behaviour of an element.
It is not an absolute rule. On very simple projects, a single media query section at the end of the file is enough. The method adapts to the project, not the other way around. That is perhaps the only principle that truly matters.
