CSS preprocessors

CSS preprocessors
« Back to Glossary Index

Quick answer: CSS preprocessors are scripting languages – mainly Sass, plus Less and Stylus – that extend CSS with variables, nesting, mixins and functions, then compile down to plain CSS. In email, CSS preprocessors keep your styles organised. But they only pay off when paired with a CSS inliner. Clients like Gmail and classic Outlook strip or ignore the <style> block you compiled them into.

CSS preprocessors are one of those web tools that walk into email development and immediately need a chaperone. On the web the story is clean. You write Sass, it compiles to CSS, the browser reads it, done. In email that last step quietly falls apart. Most inboxes never even look at the <style> block you worked to produce. A preprocessor that feels like a finish line on the web is only the halfway mark in email. This entry covers what CSS preprocessors are, why they only do half the job in email, which tools are alive in 2026, which ones died when nobody was looking, and whether you actually need one at all.

What CSS preprocessors are

A preprocessor is a language that sits on top of CSS. You write in its syntax. It compiles down to ordinary CSS that a client can read. The browser, or the email client, never touches the source file. It only ever sees the compiled output.

The point is to make CSS less repetitive. Plain CSS has no variables you can reuse across a file. It has no logic. It makes you type the same hex code in forty places. CSS preprocessors fix that with four core features.

  • Variables. Store a brand colour once, reference it everywhere.
  • Nesting. Write related rules inside each other instead of repeating selectors.
  • Mixins. Bundle a chunk of styles and reuse it like a function.
  • Functions and math. Lighten a colour, do arithmetic on spacing, generate values.

Here is the smallest taste of it in SCSS, the most common syntax.

$brand: #286dbd;

@mixin button($bg) {
  background: $bg;
  color: #ffffff;
  border-radius: 6px;
}

.cta {
  @include button($brand);
}

That compiles to plain CSS with the colour baked in. Three CSS preprocessors matter in practice. Sass leads by a wide margin. Less and Stylus trail behind it. Most people who say “preprocessor” mean Sass, and specifically the SCSS flavour, which looks almost exactly like normal CSS.

Why CSS preprocessors only do half the job in email

This is the part generic guides skip, and it is the whole reason this page exists.

A preprocessor compiles your styles into a <style> block. On a website that block lives in the <head> and works fine. In email it often does not survive the trip. Gmail strips large parts of the head in plenty of contexts. Classic Outlook ignores big chunks of CSS outright. So your carefully compiled rules can vanish before a subscriber sees a thing.

The missing piece is a CSS inliner.

An inliner takes your compiled CSS and moves each rule directly onto the element, as a style attribute. So .cta { background: #286dbd } becomes <td style="background:#286dbd">. That inlined version is what email clients actually respect. The real email pipeline is not one step. It is four.

  1. Write in a preprocessor (Sass, Less, Stylus).
  2. Compile to plain CSS.
  3. Inline that CSS onto the HTML elements.
  4. Purge unused rules and minify.

The two best-known inliners are Juice and Premailer. Without one of them in the chain, CSS preprocessors save you typing and nothing else. The styles compile. They look great in your editor. Then half your list opens the email and sees naked HTML. This trips up nearly every beginner. The preprocessor is a writing convenience. The inliner is what makes it render. Treat them as two halves of one job, not as the same thing.

A preprocessor with no inliner behind it is busywork. It tidies your source and changes nothing in the inbox.

Sass, Less and Stylus in email

Sass is the default, and it is not close. The ecosystem is bigger. The tooling is better maintained. SCSS syntax is a near-perfect superset of CSS, so the learning curve is gentle.

Less and Stylus still exist. Less had a moment years ago, tied to older framework stacks. Stylus is leaner and stranger, with optional braces and semicolons. Both work. Both are minor characters now. For email work in 2026, picking anything other than Sass means swimming against the current for no real gain.

A stale-tooling warning worth pinning

Here is a trap that catches people following old tutorials.

For years the way to compile Sass was a package called node-sass. It wrapped a C library called LibSass. Both are dead now. node-sass is deprecated and LibSass is no longer maintained. If a guide tells you to run npm install node-sass, that guide is stale.

The current, supported implementation is Dart Sass, installed as the plain sass package.

npm install sass

This matters more than it sounds. node-sass froze in time and never got newer Sass features. Worse, it ties you to specific old Node versions that break on modern machines. Anyone still teaching it is teaching 2018. So among CSS preprocessors, the language is healthy, but the compiler you reach for has changed under everyone’s feet.

The Sass @import deprecation nobody warns you about

This is fresh, it is real, and almost no email-specific page mentions it yet.

For a decade, Sass files were stitched together with @import. You split styles into partials, then pulled them in. That pattern is now on death row.

As of Dart Sass 1.80.0, released in October 2024, @import is officially deprecated. It is scheduled for removal in Dart Sass 3.0.0. The Sass team is replacing it with a proper module system built on two rules: @use and @forward.

The difference looks small and behaves very differently.

// old, deprecated
@import 'variables';
body { color: $brand; }

// new module system
@use 'variables' as vars;
body { color: vars.$brand; }

The new approach scopes things. Variables and mixins no longer leak globally. Names stop colliding. The same file never gets compiled twice into bloated output.

Why email developers should care

Plenty of email Sass setups were built on @import partials. So were the starter kits for several older frameworks. Those builds now throw deprecation warnings on every compile. Soon, when 3.0.0 lands, they will throw errors instead.

The fix is mercifully short. Sass ships a migration tool.

sass-migrator module --migrate-deps path/to/style.scss

Run it, check the diff, commit. A freelancer who hands you a build full of @import warnings is handing you a clock that is ticking. With CSS preprocessors, this is the maintenance chore of the moment. Ignore it and a future Sass upgrade simply stops working.

Frameworks that do the preprocessing for you

Most people never wire up Sass and an inliner by hand. They reach for a framework that bundles the whole pipeline. Three are worth knowing in 2026. Their current status matters, because two of them changed a lot and one of them died.

MJML

MJML is an engine from Mailjet. You write semantic tags like <mj-section> and <mj-column>. It transpiles them into nested-table HTML with inline CSS already applied. It is actively maintained and widely used.

A few honest caveats. MJML is not a Sass tool out of the box. You style through <mj-style>, or through reusable mj-attributes and mj-class defaults. If you want real Sass with it, you add a separate Sass compile step in your own build. And the column model has its own rules: columns inside a section auto-distribute their width – two split to 50% each, three to a third, four to a quarter – and you can override that with explicit widths. The real constraints are structural rather than a column count. A column cannot nest another column or section, and every column has to hold something. For most layouts none of that bites.

MJML is the framework to pick when you want responsive output and would rather not think about tables ever again.

Maizzle

Maizzle is the modern option, and it moved fast. It now runs on Vue and Tailwind CSS, with PostCSS under the hood. It uses Juice for CSS inlining and email-comb to purge unused styles. You get a live-preview dev server, modern build tooling, and dark-mode support out of the box. The project is current and shipping through 2026.

Now, a fair clarification. Tailwind is a utility framework on PostCSS, not a Sass-style preprocessor in the strict sense. But for email it fills the same slot. You write tokens, it compiles, it inlines. So when people lump Tailwind in with CSS preprocessors, they blur a real line. The workflow overlap is genuine, though.

Maizzle suits teams who already live in Tailwind and want a proper modern build.

Foundation for emails (and why it is a trap now)

Foundation for Emails was a beloved framework for years. It paired Sass with the Inky templating language, where you wrote <row> and <columns> instead of table soup. It auto-inlined your CSS. Thousands of people built on it.

That era is over.

Foundation for Emails is now archived and no longer maintained. ZURB’s plan folds it into a ground-up rewrite called Inky 2, built in Rust. It ships as a single binary, with bindings for Node, PHP, Python, Ruby and Go.

The old starter even pins Node.js to version 10 or lower. That alone tells you how frozen it became. So if a 2026 tutorial says “just use Foundation for Emails,” it is pointing you at a museum. Keep an eye on Inky 2 as it matures. Do not bet a launch on a half-shipped rewrite either. For new work right now, MJML or Maizzle is the safer call.

When CSS preprocessors earn their place

The tooling is real, but it is not always worth it. The skill is knowing when to reach for CSS preprocessors and when to leave them on the shelf.

Reach for one when

  • You maintain a library of emails and want shared variables and components.
  • Brand colours and spacing repeat everywhere, and hand-editing causes mistakes.
  • A whole team touches the same templates, and mixins enforce consistency.
  • You are building a real system, not a single message.

That first case is the strongest. If you ship dozens of emails a month, CSS preprocessors keep your styling sane. Change one variable, every template updates.

Skip it when

  • You are sending one email, once. The build overhead is not worth it.
  • You are not also setting up inlining. Then the preprocessor does nothing useful.
  • You run a small shop and a hosted ESP builder would serve you faster.

There is no shame in skipping the toolchain. A solo store owner does not need a Vue build to send a sale announcement. CSS preprocessors reward scale and repetition. For a one-off, hand-coded HTML or a drag-and-drop builder is often the smarter move. The honest answer depends on volume, not fashion.

CSS Preprocessors vs framework vs hand-coding

People conflate these three constantly. They are not the same choice. Each one fits a different situation.

ApproachStrengthsWeaknessesBest for
Raw Sass plus an inlinerFull control, reusable tokensYou wire the whole pipeline yourselfDevelopers with an existing build
Framework (MJML, Maizzle)Pipeline and responsiveness solvedYou learn its syntax and lose some controlTeams and recurring templates
Hand-coded HTML and CSSNo tooling, total controlVerbose and error-prone at scaleOne-offs and learning

The middle row is where most working teams land. A framework hands you CSS preprocessors, inlining and table generation in one package. You give up a little control. You gain a lot of speed. For senders shipping regularly, that trade almost always pays off.

CSS preprocessors: common mistakes (and how testing catches them)

These are the patterns that bite, over and over.

  • Forgetting to inline. Compiled CSS that Gmail throws straight in the bin.
  • Still running node-sass. A dead compiler that breaks on modern Node.
  • Building on @import. Deprecation warnings today, hard errors after Dart Sass 3.0.0.
  • Starting fresh on Foundation for Emails. An archived framework pinned to Node 10.
  • Over-abstracting. A mixin maze that nobody on the team can read six months later.
  • Trusting one preview. Your inbox is not forty inboxes.

That last one is the real killer. You cannot eyeball compiled-and-inlined output across every client by hand. The styles look fine in your editor. Then one client mangles them and you find out from a customer.

A note on testing tools

Testing platforms preview your email across dozens of real clients and flag the breakage before send. Two things shifted recently, so old advice misleads.

Litmus changed its pricing hard after the Validity acquisition. As of 2026 the Core plan starts at $500 per month, covering 5 users and 2,000 previews. The cheap old tiers are gone. Email on Acid, now under Sinch, is the more budget-friendly competitor, and a lot of small shops moved there. One more, since people still ask: Putsmail, the old free send-a-test tool, is no longer available. If a tutorial points you to it, the tutorial is stale.

Whatever you choose, test the compiled output, not the source. The bug always hides in a client you skipped.

CSS preprocessors and the next five years

Nobody owns a crystal ball, but the direction is fairly clear. Worth mapping, because building for today without an eye on the timeline is how you redo everything in 2028.

  • 2026 to 2027. Sass stays dominant. The @use migration becomes non-negotiable as Dart Sass 3.0.0 approaches. Maizzle and Tailwind keep rising. Classic Foundation for Emails fully fades from new projects.
  • 2027 to 2028. The new Outlook for Windows spreads. It runs a Chromium-style engine with real CSS support. Microsoft pushed its enterprise opt-out to March 2027, so this is gradual. More standard CSS means slightly less reliance on heavy table-generating frameworks.
  • 2028 to 2029. Classic Outlook support runs to at least 2029. If it genuinely winds down, leaner output gets safer. The job of CSS preprocessors shifts from “survive Outlook” toward “stay maintainable”.

One thing does not change across any of it. Whatever compiles your styles, inlining and real-client testing never stop mattering. The new Outlook arriving does not retire the inliner. Legacy clients persist for years. So the pipeline survives even as the rendering engines improve.

There is also a quieter shift in the tooling itself. Tailwind has moved toward CSS-first configuration. That blurs the old line between a preprocessor and a framework. The label “CSS preprocessors” is slowly stretching to mean the whole compile-and-inline build, not just Sass. That is fine. The underlying job – clean source in, inbox-safe HTML out – stays exactly the same.

Frequently asked questions

What is a CSS preprocessors in email development?

A CSS preprocessor is a language like Sass. It extends CSS with variables, nesting and mixins, then compiles to plain CSS. In email, CSS preprocessors keep styles maintainable across many templates. They only become useful when a CSS inliner runs after them, because most email clients need inline styles.

Do I need Sass to build HTML emails?

No. Plain HTML and CSS, plus an inliner, will get an email out the door. Sass is a convenience that pays off at scale. If you ship many emails, CSS preprocessors save real time. For a single message, they are usually overkill.

Why doesn’t my compiled CSS show up in Gmail?

Because Gmail strips much of the <style> block, and your compiled rules live there. The fix is inlining. A CSS inliner like Juice or Premailer moves each rule onto the element as a style attribute. That inlined version is what Gmail and Outlook actually respect.

Is MJML a CSS preprocessor?

Not in the strict sense. MJML is a templating and transpiling engine, not a Sass-style preprocessor. It turns its own tags into nested-table HTML with inline CSS. It overlaps with CSS preprocessors because it handles compiling and inlining for you, but the mechanism is different.

Is Foundation for emails still usable in 2026?

It still runs, but it is archived and no longer maintained. ZURB is replacing it with a Rust rewrite called Inky 2. The old starter is pinned to Node.js 10. For new projects, MJML or Maizzle is the better choice today.

What is replacing @import in Sass?

The module system, built on @use and @forward. As of Dart Sass 1.80.0, @import is deprecated and headed for removal in Dart Sass 3.0.0. Sass provides a migration tool, sass-migrator, that converts most old code automatically.

Sass or Tailwind for email – which one?

They solve overlapping problems differently. Use Tailwind, usually through Maizzle, if you want utility classes and a modern build. Use Sass if you prefer classic variables, mixins and a familiar SCSS syntax. Both count, loosely, as CSS preprocessors in the email workflow.

Key takeaways about CSS preprocessors

  • CSS preprocessors (Sass, Less, Stylus) add variables, mixins and logic, then compile to plain CSS.
  • In email a preprocessor is only half the pipeline. Without a CSS inliner, Gmail and Outlook discard your styles.
  • node-sass is dead and Sass @import is deprecated. Use Dart Sass and the @use module system.
  • Foundation for Emails is archived in 2026. MJML and Maizzle are the live framework options.
  • Use CSS preprocessors for systems and teams. Skip them for one-off sends.
  • Whatever compiles your CSS, inlining and real-client testing never stop mattering.

CSS preprocessors are not magic in email. They are a writing tool that needs an inliner standing right behind them to mean anything in an inbox. Pick a maintained compiler, migrate off @import, leave the archived frameworks alone, and test the output on real clients. Do that and the toolchain works for you instead of rotting under you. The labels keep shifting. The job – clean code in, inbox-safe HTML out – does not.

« Back to Glossary Index
Published byPavel Ivanov
HTML Email Developer with deep expertise in building production-ready, cross-client templates for global audiences. Skilled at solving edge-case rendering issues (e.g., Gmail on iOS dark mode, legacy Outlook) and implementing robust fallbacks for gradients, background images, and custom layouts. Strong QA mindset with extensive Litmus/EoA testing practice and a clean, maintainable code style. Reliable partner for marketing teams: fast iterations, clear communication, and consistent delivery across multi-language campaigns (incl. 19+ locales).