Er komen cascadelagen naar uw browser

Cascadelagen (de @layer CSS-regel ) komen naar Chromium 99, Firefox 97 en Safari 15.4 Beta. Ze bieden meer expliciete controle over je CSS-bestanden om stijlspecifieke conflicten te voorkomen. Dit is met name handig voor grote codebases, ontwerpsystemen en bij het beheren van stijlen van derden in applicaties.

Door je CSS op een duidelijke manier te lagen, voorkom je onverwachte stijlwijzigingen en zorg je voor een betere CSS-architectuur.

CSS-specificiteit en de cascade

CSS-specificiteit is hoe CSS bepaalt welke stijlen op welke elementen worden toegepast. De verschillende selectors die je kunt gebruiken, bepalen de specificiteit van een stijlregel. Elementen zijn bijvoorbeeld minder specifiek dan klassen of attributen, die op hun beurt weer minder specifiek zijn dan ID's. Dit is een essentieel onderdeel van het leren van CSS.

Mensen gebruiken CSS-naamgevingsconventies zoals BEM om te voorkomen dat de specificiteit onbedoeld wordt overschreven. Door alles één klassenaam te geven, wordt alles op hetzelfde specificiteitsniveau geplaatst. Het is echter niet altijd mogelijk om zulke georganiseerde stijlen te behouden, vooral niet bij het werken met code en ontwerpsystemen van derden.

BEM-weergave van een kaart met klassen
Een geïllustreerd voorbeeld van BEM-naamgeving van keepinguptodate.com.

Cascadelagen proberen dit probleem op te lossen. Ze introduceren een nieuwe laag in de CSS- cascade . Bij gelaagde stijlen heeft de voorrang van een laag altijd voorrang op de specificiteit van een selector .

De selector .post a.link heeft bijvoorbeeld een hogere specificiteit dan .card a . Als u een link in een kaart of bericht wilt stylen, zult u merken dat de specifiekere selector wordt toegepast.

Door @layer te gebruiken, kun je explicieter zijn over de stijlspecifieke kenmerken van elke stijl en ervoor zorgen dat de stijlen van je kaartlink de stijlen van de berichtlink overschrijven, ook al zou de specificiteit numeriek lager kunnen zijn als al je CSS op hetzelfde vlak zou staan. Dit komt door de cascadeprecedentie. Gelaagde stijlen creëren nieuwe cascade-"vlakken".

Illustratie van een projectdemo van het uitbreken van de gebruikersinterface

@layer in actie

Demo waarin linkkleuren met import worden getoond
Bekijk de demo op Codepen.

Dit voorbeeld demonstreert de kracht van cascadelagen met @layer . Er worden verschillende links weergegeven: sommige zonder extra klassenamen, één met een .link klasse en één met een .pink klasse. De CSS voegt vervolgens drie lagen toe: base , typography en utilities als volgt:

@layer base {
  a {
    font-weight: 800;
    color: red; /* ignored */
  }

  .link {
    color: blue; /* ignored */
  }
}

@layer typography {
  a {
    color: green; /* styles *all* links */
  }
}

@layer utilities {
  .pink {
    color: hotpink;  /* styles *all* .pink's */
  }
}

Uiteindelijk zijn alle links groen of roze. Dit komt doordat: hoewel .link een hogere selector-level specificiteit heeft dan a , er een kleurstijl op a aanwezig is in een @layer met hogere prioriteit. a { color: green } overschrijft .link { color: blue } wanneer de groene regel zich in een laag na de blauwe regel bevindt.

De prioriteit van de laag is belangrijker dan de specificiteit van het element.

Lagen organiseren

U kunt de lagen rechtstreeks op de pagina ordenen, zoals hierboven weergegeven, of u kunt ze bovenaan een bestand ordenen.

De volgorde van de lagen wordt bepaald door de eerste keer dat de naam van een laag in uw code voorkomt.

Dat betekent dat als u het volgende bovenaan het bestand toevoegt, alle koppelingen rood worden weergegeven en de koppeling met de klasse .link blauw:

@layer utilities, typography, base;

Dit komt doordat de volgorde van de lagen nu is omgedraaid, waarbij de hulpprogramma's eerst en de basislaag als laatste worden geplaatst. De stijlregels in de base zullen daarom altijd een hogere specificiteit hebben dan de stijlregels in de typografielaag. Ze worden niet langer groene links, maar rode of blauwe.

Schermafbeelding van Codepen-project
Bekijk de demo op Codepen.

Import organiseren

Een andere manier om @layer te gebruiken is met importbestanden. Je kunt dit direct doen wanneer je stijlen importeert, met behulp van een layer() -functie, zoals in het volgende voorbeeld.

/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */

/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */

/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */

Het bovenstaande codefragment heeft drie lagen: base , layouts en components . De normalize-, theme- en typography-bestanden bevinden zich in base , met een post bestand in layouts , en cards en footer bevinden zich beide in components . Bij het importeren van het bestand worden de lagen geïnstantieerd met behulp van de layer-functie. Een alternatieve aanpak is om je lagen bovenaan het bestand te ordenen en ze te declareren vóór elke import:

@layer base,
       theme,
       layouts,
       components,
       utilities;

De volgorde waarin u uw stijlen @import heeft geen invloed op de volgorde van de lagen, omdat deze al is vastgelegd bij de eerste laagnaam. Dat is één zorg minder. U kunt geïmporteerde bestanden nog steeds op specifieke lagen instellen, maar de volgorde staat al vast.

Screenshot van Codepen Project
Ontdek het project op Codepen.

Lagen en de cascade

Laten we een stapje terug doen en bekijken waar lagen worden gebruikt in relatie tot de bredere cascade:

Cascade-illustratie

De volgorde van voorrang is als volgt:

  • Gebruikersagent normaal (laagste prioriteit)
  • Lokale gebruiker @layer
  • Lokale gebruiker normaal
  • Auteur @layers
  • Auteur normaal
  • Auteur !belangrijk
  • Auteur @layer !important
  • Lokale gebruiker !important
  • Gebruikersagent !important** (hoogste prioriteit)

Je ziet hier misschien dat @layer !important stijlen omgekeerd zijn. In plaats van minder specifiek te zijn dan niet-gelaagde (normale) stijlen, hebben ze een hogere prioriteit. Dit komt door de manier waarop !important in de cascade werkt: het verbreekt de normale cascadering in je stylesheets en draait de normale specificiteit (prioriteit) op laagniveau om.

Geneste lagen

Lagen kunnen ook binnen andere lagen worden genest. Het volgende voorbeeld komt uit de Cascade Layers-uitleg van Miriam Suzanne:

@layer default {
  p { max-width: 70ch; }
}

@layer framework {
  @layer default {
    p { margin-block: 0.75em; }
  }

  p { margin-bottom: 1em; }
}

In het bovenstaande codefragment kunt u framework.default benaderen door een . te gebruiken als teken voor de default die in framework is genest. U kunt dit ook in een kortere vorm schrijven:

@layer framework.default {
  p { margin-block: 0.75em }
}

De resulterende lagen en laagvolgorde zijn:

  • standaard
  • framework.default
  • framework ongelaagd
  • ongelaagd

Waar je op moet letten

Cascadelagen kunnen geweldig zijn als je ze correct gebruikt, maar ze kunnen ook voor extra verwarring en onverwachte resultaten zorgen. Let op het volgende bij het werken met cascadelagen:

Regel 1: Gebruik @layer niet voor scoping

Cascadelagen lossen scoping niet op. Als je een CSS-bestand hebt met een @layer , bijvoorbeeld card.css , en je wilt alle links in card stylen, schrijf dan geen stijlen zoals:

a {
  
}

Dit zorgt ervoor dat alle a tags in je bestand deze overschrijving krijgen. Het is nog steeds belangrijk om je stijlen correct af te bakenen :

.card a {
  
}

Regel 2: cascadelagen worden achter niet-gelaagde CSS geordend

Het is belangrijk om te weten dat een gelaagd CSS-bestand geen niet-gelaagde CSS zal overschrijven. Dit was een bewuste keuze om het eenvoudiger te maken om lagen op een verstandigere manier te introduceren in je bestaande codebase. Het gebruik van een reset.css -bestand is bijvoorbeeld een goed startpunt en een goede use case voor cascadelagen.

Regel 3: !important keert de cascadespecificiteit om

Hoewel gelaagde stijlen over het algemeen minder specifiek zijn dan ongelaagde stijlen, draait het gebruik van !important dit om. In een laag zijn declaraties met de !important -regel specifieker dan ongelaagde stijlen.

In dat geval keren de stijlen !important hun specificiteit om. Het bovenstaande diagram toont dit ter referentie: auteur @layers hebben een lagere prioriteit dan auteur normaal, die een lagere prioriteit hebben dan auteur !important, die een lagere prioriteit hebben dan auteur @layer !important.

Als u meerdere lagen hebt, krijgt de eerste laag met !important voorrang op !important en is dit de meest specifieke stijl.

Regel 4: Begrijp injectiepunten

Omdat de volgorde van de lagen wordt bepaald door de eerste keer dat elke laagnaam in je code voorkomt, kan een @layer -declaratie die je plaatst na het importeren en instellen layer() , of na een andere @layer -statement, worden genegeerd. In tegenstelling tot CSS, waar de stijlregel onderaan de pagina wordt toegepast op cascadelagen, wordt de volgorde in eerste instantie bepaald.

Dit kan in een lijst, in een lagenblok of in een import staan. Als je @layer na een importlijst plaatst met layer() , gebeurt er niets. Door het bovenaan het bestand te plaatsen, wordt de volgorde van de lagen ingesteld en worden de lagen binnen de architectuur duidelijker zichtbaar.

Regel #5: Let op je specificiteit

Bij cascadelagen overschrijft een minder specifieke selector (zoals a ) een specifiekere selector (zoals .link ) als die minder specifieke selector zich op een specifiekere laag bevindt. Houd rekening met het volgende:

a in layer(components) zou .pink in layer(utilities) overschrijven als: @layer utilities, components was gespecificeerd. Hoewel dit een opzettelijk onderdeel van de API is, kan het verwarrend en frustrerend zijn als je het niet verwacht.

Dus als je utility-klassen schrijft, voeg ze dan altijd toe als een hogere-orde laag dan de componenten waarmee je ze wilt overschrijven. Je zou kunnen denken: "Ik heb net deze .pink klasse toegevoegd om de kleur te veranderen, maar die wordt niet toegepast."

Meer informatie over cascadelagen

U kunt ook de volgende bronnen raadplegen voor meer informatie over cascadelagen: