skip to content

How do you load a third-party stylesheet into its own cascade layer using CSS @import, and where must that rule appear in the file?

level: seniorimportance: should knowfreq 25%

answer

  1. layer() rides on the import
  2. a bare layer keyword means anonymous
  3. imports go at the very top
  4. only @charset and layer statements above
  5. costs one extra round trip

basics

~20 s

Write @import url("vendor.css") layer(vendor); which places every rule from that file into the vendor layer. The @import must come before all other rules except @charset and @layer ordering statements, so it sits at the very top of the stylesheet.

solid answer

~50 s

`@import` takes an optional `layer()` function: `@import url("vendor.css") layer(vendor);` puts every rule in that file into the `vendor` layer, which is the standard way to tame CSS you did not write. A bare `layer` keyword with no parentheses drops it into an anonymous layer instead. Placement is constrained — `@import` rules must precede all other rules in a stylesheet, with only `@charset` and `@layer` ordering statements allowed before them, so the normal entry file looks like the layer statement first, then the imports. You can also add a `supports()` condition and a media query after the layer, in that order. The one caveat worth raising unprompted is that `@import` fetches serially, so a vendor sheet imported this way is discovered later than a directly linked one; when that matters, teams do the layering in their build instead.

code

css · 9 lines
css
@layer reset, vendor, base, components, utilities;

@import url("reset.css") layer(reset);
@import url("vendor/datepicker.css") layer(vendor);
@import url("grid.css") layer(vendor) supports(display: grid) screen and (min-width: 40em);

@layer components {
  .datepicker { border-radius: 0; }
}

go deeper

for a junior

Be able to write the line: @import url("vendor.css") layer(vendor); and say that every rule in that file lands in the vendor layer.

for a middle

Explain the placement rule — imports before all other rules, with only @charset and @layer statements above them — and why the layer-statement exception exists.

for a senior

Show the full pattern on a real integration: order statement, vendor sheet into an early layer, your components later, plus the serial-fetch cost and when you would move the layering into the build instead.

for a principal

Own the integration policy: which third-party CSS is allowed in the bundle, which layer it lands in, and how the ordering statement is governed so a new dependency cannot quietly become the strongest source of styles.

## The mechanism CSS you did not author is the main reason cascade layers exist, and `@import` is the hook that lets you assign such a file a layer without editing it: ```css @layer reset, vendor, base, components, utilities; @import url("reset.css") layer(reset); @import url("vendor/datepicker.css") layer(vendor); ``` Every rule inside `datepicker.css` now behaves as though it were written inside `@layer vendor { ... }`. Since `vendor` is ordered near the start, your `components` rules beat it on layer order alone — no specificity escalation, no `!important`, and the vendor file itself is untouched so it can be upgraded freely. This matters specifically because unlayered CSS outranks every layer: a vendor sheet left unlayered would beat your layered components no matter how specific your selectors were. Importing it into an early layer is what puts it back under your control. ## The full syntax The optional pieces come in a fixed order after the URL: ```css @import url("grid.css") layer(vendor) supports(display: grid) screen and (min-width: 40em); ``` - `layer(name)` — a named layer, which can be reopened and ordered explicitly. - `layer` — the bare keyword, creating an anonymous layer that nothing can reference or extend afterwards. Use it only for a file you are certain nobody will need to append to. - `supports(...)` — imports the file only if the condition holds. - A media query — imports only for matching conditions. The URL can also be written as a bare string, `@import "vendor.css" layer(vendor);`. ## Placement rules `@import` rules must come before every other rule in the stylesheet. The only things allowed above them are `@charset` and `@layer` ordering **statements** — the semicolon form that just names layers. This exception is deliberate: it exists precisely so you can fix the layer order before importing anything into those layers. ```css @layer reset, vendor, base, components; /* allowed above @import */ @import url("vendor.css") layer(vendor); .page { margin: 0; } /* any @import after this is ignored */ ``` An `@import` placed after a normal rule is simply dropped, silently, and the file never loads — a failure that looks like "the vendor styles disappeared" rather than a syntax error. An `@import` nested inside a `@layer { ... }` block is invalid for the same reason; you express that with `layer()` on the import instead. ## Strict ordering is not required Because layer order comes from first mention, the imports themselves may appear in any sequence once the ordering statement exists. This is useful with bundlers and with code-split CSS: whichever chunk loads first, the precedence is whatever the statement said. Without the statement, the layer order would follow the import order, and you would be back to caring about build output. ## The cost, stated honestly `@import` inside a stylesheet is discovered only after that stylesheet has been fetched and parsed, so the imported file starts downloading a round trip later than a directly referenced one. On a critical-path stylesheet that is a real delay, and it is the standard argument against building an entire architecture out of `@import`. Two common responses: use `@import ... layer()` only for a handful of third-party files whose loading is not critical, or have the build concatenate the files and wrap each one in `@layer name { ... }` at bundle time, which produces the same cascade result with a single request. Anything beyond that tradeoff is performance-strategy territory. ## What you cannot do from markup There is no widely supported way to attach a layer to a stylesheet referenced directly from the document, so a CSS entry file that imports the vendor sheet is the usual route when you need the layer assignment at runtime rather than at build time. ## Checklist for the answer 1. `@import url("x.css") layer(name);` — layered import. 2. Ordering statement above the imports so precedence is explicit. 3. Imports first in the file; only `@charset` and `@layer` statements may precede them. 4. Optional `supports()` and media query, in that order, after the layer. 5. Mention the serial-fetch cost and the build-time alternative.

  • What happens to an @import that appears after a normal style rule?
    It is invalid and ignored, so the file never loads and its styles are silently missing. Only `@charset` and `@layer` ordering statements are permitted above `@import` rules — the layer-statement exception exists specifically so you can fix layer order before importing into those layers. The symptom is missing styles rather than a parse error, which makes it easy to misdiagnose.
  • What is the difference between layer(name) and the bare layer keyword on an @import?
    `layer(name)` puts the file into a named layer that can be ordered explicitly in a `@layer` statement, reopened, and appended to later. The bare `layer` keyword creates an anonymous layer at that position — the rules are still layered, but nothing can ever reference, reorder, or extend that layer, so it is only appropriate for a self-contained file.
  • Why might a team avoid @import for layering and do it at build time instead?
    An `@import` is discovered only after the importing stylesheet is fetched and parsed, so the imported file starts downloading a round trip later. Wrapping each source file in `@layer name { ... }` during the build produces the same cascade result in one request. The `@import` form is usually reserved for a few third-party files, or for cases where the layering must happen at runtime.

saying these in an interview costs you the question

  • Writes @import inside a @layer block and expects it to work
  • Puts @import rules after other style rules
  • Thinks layer() must precede the url in the @import
  • Assumes a vendor sheet must be edited to be layered
  • Believes @import costs nothing because it is CSS-native

context