CSS @import vs link: The Debate That CSS Layers Resurrected
My 2015 Stack Overflow question about including stylesheets had a clear answer: use link. In 2026, @import found a new purpose with @layer.
CSS @import vs link: The Debate That CSS Layers Resurrected
In 2015, I asked a question on Stack Overflow in Portuguese about the difference between @import and <link> for including CSS files. It scored 12 upvotes. The answer was unanimous: don’t use @import.
The 2015 Answer: @import Is Slow
The problem was waterfalling. A <link> tag lets the browser discover all stylesheets in parallel by scanning the HTML. But @import hides dependencies inside CSS files — the browser can’t find them until it downloads and parses the parent stylesheet.
<!-- Good: browser discovers both in one HTML parse -->
<link rel="stylesheet" href="reset.css" />
<link rel="stylesheet" href="main.css" />
/* Bad: browser discovers reset.css only after downloading main.css */
@import url('reset.css');
/* ... rest of main.css */
Steve Souders called @import one of the worst CSS performance practices. The advice was simple: always use <link>.
The 2026 Plot Twist: @import and @layer
CSS Cascade Layers changed the equation. The @layer feature lets you define explicit cascade priorities, and @import is how you assign external files to layers:
/* Import third-party styles into a low-priority layer */
@import url('vendor/normalize.css') layer(reset);
@import url('vendor/component-library.css') layer(components);
/* Your styles automatically win over layered imports */
@layer reset, components, custom;
.button {
/* This always overrides component-library styles,
regardless of specificity */
background: var(--color-neon);
}
You can’t do this with <link> tags alone. While there’s a layer attribute proposal for <link>, @import with layer() is the established pattern in 2026.
But Bundlers Make It Moot
In production, build tools (Vite, Lightning CSS, PostCSS) resolve @import statements at build time, inlining everything into a single file. The waterfall problem disappears because there’s nothing to waterfall — it’s all one file.
/* In development: readable @import chains */
@import url('./tokens.css') layer(tokens);
@import url('./reset.css') layer(reset);
@import url('./components.css') layer(components);
/* In production: bundled into one file, zero extra requests */
When to Use Each in 2026
| Method | Use when |
|---|---|
<link> | Loading independent stylesheets that don’t need layer ordering |
@import with layer() | Controlling cascade priority of external CSS |
| Bundler imports | Always in production (automatic) |
Key Takeaway
In 2015, @import was a performance mistake. In 2026, it’s a cascade management tool — when paired with @layer. The performance concern is valid but academic: bundlers inline everything in production anyway. The real question shifted from “how to load CSS” to “how to control the cascade.”
Related Posts
CSS @import vs link: The Debate That CSS Layers Resurrected
My 2015 Stack Overflow question about including stylesheets had a clear answer: use link. In 2026, @import found a new purpose with @layer.
CSS Preprocessors in 2026: Sass vs Less vs Stylus — Do You Still Need Them?
A Stack Overflow question from 2015 asked about Sass vs Less vs Stylus. In 2026, native CSS has caught up. Here is what changed and when preprocessors still make sense.
CSS word-wrap and Text Overflow: From Hack to Standard
My 2015 Stack Overflow answer used word-wrap: break-word as a quick fix. In 2026, CSS handles text overflow with elegance and intelligence.