Een van onze favoriete CSS-preprocessorfuncties is nu in de taal ingebouwd: neststijlregels.
Vóór het nesten moest elke selector expliciet worden gedeclareerd, afzonderlijk van elkaar. Dit leidt tot herhaling, stylesheet-bulk en een verspreide schrijfervaring.
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; }
Na het nesten kunnen selectors worden voortgezet en kunnen gerelateerde stijlregels daarin worden gegroepeerd.
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } }
Probeer dit eens in de browser .
Nesten helpt ontwikkelaars door de noodzaak om selectors te herhalen te verminderen en tegelijkertijd stijlregels voor gerelateerde elementen samen te plaatsen. Het kan er ook voor zorgen dat stijlen overeenkomen met de HTML die ze targeten. Als de .nesting
component in het vorige voorbeeld uit het project was verwijderd, kunt u de hele groep verwijderen in plaats van in bestanden te zoeken naar gerelateerde selectorinstanties.
Nesten kan helpen bij: - Organisatie - Het verkleinen van de bestandsgrootte - Refactoring
Nesten is beschikbaar vanaf Chrome 112 en kan ook worden geprobeerd in Safari Technical Preview 162 .
Aan de slag met CSS-nesten
In de rest van dit bericht wordt de volgende demo-sandbox gebruikt om u te helpen de selecties te visualiseren. In deze standaardstatus is niets geselecteerd en is alles zichtbaar. Door de verschillende vormen en formaten te selecteren, kunt u de syntaxis oefenen en in actie zien.
In de zandbak bevinden zich cirkels, driehoeken en vierkanten. Sommige zijn klein, middelgroot of groot. Anderen zijn blauw, roze of paars. Ze bevinden zich allemaal in het .demo
bevattende element. Het volgende is een voorbeeld van de HTML-elementen die u gaat targeten.
<div class="demo">
<div class="sm triangle pink"></div>
<div class="sm triangle blue"></div>
<div class="square blue"></div>
<div class="sm square pink"></div>
<div class="sm square blue"></div>
<div class="circle pink"></div>
…
</div>
Nestvoorbeelden
Met CSS-nesten kunt u stijlen definiëren voor een element binnen de context van een andere selector.
.parent {
color: blue;
.child {
color: red;
}
}
In dit voorbeeld is de klasseselector .child
genest in de klasseselector .parent
. Dit betekent dat de geneste .child
selector alleen van toepassing is op elementen die onderliggende elementen zijn van elementen met een .parent
klasse.
Dit voorbeeld kan ook worden geschreven met het &
-symbool, om expliciet aan te geven waar de bovenliggende klasse moet worden geplaatst.
.parent {
color: blue;
& .child {
color: red;
}
}
Deze twee voorbeelden zijn functioneel gelijkwaardig en de reden waarom u opties heeft, zal duidelijker worden naarmate meer geavanceerde voorbeelden in dit artikel worden onderzocht.
Het selecteren van de cirkels
Voor dit eerste voorbeeld is het de taak om stijlen toe te voegen om alleen de cirkels in de demo te vervagen en te vervagen.
Zonder nesten , CSS vandaag:
.demo .circle {
opacity: .25;
filter: blur(25px);
}
Met nesten zijn er twee geldige manieren:
/* & is explicitly placed in front of .circle */
.demo {
& .circle {
opacity: .25;
filter: blur(25px);
}
}
of
/* & + " " space is added for you */
.demo {
.circle {
opacity: .25;
filter: blur(25px);
}
}
Het resultaat , alle elementen binnen .demo
met een .circle
-klasse zijn vervaagd en bijna onzichtbaar:
Selecteer eventuele driehoeken en vierkanten
Deze taak vereist het selecteren van meerdere geneste elementen, ook wel een groepskiezer genoemd.
Zonder nesting zijn er tegenwoordig twee manieren voor CSS:
.demo .triangle,
.demo .square {
opacity: .25;
filter: blur(25px);
}
of, met behulp van :is()
/* grouped with :is() */
.demo :is(.triangle, .square) {
opacity: .25;
filter: blur(25px);
}
Met nesting zijn hier twee geldige manieren:
.demo {
& .triangle,
& .square {
opacity: .25;
filter: blur(25px);
}
}
of
.demo {
.triangle, .square {
opacity: .25;
filter: blur(25px);
}
}
Het resultaat : alleen .circle
elementen blijven binnen .demo
:
Grote driehoeken en cirkels selecteren
Voor deze taak is een samengestelde selector vereist, waarbij voor elementen beide klassen aanwezig moeten zijn om te kunnen worden geselecteerd.
Zonder nesten , CSS vandaag:
.demo .lg.triangle,
.demo .lg.square {
opacity: .25;
filter: blur(25px);
}
of
.demo .lg:is(.triangle, .circle) {
opacity: .25;
filter: blur(25px);
}
Met nesting zijn hier twee geldige manieren:
.demo {
.lg.triangle,
.lg.circle {
opacity: .25;
filter: blur(25px);
}
}
of
.demo {
.lg {
&.triangle,
&.circle {
opacity: .25;
filter: blur(25px);
}
}
}
Het resultaat , alle grote driehoeken en cirkels zijn verborgen in .demo
:
Pro-tip met samengestelde selectors en nesten
Het &
-symbool is hier uw vriend, omdat het expliciet laat zien hoe u geneste selectors kunt aansluiten. Beschouw het volgende voorbeeld:
.demo {
.lg {
.triangle,
.circle {
opacity: .25;
filter: blur(25px);
}
}
}
Hoewel dit een geldige manier is om te nesten, komen de resultaten niet overeen met de elementen die u mag verwachten. De reden is dat zonder &
het gewenste resultaat van .lg.triangle, .lg.circle
samengevoegd, het werkelijke resultaat .lg .triangle, .lg .circle
zou zijn; afstammeling selecteurs .
Alle vormen selecteren behalve de roze
Deze taak vereist een negatie-functionele pseudo-klasse , waarbij elementen niet de opgegeven selector mogen hebben.
Zonder nesten , CSS vandaag:
.demo :not(.pink) {
opacity: .25;
filter: blur(25px);
}
Met nesting zijn hier twee geldige manieren:
.demo {
:not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
of
.demo {
& :not(.pink) {
opacity: .25;
filter: blur(25px);
}
}
Het resultaat , alle vormen die niet roze zijn, zijn verborgen in .demo
:
Precisie en flexibiliteit met &
Stel dat u .demo
wilt targeten met de :not()
-selector. &
is daarvoor nodig :
.demo {
&:not() {
...
}
}
Dit combineert .demo
en :not()
tot .demo:not()
, in tegenstelling tot het vorige voorbeeld waarvoor .demo :not()
nodig was. Deze herinnering is erg belangrijk als u een :hover
-interactie wilt nesten.
.demo {
&:hover {
/* .demo:hover */
}
:hover {
/* .demo :hover */
}
}
Meer nestvoorbeelden
De CSS-specificatie voor nesten staat boordevol meer voorbeelden. Als u via voorbeelden meer over de syntaxis wilt leren, vindt u hier een breed scala aan geldige en ongeldige voorbeelden.
De volgende paar voorbeelden introduceren kort een CSS-nestfunctie, om u te helpen de breedte van de mogelijkheden die deze introduceert te begrijpen.
Nesten van @media
Het kan erg afleidend zijn om naar een ander gebied van het stylesheet te gaan om mediaqueryvoorwaarden te vinden die een selector en zijn stijlen wijzigen. Die afleiding is verdwenen dankzij het vermogen om de omstandigheden precies in de context te plaatsen.
Voor syntaxisgemak: als de geneste mediaquery alleen de stijlen voor de huidige selectorcontext wijzigt, kan een minimale syntaxis worden gebruikt.
.card {
font-size: 1rem;
@media (width >= 1024px) {
font-size: 1.25rem;
}
}
Met &
expliciet kan ook worden gebruikt:
.card {
font-size: 1rem;
@media (width >= 1024px) {
&.large {
font-size: 1.25rem;
}
}
}
Dit voorbeeld toont de uitgebreide syntaxis met &
, terwijl ook .large
kaarten worden getarget om aan te tonen dat aanvullende nestingsfuncties blijven werken.
Meer informatie over het nesten van @rules .
Overal nestelen
Alle voorbeelden tot nu toe zijn voortgezet of toegevoegd aan een eerdere context. Indien nodig kunt u de context volledig wijzigen of herschikken.
.card {
.featured & {
/* .featured .card */
}
}
Het &
-symbool vertegenwoordigt een verwijzing naar een selectorobject (geen tekenreeks) en kan overal in een geneste selector worden geplaatst. Hij kan zelfs meerdere keren geplaatst worden:
.card {
.featured & & & {
/* .featured .card .card .card */
}
}
Hoewel dit voorbeeld er wat nutteloos uitziet, zijn er zeker scenario's waarin het handig is om een selectorcontext te kunnen herhalen.
Ongeldige nestvoorbeelden
Er zijn enkele scenario's voor het nesten van syntaxis die ongeldig zijn en die u wellicht zullen verrassen als u in preprocessors heeft genest.
Nesten en aaneenschakelen
Veel CSS-naamgevingsconventies voor klassen rekenen erop dat nesten selectors kan aaneenschakelen of toevoegen alsof het strings zijn. Dit werkt niet bij het nesten van CSS, omdat de selectors geen tekenreeksen zijn, maar objectreferenties.
.card {
&--header {
/* is not equal to ".card--header" */
}
}
Een meer diepgaande uitleg is te vinden in de specificatie .
Lastig nestvoorbeeld
Nesten binnen selectorlijsten en :is()
Overweeg het volgende nestende CSS-blok:
.one, #two {
.three {
/* some styles */
}
}
Dit is het eerste voorbeeld dat begint met een selectorlijst en vervolgens verder nestelt. Eerdere voorbeelden eindigden alleen met een selectorlijst. Er is niets ongeldig in dit nestvoorbeeld, maar er is een potentieel lastig implementatiedetail over het nesten in selectorlijsten, vooral die welke een ID-selector bevatten.
Om de bedoeling van het nesten te laten werken, zal elke selectielijst die niet de binnenste nesting is, door de browser worden omhuld met :is()
. Deze omloop behoudt de groepering van de selectorlijst binnen alle geschreven contexten. Het neveneffect van deze groepering, :is(.one, #two)
, is dat deze de specificiteit overneemt van de hoogste score binnen de selectors tussen haakjes. Dit is hoe :is()
altijd werkt , maar het kan een verrassing zijn als je nest-syntaxis gebruikt, omdat het niet precies is wat er is geschreven. De truc samengevat; Nesten met ID's en selectorlijsten kan leiden tot selectors met een zeer hoge specificiteit.
Om het lastige voorbeeld duidelijk samen te vatten: het vorige nestblok wordt als volgt op het document toegepast:
:is(.one, #two) .three {
/* some styles */
}
Houd een oogje in het zeil of leer uw linters om te waarschuwen wanneer ze nesten in een selectorlijst die gebruikmaakt van een ID-selector. De specificiteit van alle nestingen binnen die selectorlijst zal hoog zijn.
Nesten en declaraties combineren
Overweeg het volgende nestende CSS-blok:
.card {
color: green;
& { color: blue; }
color: red;
}
De kleur van .card
elementen is blue
.
Eventuele onderling gemengde stijldeclaraties worden naar boven gehesen, alsof ze zijn geschreven voordat er sprake was van nesten. Meer details vindt u in de specificatie .
Er zijn manieren om dit te omzeilen. Het volgende omvat de drie kleurstijlen in &
, waardoor de cascadevolgorde wordt gehandhaafd zoals de auteur mogelijk heeft bedoeld. De kleur van .card
elementen is rood.
.card {
color: green;
& { color: blue; }
& { color: red; }
}
Het is zelfs een goede gewoonte om alle stijlen die volgen op het nesten te verpakken met een &
.
.card {
color: green;
@media (prefers-color-scheme: dark) {
color: lightgreen;
}
& {
aspect-ratio: 4/3;
}
}
Functiedetectie
Er zijn twee geweldige manieren om CSS-nesten te detecteren: gebruik nesten of gebruik @supports
om te controleren of de nesting-selector parseermogelijkheden heeft.
Nesten gebruiken:
html {
.has-nesting {
display: block;
}
.no-nesting {
display: none;
}
}
@supports
gebruiken:
@supports (selector(&)) {
/* nesting parsing available */
}
Mijn collega Bramus heeft een geweldige Codepen die deze strategie laat zien.
Foutopsporing met Chrome DevTools
De huidige ondersteuning in DevTools voor nesten is minimaal. Momenteel ziet u dat stijlen zoals verwacht worden weergegeven in het deelvenster Stijlen, maar het traceren van de nesting en de volledige selectorcontext wordt nog niet ondersteund. We hebben een ontwerp en plannen om dit transparant en duidelijk te maken.
Chrome 113 is van plan extra ondersteuning te bieden voor CSS-nesten. Blijf op de hoogte.
De toekomst
CSS Nesting is alleen beschikbaar in versie 1. Versie 2 introduceert meer syntactische suiker en mogelijk minder regels om te onthouden. Er is veel vraag naar het parseren van nesten, zodat het niet beperkt is of lastige momenten kent.
Nesten is een grote verbetering van de CSS-taal. Het heeft implicaties voor het schrijven van bijna elk architectonisch aspect van CSS. Deze grote impact moet diepgaand worden onderzocht en begrepen voordat versie 2 effectief kan worden gespecificeerd.
Als laatste gedachte is hier een demo die @scope
, nesting en @layer
allemaal samen gebruikt. Het is allemaal heel spannend!