@scope
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Die @scope
CSS At-Regel ermöglicht es Ihnen, Elemente in bestimmten DOM-Unterbäumen auszuwählen. Damit können Sie Elemente gezielt ansprechen, ohne übermäßig spezifische Selektoren schreiben zu müssen, die schwer zu überschreiben sind, und ohne Ihre Selektoren zu eng an die DOM-Struktur zu koppeln.
In JavaScript kann auf @scope
über die CSS-Objektmodell-Schnittstelle CSSScopeRule
zugegriffen werden.
Syntax
Die @scope
-At-Regel enthält eine oder mehrere Regelsätze (bezeichnet als scoped style rules) und definiert einen Bereich, in dem diese auf ausgewählte Elemente angewendet werden. @scope
kann auf zwei Arten verwendet werden:
-
Als eigenständiger Block in Ihrem CSS, wobei es einen Präludium-Abschnitt gibt, der Scope-Root- und optionale Scope-Limit-Selektoren enthält — diese definieren die oberen und unteren Grenzen des Umfangs.
css@scope (scope root) to (scope limit) { rulesets }
-
Als Inline-Stile innerhalb eines
<style>
-Elements in Ihrem HTML, wobei das Präludium weggelassen wird und der eingeschlossene Regelsatz automatisch auf das umschließende übergeordnete Element des<style>
-Elements angewendet wird.html<parent-element> <style> @scope { rulesets } </style> </parent-element>
Es ist auch möglich, ein Inline-
@scope
mit einem Scope-Limit-Selektor zu kombinieren, wie in@scope to (scope limit) { ... }
.
Beschreibung
Ein komplexes Webdokument könnte Komponenten wie Header, Footer, Nachrichtenartikel, Karten, Medien-Player, Anzeigen und andere enthalten. Mit zunehmender Komplexität wird das effektive Management des Stylings für diese Komponenten zu einer größeren Herausforderung, und eine effektive Eingrenzung der Stile hilft uns, diese Komplexität zu bewältigen. Betrachten wir den folgenden DOM-Baum:
body └─ article.feature ├─ section.article-hero │ ├─ h2 │ └─ img │ ├─ section.article-body │ ├─ h3 │ ├─ p │ ├─ img │ ├─ p │ └─ figure │ ├─ img │ └─ figcaption │ └─ footer ├─ p └─ img
Wenn Sie das <img>
-Element innerhalb des <section>
mit der Klasse article-body
auswählen wollten, könnten Sie Folgendes tun:
- Einen Selektor wie
.feature > .article-body > img
schreiben. Das hat jedoch eine hohe Spezifität und ist schwer zu überschreiben, zudem ist es stark an die DOM-Struktur gebunden. Wenn sich Ihre Markup-Struktur in Zukunft ändert, müssten Sie möglicherweise Ihr CSS neu schreiben. - Etwas weniger Spezifisches wie
.article-body img
schreiben. Das würde jedoch alle Bilder innerhalb dessection
auswählen.
Hier ist @scope
nützlich. Es ermöglicht Ihnen, einen präzisen Bereich zu definieren, innerhalb dessen Ihre Selektoren Elemente ansprechen können. Zum Beispiel könnten Sie das oben genannte Problem mit einem eigenständigen @scope
-Block wie folgt lösen:
@scope (.article-body) to (figure) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Der Scope-Root-Selektor .article-body
definiert die obere Grenze des DOM-Baum-Bereichs, in dem der Regelsatz angewendet wird, und der Scope-Limit-Selektor figure
definiert die untere Grenze. Infolgedessen werden nur <img>
-Elemente innerhalb eines <section>
mit einer Klasse article-body
, aber nicht innerhalb von <figure>
-Elementen ausgewählt.
Hinweis: Diese Art der Eingrenzung – mit einer oberen und einer unteren Grenze – wird allgemein als Donut-Bereich bezeichnet.
Die obere Grenze eines Bereichs ist inklusiv und die untere Grenze exklusiv. Um dieses Verhalten zu ändern, können Sie entweder den Selektor mit einem universellen Kind-Selektor kombinieren. Zum Beispiel würde @scope (scope root) to (scope limit > *)
beide Grenzen inklusiv machen, @scope (scope root > *) to (scope limit)
würde beide Grenzen exklusiv machen, während @scope (scope root > *) to (scope limit > *)
eine exklusive obere Grenze und eine inklusive untere Grenze geben würde.
Wenn Sie alle Bilder innerhalb eines <section>
mit einer Klasse article-body
auswählen möchten, können Sie das Scope-Limit weglassen:
@scope (.article-body) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Oder Sie könnten Ihren @scope
-Block inline innerhalb eines <style>
-Elements einfügen, das wiederum innerhalb eines <section>
mit einer Klasse article-body
ist:
<section class="article-body">
<style>
@scope {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
</style>
<!-- ... -->
</section>
Hinweis:
Es ist wichtig zu verstehen, dass @scope
, obwohl es Ihnen ermöglicht, die Anwendung von Selektoren auf bestimmte DOM-Unterbäume zu isolieren, die angewendeten Stile nicht vollständig auf diese Unterbäume beschränkt. Dies ist am auffälligsten bei der Vererbung – Eigenschaften, die von Kindern geerbt werden (zum Beispiel color
oder font-family
), werden über die festgelegte Bereichsgrenze hinaus vererbt.
Die :scope
Pseudoklasse
Im Kontext eines @scope
-Blocks repräsentiert die :scope
Pseudoklasse die Scope-Root – sie bietet eine einfache Möglichkeit, Stile auf das Scope-Root selbst anzuwenden, von innen heraus:
@scope (.feature) {
:scope {
background: rebeccapurple;
color: antiquewhite;
font-family: sans-serif;
}
}
In der Tat wird :scope
implizit allen scopen Style-Regeln vorangestellt. Wenn Sie möchten, können Sie :scope
explizit voranstellen oder den Nesting-Selektor (&
) voranstellen, um denselben Effekt zu erzielen, wenn Sie diese Darstellungen leichter verständlich finden.
Die drei Regeln im folgenden Block sind alle gleichwertig in dem, was sie auswählen:
@scope (.feature) {
img { ... }
:scope img { ... }
& img { ... }
}
Hinweise zur Nutzung von scopen Selektoren
-
Ein Scope-Limit kann
:scope
verwenden, um eine spezifische Beziehungsanforderung zwischen dem Scope-Limit und dem Root festzulegen. Zum Beispiel:css/* figure is only a limit when it is a direct child of the :scope */ @scope (.article-body) to (:scope > figure) { ... }
-
Ein Scope-Limit kann auf Elemente außerhalb des Scope-Roots unter Verwendung von
:scope
verweisen. Zum Beispiel:css/* figure is only a limit when the :scope is inside .feature */ @scope (.article-body) to (.feature :scope figure) { ... }
-
Scopen Style-Regeln können den Unterbaum nicht verlassen. Selektionen wie
:scope + p
sind ungültig, da diese Auswahl außerhalb des Unterbaums wäre. -
Es ist vollkommen gültig, das Scope-Root und das Limit als Selektorliste zu definieren, in diesem Fall werden mehrere Bereiche definiert. Im folgenden Beispiel werden die Stile auf jedes
<img>
innerhalb eines<section>
mit einer Klassearticle-hero
oderarticle-body
angewendet, jedoch nicht, wenn es innerhalb eines<figure>
verschachtelt ist:css@scope (.article-hero, .article-body) to (figure) { img { border: 5px solid black; background-color: goldenrod; } }
Spezifität in @scope
Das Einfügen eines Regelsatzes in einen @scope
-Block beeinflusst nicht die Spezifität seines Selektors, unabhängig von den Selektoren, die innerhalb des Scope-Roots und -Limits verwendet werden. Zum Beispiel:
@scope (.article-body) {
/* img has a specificity of 0-0-1, as expected */
img { ... }
}
Wenn Sie sich jedoch dafür entscheiden, die :scope
Pseudoklasse explizit vor Ihre scopen Selektoren zu stellen, müssen Sie diese berücksichtigen, wenn Sie deren Spezifität berechnen. :scope
, wie alle regulären Pseudoklassen, hat eine Spezifität von 0-1-0. Zum Beispiel:
@scope (.article-body) {
/* :scope img has a specificity of 0-1-0 + 0-0-1 = 0-1-1 */
:scope img { ... }
}
Wenn Sie den &
-Selektor innerhalb eines @scope
-Blocks verwenden, stellt &
den Scope-Root-Selektor dar; er wird intern als dieser Selektor innerhalb einer :is()
Pseudoklasse-Funktion berechnet. Zum Beispiel in:
@scope (figure, #primary) {
& img { ... }
}
& img
ist äquivalent zu :is(figure, #primary) img
. Da :is()
die Spezifität seines spezifischsten Arguments übernimmt (#primary
in diesem Fall), beträgt die Spezifität des scopen & img
-Selektors daher 1-0-0 + 0-0-1 = 1-0-1.
Der Unterschied zwischen :scope
und &
innerhalb von @scope
:scope
repräsentiert das übereinstimmende Scope-Root, während &
den Selektor darstellt, der verwendet wird, um das Scope-Root zu matchen. Daher ist es möglich, &
mehrmals zu verketten. Sie können jedoch :scope
nur einmal verwenden – Sie können nicht ein Scope-Root innerhalb eines Scope-Roots matchen.
@scope (.feature) {
/* Selects a .feature inside the matched root .feature */
& & { ... }
/* Doesn't work */
:scope :scope { ... }
}
Wie @scope
-Konflikte gelöst werden
@scope
fügt ein neues Kriterium zur CSS Cascade hinzu: Scoping-Nähe. Dies besagt, dass wenn zwei Scopes widersprüchliche Stile haben, der Stil angewendet wird, der die geringste Anzahl von Sprüngen in der DOM-Baum-Hierarchie bis zum Scope-Root hat. Schauen wir uns ein Beispiel an, um zu sehen, was das bedeutet.
Nehmen Sie den folgenden HTML-Schnipsel, bei dem unterschiedlich gestaltete Karten ineinander verschachtelt sind:
<div class="light-theme">
<p>Light theme text</p>
<div class="dark-theme">
<p>Dark theme text</p>
<div class="light-theme">
<p>Light theme text</p>
</div>
</div>
</div>
Wenn Sie das Thema-CSS so schreiben, laufen Sie in Schwierigkeiten:
.light-theme {
background: #ccc;
}
.dark-theme {
background: #333;
}
.light-theme p {
color: black;
}
.dark-theme p {
color: white;
}
Der innerste Absatz sollte schwarz gefärbt sein, da er sich in einer lichtthematischen Karte befindet. Er wird jedoch sowohl von .light-theme p
als auch von .dark-theme p
angesprochen. Da die Regel .dark-theme p
später in der Quellreihenfolge erscheint, wird sie angewendet, und der Absatz wird falsch weiß gefärbt.
Um das zu beheben, können Sie @scope
wie folgt verwenden:
@scope (.light-theme) {
:scope {
background: #ccc;
}
p {
color: black;
}
}
@scope (.dark-theme) {
:scope {
background: #333;
}
p {
color: white;
}
}
Jetzt wird der innerste Absatz korrekt schwarz gefärbt. Das liegt daran, dass er nur eine Ebene in der DOM-Baum-Hierarchie vom Scope-Root .light-theme
entfernt ist, aber zwei Ebenen vom Scope-Root .dark-theme
entfernt ist. Daher gewinnt der helle Stil.
Hinweis: Die Scoping-Nähe übertrifft die Quellreihenfolge, wird jedoch von anderen, höher priorisierten Kriterien wie Wichtigkeit, Layers und Spezifität übertroffen.
Formale Syntax
@scope =
@scope [ ( <scope-start> ) ]? [ to ( <scope-end> ) ]? { <block-contents> }
Beispiele
Grundlegender Stil innerhalb von Scope-Roots
In diesem Beispiel verwenden wir zwei separate @scope
-Blöcke, um Links innerhalb von Elementen mit einer .light-scheme
- und .dark-scheme
-Klasse entsprechend zu matchen. Beachten Sie, wie :scope
verwendet wird, um die Scope-Roots selbst zu selektieren und zu stylen. In diesem Beispiel sind die Scope-Roots die <div>
-Elemente, die die Klassen auf sich haben.
HTML
<div class="light-scheme">
<p>
MDN contains lots of information about
<a href="/en-US/docs/Web/HTML">HTML</a>,
<a href="/en-US/docs/Web/CSS">CSS</a>, and
<a href="/en-US/docs/Web/JavaScript">JavaScript</a>.
</p>
</div>
<div class="dark-scheme">
<p>
MDN contains lots of information about
<a href="/en-US/docs/Web/HTML">HTML</a>,
<a href="/en-US/docs/Web/CSS">CSS</a>, and
<a href="/en-US/docs/Web/JavaScript">JavaScript</a>.
</p>
</div>
CSS
@scope (.light-scheme) {
:scope {
background-color: plum;
}
a {
color: darkmagenta;
}
}
@scope (.dark-scheme) {
:scope {
background-color: darkmagenta;
color: antiquewhite;
}
a {
color: plum;
}
}
Ergebnis
Der obige Code wird folgendermaßen gerendert:
Scope-Roots und Scope-Limits
In diesem Beispiel haben wir einen HTML-Schnipsel, der mit der DOM-Struktur übereinstimmt, über die wir zuvor im Beschreibung-Abschnitt gesprochen haben. Diese Struktur repräsentiert eine typische Artikelsammlung. Die wichtigsten Merkmale sind die <img>
-Elemente, die in verschiedenen Ebenen in der Struktur verschachtelt sind.
Das Ziel dieses Beispiels ist es zu zeigen, wie man einen Scope-Root und ein Limit verwendet, um <img>
-Elemente ab der oberen Hierarchieebene zu stylen, jedoch nur so weit (und nicht einschließlich) des <img>
innerhalb des <figure>
-Elements – im Effekt einen Donut-Bereich zu schaffen.
HTML
<article class="feature">
<section class="article-hero">
<h2>Article heading</h2>
<img alt="image" />
</section>
<section class="article-body">
<h3>Article subheading</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam euismod
consectetur leo, nec eleifend quam volutpat vitae. Duis quis felis at
augue imperdiet aliquam. Morbi at felis et massa mattis lacinia. Cras
pharetra velit nisi, ac efficitur magna luctus nec.
</p>
<img alt="image" />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<figure>
<img alt="image" />
<figcaption>My infographic</figcaption>
</figure>
</section>
<footer>
<p>Written by Chris Mills.</p>
<img alt="image" />
</footer>
</article>
CSS
In unserem CSS haben wir zwei @scope
-Blöcke:
- Der erste
@scope
-Block definiert seinen Scope-Root als Elemente mit einer Klasse.feature
(in diesem Fall nur das äußere<article>
), was zeigt, wie@scope
verwendet werden kann, um ein spezifisches HTML-Subset zu gestalten. - Der zweite
@scope
-Block definiert ebenfalls seinen Scope-Root als Elemente mit einer Klasse.feature
, jedoch auch als Scope-Limitfigure
. Dies stellt sicher, dass eingeschlossene Regelsätze nur auf übereinstimmende Elemente innerhalb des Scope-Roots angewendet werden (<article class="feature"> ... </article>
in diesem Fall), die nicht innerhalb von Nachkommen-<figure>
-Elementen verschachtelt sind. Dieser@scope
-Block enthält einen einzigen Regelsatz, der<img>
-Elemente mit einem dicken schwarzen Rand und einer goldenen Hintergrundfarbe stylt.
/* Scoped CSS */
@scope (.feature) {
:scope {
background: rebeccapurple;
color: antiquewhite;
font-family: sans-serif;
}
figure {
background-color: white;
border: 2px solid black;
color: black;
padding: 10px;
}
}
/* Donut scope */
@scope (.feature) to (figure) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Ergebnis
Im gerenderten Code beachten Sie, wie alle <img>
-Elemente mit dem dicken Rand und der goldenen Hintergrundfarbe gestylt sind, außer für das innerhalb des <figure>
-Elements (beschriftet mit "Meine Infografik").
Spezifikationen
Specification |
---|
CSS Cascading and Inheritance Level 6 # scoped-styles |
Browser-Kompatibilität
Siehe auch
:scope
CSSScopeRule
- Limit the reach of your selectors with the CSS
@scope
at-rule auf developer.chrome.com (2023)