Ställ in sidtextstandarder på body, låt ärvda egenskaper flöda in i komponenter, och rikta layoutregler medvetet. Den här guiden visar hur du bygger och testar en lokal HTML-sida på en Mac utan att tvinga varje element att åsidosätta en universell regel.
Varför stör en universell regel komponentstandarder?
Det universella selektorn * matchar varje element. En deklaration inuti den regeln gäller därmed direkt för varje matchande element; den ger inte bara ett värde för efterkommar att ärva. Den matchar inte heller direkt pseudo-element, som kräver selektorer som *::before. Universella selektorer.
Överväg det här CSS-utdraget för en komponent som innehåller ett stycke och en kapslad textspan:
/* Illustrative fragment: assumes a .tile with text descendants. */
* {
color: #303840;
}
.tile {
color: #245d75;
}
Panelen får själv den blå textfärgen. Dess stycke och span får den universella regelns mörka färg direkt. Komponentens färg kan inte flöda genom dessa deklarationer genom ordinär arv. Enligt CSS-standardregler för standardvärden får ärvda egenskaper sin förälders beräknade värde när kaskaden inte ger något värde för den egenskapen på elementet. CSS Cascading and Inheritance Level 4, Defaulting.
Det här kan vara förvirrande eftersom * har noll specificitet. Specificitet jämför konkurrerande deklarationer på samma element inom den tillämpliga kaskadursprunget och lagret. En deklaration på en förälder är inte en konkurrerande selektormatchning på dess barn. Att göra förälderselektorn mer specifik löser därmed inte det här arvproblemet. Specificitet.
Den användbara ändringen är att ta bort den universella textdeklarationen och etablera standarden på body. Efterkommar kan då ärva den tills en komponent eller ett element anger ett annat värde. MDN identifierar color som en ärvd egenskap och förklarar att arv följer förälderns beräknade värde. Arv.
Vilka standarder hör på sidan, en komponent eller varje element?
Innan du skriver en bred selektor, bestäm om egenskapen ska flöda genom ett textträd, beskriva en ruta, eller etablera en medveten regel för alla rutor. Följande beslutsstöd tillämpar den skiljelinjen på en liten sida.
| Önskat resultat | Rekommenderad placering | Orsak |
|---|---|---|
| Vanlig sidtext delar en basfärg och typografi | body |
Ger text en gemensam utgångspunkt genom arv |
| En panel och dess vanliga text delar en annan färg | .tile |
Etablerar ett nytt ärvt värde inom den komponenten |
| En enda bildtext har en annan färg | .caption |
Tillämpar undantaget på elementet som behöver det |
| En panel har padding, en ram eller en bakgrund | Panels klass | Håller rute-dekoration knuten till sin ägare |
| Rutor använder en konsekvent storleksmodell | En medveten box-sizing-regel |
Etablerar en explicit storleks konvention |
| Rubriker har en lättbytbar marginalstandard | En riktrad rubrikselektor, valfritt inpackad i :where() |
Begränsar standarden till de avsedda elementen |
Arv är egenskapsspecifikt. Konsultera egenskapsreferensens Inherited-post istället för att anta att varje deklaration på body når sina efterkommar. Till exempel ärvs inte ramar som standard. Arv.
En universell storleksregel kan fortfarande vara lämplig. Med border-box ingår ett elements deklarerade bredd dess padding och ram; marginaler ligger utanför den bredden. Det är ett specifikt box-modell-beslut, snarare än en anledning att applicera varje sidstandard universellt. box-sizing.
Bygg en komplett lokal demonstration på din Mac
Använd TextEdit i ren textläge eller en befintlig kodredigerare. I TextEdit, välj Arkiv > Ny, sedan Format > Gör ren text. Klistra in hela dokumentet nedan, välj Arkiv > Spara, och ge det namnet page-defaults.html. Om du uppmanas, välj Använd .html. Apple dokumenterar det här arbetsflödet i sin TextEdit HTML-guide.
Det här exemplet använder syntetiska etiketter och CSS-ritade former. Det är ett komplett dokument med inbäddat formatark, så det finns inga ytterligare filer att förbereda. Koden har granskats här; dess rendering har inte körts i en Mac-webbläsare.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Page defaults demonstration</title>
<style>
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
font-size: 1rem;
line-height: 1.5;
color: #303840;
background-color: #f4f5f6;
}
main {
max-width: 44rem;
margin: 0 auto;
padding: 2rem 1rem;
}
h1 {
line-height: 1.2;
}
.tile {
margin: 1.5rem 0;
padding: 1.25rem;
border: 2px solid currentColor;
border-radius: 0.75rem;
color: #245d75;
background-color: #ffffff;
}
.tile h2 {
margin-top: 0;
}
.shape {
width: 4rem;
height: 4rem;
background-color: currentColor;
}
.shape--round {
border-radius: 50%;
}
.caption {
color: #66523c;
}
</style>
</head>
<body>
<main>
<h1>Shape notes</h1>
<p>Page sample: <span>Label A</span>.</p>
<section class="tile">
<h2>Tile B</h2>
<div class="shape shape--round" aria-hidden="true"></div>
<p>Component sample: <span>Label C</span>.</p>
<p class="caption">Caption D has its own text color.</p>
</section>
<p>Page sample: <span>Label E</span>.</p>
</main>
</body>
</html>
Öppna page-defaults.html i din webbläsare. Vid återöppning av källan i TextEdit, välj TextEdit > Inställningar > Öppna och spara och aktivera Visa HTML-filer som HTML-kod istället för formaterad text om du vill att TextEdit ska visa markupen konsekvent. Arbeta med HTML-dokument i TextEdit på Mac.
Kontrollera arvgränsen med tre ändringar
Dessa kontroller gör dokumentet till en liten diagnostisk övning. Spara källan och ladda om webbläsaren efter varje ändring. Behåll en kopia av det ursprungliga dokumentet eller ångra varje ändring innan du provar nästa.
- Ändra endast
body-färgen till#4b465f. Texten runtEtikett AochEtikett Ebör ändras. Panelen behåller sin egen färg. - Återställ sidfärgen, ändra endast
.tiletillcolor: #526637. Dess vanliga rubrik- och stycketext bör följa den ändringen, inklusiveEtikett C.Bildtext Dbehåller sin explicita färg. - Återställ panelfärgen, lägg sedan tillfälligt till
* { color: #303840; }i början av formatarket. Stycket som innehållerEtikett Cfår nu den direkta deklarationen. Ta bort den tillfälliga regeln därefter.
Kontrollerna illustrerar skillnaden mellan en komponent som etablerar ett ärvt värde och ett efterkomma som får en egen deklaration. Det förväntade textbeteendet följer specifikationens arv- och standardregler.
Vad är kontraktet mellan HTML-sidan och dess formatark?
Håll resursinläsning separat från selektorbeteende. Exemplet bäddar in sitt CSS i ett style-element. Om du föredrar ett separat formatark, flytta endast innehållet i det elementet till en ren textfil med namnet page-defaults.css, sparat bredvid HTML-filen. Ersätt hela style-elementet med följande rad inuti head. Det här är ett ersättningsfragment, inte ett annat komplett dokument.
<link rel="stylesheet" href="page-defaults.css">
stylesheet-länktypen identifierar en extern CSS-resurs som används för att presentera dokumentet. Filnamnet i href måste peka på den fil du faktiskt sparade; deklarationen skapar inte den filen. HTML-standarden definierar den här relationen i Länktyp: stylesheet.
För det här exemplet är det resulterande kontraket enkelt: HTML levererar element och klasser, medan CSS levererar deras presentation. Att byta namn på .tile i formatarket kräver att du uppdaterar motsvarande klass i HTML. Att flytta CSS-filen kräver att du uppdaterar dess resursreferens. Ingen av ändringarna kräver en starkare selektor.
Om den externa versionen verkar ostylad, bekräfta först att CSS-filen finns under det förväntade namnet och att dess innehåll innehåller CSS snarare än det omgivande HTML-dokumentet. Gå tillbaka till den inbäddade versionen för att isolera resursinläsningsfel innan du ändrar kaskaden.
När ska du använda :where() eller kaskadlager?
Använd dessa funktioner när de löser ett ytterligare problem. Det kompletta exemplet ovan beror inte på någon av dem.
Använd :where() för rikta standarder med noll specificitet
Anta att sidan växer och innehåller flera rubriknivåer. Det här valfria formatarksfragmentet etablerar delad avstånd samtidigt som vanliga rubrikselektorer enkelt kan ersätta det:
/* Optional fragment: add to the example stylesheet. */
:where(h1, h2, h3) {
margin-bottom: 0.75rem;
}
h2 {
margin-bottom: 1rem;
}
Hela :where()-selektorn har noll specificitet, inklusive dess argument. Men att ersätta * med :where(*) fixar inte det tidigare färgproblemet: den matchar fortfarande varje element och ger en direkt deklaration. Använd arv för att lösa det problemet. MDN dokumenterar :where() som bredt tillgänglig över webbläsare sedan januari 2021; kontrollera dess kompatibilitetstabell när du stödjer en äldre webbläsare. Pseudoklassen :where().
För en webbläsare utan :where()-stöd, använd en vanlig selektorlista som h1, h2, h3 för dessa avståndsstandarder, placera sedan lika-specifika undantag senare i samma formatark och lager. Detta behåller rikta standarder, även om deras specificitet inte längre är noll. Specificitet.
Använd lager när grupper av regler behöver en explicit ordning
För ett större formatark demonstrerar det här valfria fragmentet en deklarerad lagerordning. Det är separat från det kompletta exemplet snarare än en ersättning för dess fullständiga CSS.
/* Optional fragment for browsers supporting cascade layers. */
@layer defaults, components;
@layer defaults {
p {
margin-bottom: 1rem;
}
}
@layer components {
.tile p {
margin-bottom: 0.5rem;
}
}
För normala författardeklarationer har senare lager företräde framför tidigare lager; normala olagraddeklarationer rankas högre än lagrade deklarationer. Viktiga deklarationer vänder lagerordningen, så att lägga till !important ändrar den ordningen. Lager organiserar konkurrerande regler; de gör inte att ett direkt stilat barn ärver sitt föräldervärde. At-regeln @layer.
MDN registrerar cross-browser-tillgänglighet för @layer sedan mars 2022. Om en äldre målwebbläsare saknar stöd, håll väsentlig presentation utanför lagerblock och använd det olagrade tillvägagångssättet som visas i det kompletta exemplet. Placera inte den enda kopian av nödvändiga stilar inuti en icke-stödd funktion. Kaskadlager-stöd.
Hur fixar du ett befintligt formatark utan att lägga till fler åsidosättningar?
Arbeta igenom en egenskap i taget. För ett textfärgproblem, hitta den breda regeln som tilldelar färgen direkt till efterkommar. Ta bort den deklarationen från den universella regeln, etablera sidvärdet på body, och håll komponentfärger på deras komponentrötter. Behåll elementdeklarationer bara där designen kräver ett undantag.
Upprepa sedan de tre ändringarna från demonstrationen. Om vanlig komponenttext fortfarande inte följer sin förälder, leta efter en deklaration som riktar sig mot det efterkomma. Om att ändra en komponentens ram inte ändrar någon av dess efterkommars ramar, är det förväntat: ramarv skiljer sig från textfärgsarv. Arv.
En underhållbar standard har en tydlig ägare. Sätt sidtypografi vid sidgränsen, komponentpresentation vid komponentgränsen, och medvetna undantag på de element som behöver dem. Reservera universella deklarationer för beslut du faktiskt avser att tillämpa på varje matchande element, verifiera sedan dessa gränser med en liten lokal sida.
Källor
- CSS Cascading and Inheritance Level 4 — W3C.
- Universella selektorer — MDN Web Docs.
- Specificitet — MDN Web Docs.
- Arv — MDN Web Docs.
- box-sizing — MDN Web Docs.
- Arbeta med HTML-dokument i TextEdit på Mac — Apple Support.
- HTML-standard: Länktyp stylesheet — WHATWG.
- CSS-pseudoklassen :where() — MDN Web Docs.
- CSS-at-regel @layer — MDN Web Docs.