Cascadă, specificitate, moștenire
Ce este CSS, cum se decide ce regulă câștigă și ce se moștenește.
Actualizat
Ce este CSS
CSS (Cascading Style Sheets) descrie cum arată HTML-ul. O regulă CSS are un selector (pe cine) și declarații (ce):
.card h2 { /* selector */
color: navy; /* proprietate: valoare; */
margin-bottom: 1rem;
}Problema centrală a CSS-ului: mai multe reguli pot ținti același element. Care câștigă? Răspunsul e cascada.
Cascada — ordinea în care se decide
Când două declarații se bat pe aceeași proprietate, browserul compară, în ordine:
- Importanța —
!importantbate tot (evită-l; e semn că ceva e greșit). - Layer-ul (
@layer) — straturile declarate mai târziu câștigă. Tailwind îl folosește intern. - Specificitatea selectorului.
- Ordinea în sursă — la egalitate, ultima regulă câștigă.
Specificitatea
Fiecare selector primește un scor de forma (ID-uri, clase, elemente). Se compară de la stânga la dreapta — o clasă bate oricâte elemente, un ID bate oricâte clase.
| Selector | Scor | Explicație |
|---|---|---|
p |
(0, 0, 1) | un element |
.card |
(0, 1, 0) | o clasă |
.card p |
(0, 1, 1) | clasă + element |
nav a:hover |
(0, 1, 2) | pseudo-clasa contează ca o clasă |
[type="email"] |
(0, 1, 0) | atributul contează ca o clasă |
#header .logo |
(1, 1, 0) | ID-ul bate tot ce e sub el |
style="..." |
peste toate | stilul inline |
* |
(0, 0, 0) | universal, fără scor |
Speciale: :where(...) are specificitate 0 (bun pentru stiluri de bază ușor de suprascris); :is(...) și :not(...) iau specificitatea celui mai „puternic” argument.
Regula practică: folosește clase, evită ID-urile în CSS și !important. Așa toate regulile au scor apropiat și ordinea rămâne previzibilă.
Moștenirea
Unele proprietăți trec automat de la părinte la copii, altele nu:
| Se moștenesc (de obicei text) | Nu se moștenesc (de obicei box) |
|---|---|
color, font-*, line-height, text-align, visibility |
margin, padding, border, width, background, display |
De-asta pui font-family pe body și se aplică peste tot, dar padding pe body nu apare la fiecare paragraf.
Poți forța: inherit (ia valoarea părintelui), initial (valoarea implicită), unset.
Tipuri de selectori
| Tip | Exemplu | Selectează |
|---|---|---|
| element | p |
toate paragrafele |
| clasă | .btn |
elementele cu class="btn" |
| ID | #app |
elementul cu id="app" |
| atribut | [disabled], [href^="http"] |
după atribute |
| descendent | .card p |
p oriunde în .card |
| copil direct | .menu > li |
doar copiii direcți |
| frate următor | h2 + p |
p-ul imediat după h2 |
| pseudo-clasă | :hover, :focus-visible, :first-child, :nth-child(2n) |
o stare sau poziție |
| pseudo-element | ::before, ::after, ::placeholder |
o parte „virtuală” a elementului |
| relațional | .card:has(img) |
părintele care conține ceva |
Greșeli frecvente
- Selectori lungi (
.page .main .content .card .title) — greu de suprascris. !importantca să „bați” o regulă — ascunde problema reală.- Stiluri pe ID-uri.
Pe scurt
- Câștigă:
!important→ layer → specificitate → ordine. - Specificitate = (ID-uri, clase, elemente); folosește clase.
- Text se moștenește, box-ul nu.