Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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 @import

One 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

RuleWhy
One component — one fileThe button styles are easy to find
No rules with output in variables.less and mixins.lessThey can be imported anywhere without duplicates in the CSS
The theme is a separate file after the variablesThe library can be updated without touching your values
Nesting no deeper than three levelsSelectors 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.

Thanks for reading!

Donate to the site — we work hard for you.