Organising a project
The previous lessons showed the features one at a time. Here they come together into the structure of a small blog site: variables and mixins separately, components in their own files, and one main.less that only imports the rest. Big Less projects such as the Bootstrap 3 sources are organised the same way.
The folder tree
styles/
├── variables.less ← colours, sizes, fonts
├── mixins.less ← mixins with no CSS output
├── theme.less ← variable overrides
├── base.less ← styles for body, links, headings
├── components/
│ ├── buttons.less
│ └── cards.less
├── utilities.less ← utility classes
└── main.less ← only @importOne file is compiled: lessc styles/main.less css/main.css.
Variables and mixins
To keep the example short, each file holds one or two values:
// styles/variables.less
@primary: #2563eb;
@radius: 8px;
@gap: 16px;// styles/mixins.less
.card-shadow() {
box-shadow: 0 2px 8px fade(#111827, 15%);
}The theme
Thanks to lazy evaluation a variable can be overridden in a separate file imported after variables.less. Every component picks up the new value:
// styles/theme.less
@primary: #7c3aed;Components
Components use the variables and mixins without importing them — everything is imported in main.less:
// styles/components/buttons.less
.btn {
padding: (@gap / 2) @gap;
color: white;
background: @primary;
border-radius: @radius;
}// styles/components/cards.less
.card {
padding: @gap;
border-radius: @radius;
.card-shadow();
}Base styles and utilities
Base styles style elements without classes; utilities are short single-purpose classes:
// styles/base.less
body {
margin: 0;
font-family: system-ui, sans-serif;
}// styles/utilities.less
.text-center {
text-align: center;
}The main file
The order matters: first what produces no output, then base styles, components and utility classes — the last ones must win at equal specificity:
// styles/main.less
@import "variables";
@import "theme";
@import "mixins";
@import "base";
@import "components/buttons";
@import "components/cards";
@import "utilities";body {
margin: 0;
font-family: system-ui, sans-serif;
}
.btn {
padding: 8px 16px;
color: white;
background: #7c3aed;
border-radius: 8px;
}
.card {
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(17, 24, 39, 0.15);
}
.text-center {
text-align: center;
}<style>
body {
margin: 0;
font-family: system-ui, sans-serif;
}
.btn {
padding: 8px 16px;
color: white;
background: #7c3aed;
border-radius: 8px;
}
.card {
padding: 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(17, 24, 39, 0.15);
}
.text-center {
text-align: center;
}
</style>
<div class="card text-center">
<p>The post is saved as a draft.</p>
<button class="btn">Publish</button>
</div>The button is purple: the value from theme.less replaced #2563eb throughout the project. Remove the line @import "theme"; and the button turns blue again.
Rules that make life easier
| Rule | Why |
|---|---|
| One component — one file | The button styles are easy to find |
No rules with output in variables.less and mixins.less | They can be imported anywhere without duplicates in the CSS |
| The theme is a separate file after the variables | The library can be updated without touching your values |
| Nesting no deeper than three levels | Selectors stay short |
Common mistake
If you import theme.less before variables.less, the theme stops working: the original value @primary: #2563eb comes last, and with lazy evaluation it wins. Always import overrides after the file they change.