Layers stack in the order they were first defined,
with un-layered styles at the bottom,
and the last layer at the top.
Selectors inside the components layer here,
will take priority over all the otherlayers.
@layer default{/* … */} @layer theme{/* … */}
/* still a lower layer than "theme" styles */ @layer default{/* … */}
But we don’t need to keep all our layered styles in that same order.
The layer priority is based on when a layer name firstappears.
So we can even establish our desired layer order up-front,
by using the layer rule without any styles –
just a layer name or list of names.
Once they’re established,
we can add to those layers in any order,
and our code will slot intoplace.
@layer tools{ @layer theme{ /* tools.theme */ } }
@layer tools.theme{/* tools.theme */}
We can also nest layers as needed –
and reference nested layers directly with a dotnotation.
@layer{/* anonymous */}
Or create anonymous layers
that are maintained in a singlelocation.
The next feature is also about how selectors work.
With “scope”,
we’re trying to address two closely related issues
that come up regularly,
and drive people to use tools & conventions
like BEM syntax orCSS-in-JS.
1. AvoidNaming Conflicts
(across large teams&projects)
The first goal is to avoid
naming conflicts as our projectsgrow.
2. By
Expressing Membership
(through lower boundaries&proximity)
Which we can solve
by focusing on our second goal:
expressing “membership” or “ownership”
in ourselectors.
.title{/* global */} .post .title{/* nested */}
While nested selectors
might seem like a way to
express membership –
in this case
a title that is inside a post–
.title{/* global */} .post .title{/* nested */}
.post__title{/* BEM */}
That’s not quite the same thing
as a post-title.
The first one only describes a nested structure,
but the second describes
a more clear membership in a component pattern.
Not all the titles in a post,
just the title that belongs to thepost.
Another way to think about this is
to say that some components
have lower boundaries.
The component itself is a “donut”
with a slot in the middle for content.
We should be able to style these donut compontents,
without worrying that we might accidentally
style everything inside them bymistake.
There are some similarities
between scope and shadow-DOMencapsulation.
But Shadow boundaries are defined in the DOM,
so that each element has a single scope,
and styles are strongly isolated from getting in or out.
They never allowed to overlap atall.
Where scopes are defined entirely in CSS –
more fluid,
able to overlap,
and integrate more smoothly
with global designsystems.
@scope(.media) to (.content){ img{/* only images that are "in scope" */} }
The current proposal uses an at-scope rule,
which accepts both a scope-root selector
(in this case media)
and a lower-boundary selector
(in this case content).
Any selectors inside the at-rule
only match elements between a matched
root element and any lower-boundarydescendants.
We’re also considering how
scope proximity might become part of the cascade.
When two styles have the same specificity
we could give priority to the “closer” scope-root
before falling back tosource-order.
@scope(.media) to (.content){ img{border: red;} }
/* as a selector, without proximity rules? */ img:in(.media / .content){border: red;}
There has also been talk about adding
some form of lower-boundary or donut selector syntax,
to write more targeted selectors
without the at-rule or proximityweighting.
Same element in multiple containers,
viewport isn’tuseful
Respond to containersinstead
Layout Loops
CSSContext vs Content
But this type of query could lead to an infinite layoutloop.
.container{ contain: size layout style; }
So the first thing we need to do
is define our containers –
any element the we want to query –
and turn off content-based sizing
on thoseelements.
We can do something similar with the contain property,
but the current options are a little tooheavy-handed.
.container{ contain: inline-size; }
We usually want to contain only the width of an element,
or the inline-dimension,
and allow the height or block dimension to grow and shrink
with the content.
This isn’t entirely solved, yet,
but we have a prototype,
and we’re confident that there’s a pathforward.
And then any element can query the container it is in –
its nearest ancestor that’s been defined as a container.
This container-query looks exactly like a media-query,
but with at-container instead ofat-media.
Max Böck has created this bookstore demo
with self-contained web components.
Each host element is a container,
and everything inside the component
adjusts based on availablesize.
More to do…
Container Units
qw | qh | qi | qb | qmin | qmax
We’re also working on container-relative units,
similar to vw, vh, vmin, vmax,
but a percentage of the container size
rather than theviewport.
These are also supported in
the Chrome Canary prototype.
Here’s a demo from Scott Kellum
showing query units inaction.
@containerproperty(--colors == invert){ … }
We’re also working on queries
that aren’t about the container size.
The exact syntax is not established yet,
but we might be able to query the actual value
of a property–
@containerstate(is-stuck){ … }
Or the current state of a container.
Is it position-sticky, and currently in a “stuck”state?
This is an editor’s draft,
just waiting on the details of single-axis containment
before we move it to First Public Working Draft,
and start looking for moreimplementations.
All of these features are designed to work together,
building on the existing features of CSS.
we’re excited to see what people build with these new tools,
and always eager to getfeedback.