Frontend

O dedení a zdieľaní hodnôt vlastností v CSS

Naučte sa praktické spôsoby, ako v CSS zdieľať hodnoty medzi vlastnosťami pomocou custom properties, jednotiek, aspect-ratio a ďalších techník, ktoré sú už dnes k dispozícii.

GUY Team
8 min čítania
O dedení a zdieľaní hodnôt vlastností v CSS

Niekedy chcem nastaviť hodnotu CSS vlastnosti na hodnotu inej vlastnosti, aj keď neviem, aká tá hodnota je, a aj keď sa neskôr zmení. Bohužiaľ, to nie je možné (aspoň neexistuje CSS funkcia, ktorá by to špecificky robila).

Podľa môjho názoru by bylo super užitočné mať niečo také (na interpoláciu by ste možno pridali aj calc-size()):

/* Úplne hypotetické */
button { border-radius: compute(height, self); border-radius: compute(height, inherit); border-radius: compute(height, #this);
}

V roku 2021 Lea Verou vysvetlila, prečo napriek tomu, že to bolo viackrát navrhnuté, implementácia takejto univerzálnej CSS funkcie nie je uskutočniteľná. Napriek tomu zostávam optimistický, pretože veci sa neustále vyvíjajú a proces CSSWG nie je vždy lineárny.

Medzitým, aj keď neexistuje CSS funkcia, ktorá by nám umožnila získať hodnotu inej vlastnosti, možno dokážete dosiahnuť svoj výsledok použitím inej metódy, a práve tie metódy si dnes prejdeme.

Spoľahlivá metóda CSS custom properties

Môžeme ľahko získať hodnotu inej CSS vlastnosti pomocou custom properties, ale museli by sme vedieť, aká je tá hodnota, aby sme vôbec mohli custom property deklarovať. Nie je to ideálne, ale umožňuje nám to dosiahnuť niektoré výsledky.

Vráťme sa k príkladu z úvodu, kde sa snažíme nastaviť border-radius na základe height, len tentoraz vieme, aká je výška a uložíme ju ako CSS custom property pre opätovné použitie, a tak dokážeme dosiahnuť náš výsledok:

button { --button-height: 3rem; height: var(--button-height); border-radius: calc(var(--button-height) * 0.3);
}

Môžeme dokonca umiestniť túto custom property --button-height vyššie v CSS kaskáde, aby bola dostupná vo viacerých kontextoch containmentu.

:root { /* Deklarujte tu, aby ste mohli použiť kdekoľvek */ --button-height: 3rem; header { --header-padding: 1rem; padding: var(--header-padding); /* Výška je neznáma (ale môžeme ju vypočítať) */ --header-height: calc(var(--button-height) + (var(--header-padding) * 2)); /* Čo znamená, že môžeme vypočítať aj toto */ border-radius: calc(var(--header-height) * 0.3); button { /* Rovnako ako toto, samozrejme */ height: var(--button-height); border-radius: calc(var(--button-height) * 0.3); /* Čo už, ideme do toho */ padding-inline: calc(var(--button-height) * 0.5); } }
}

Hádam keď moja učiteľka matematiky povedala, že jedného dňa budem potrebovať algebru, neklamala!

Metóda nepodporovanej CSS funkcie inherit()

CSS funkcia inherit(), ktorá momentálne nie je podporovaná žiadnym webovým prehliadačom, nám umožní získať hodnotu vlastnosti rodiča. Predstavte si: kľúčové slovo inherit, len že môžeme získať hodnotu akejkoľvek vlastnosti rodiča a dokonca ju upraviť pomocou hodnotových funkcií ako calc(). Najnovší návrh špecifikácie CSS Values and Units Module Level 5 definuje, ako by to fungovalo pre custom properties, čo by nám v podstate neumožnilo robiť nič, čo už nemôžeme robiť (ako je ukázané v predchádzajúcom príklade), ale nádej je, že by to fungovalo pre všetky CSS vlastnosti niekedy v budúcnosti, takže by sme nemuseli používať custom properties (čo je len o niečo dlhšie):

header { height: 3rem; button { height: 100%; /* Získať výšku rodiča, ale použiť ju tu */ border-radius: calc(inherit(height) * 0.3); padding-inline: calc(inherit(height) * 0.5); }
}

Medzi touto a metódou custom properties je však jeden rozdiel. Táto metóda závisí od fixnej výšky rodiča, zatiaľ čo pri metóde custom properties môže mať fixnú výšku buď rodič alebo potomok.

To znamená, že inherit() by neinterpolovalo hodnoty. Napríklad hodnota auto, ktorá sa vypočíta na 3rem, by sa stále dedila ako auto, čo by sa mohlo vypočítať na niečo iné pri použití inherit(). Niekedy by to bolo v poriadku, ale inokedy by to bol problém. Osobne dúfam, že interpolácia sa niekedy stane možnosťou, čím by to bolo oveľa užitočnejšie ako metóda custom properties.

Dovtedy existujú niektoré ďalšie (väčšinou špecifické pre vlastnosť) možnosti.

CSS vlastnosť aspect-ratio

Použitím CSS vlastnosti aspect-ratio môžeme nastaviť výšku relatívne k šírke a naopak. Napríklad:

div { width: 30rem; /* výška bude polovica šírky */ aspect-ratio: 2 / 1; /* To isté */ aspect-ratio: 3 / 1.5; /* To isté */ aspect-ratio: 10 / 5; /* šírka a výška budú rovnaké */ aspect-ratio: 1 / 1;
}

Technicky "nezískavame" width ani height, ale môžeme nastaviť jednu na základe druhej, čo je dôležité (a keďže je to pomer, nemusíte poznať skutočnú hodnotu - ani jednotku - ani jednej z nich).

CSS kľúčové slovo currentColor

CSS kľúčové slovo currentColor sa preloží na vypočítanú hodnotu vlastnosti color. Jeho dátový typ je <color>, takže ho môžeme použiť namiesto akéhokoľvek <color> v akejkoľvek vlastnosti na tom istom elemente. Napríklad, ak nastavíme color na red (alebo niečo, co sa preloží na red), alebo ak sa color vypočíta ako red cez dedenie, potom môžeme deklarovať border-color: currentColor, aby bol aj okraj červený:

body { /* Môžeme nastaviť color tu (a nechať ho zdediť) */ color: red; button { /* Alebo to nastaviť tu */ color: red; /* A potom použiť currentColor tu */ border-color: currentColor; border: 0.0625rem solid currentColor; background: hsl(from currentColor h s 90); }
}

To nám umožňuje opakovane použiť farbu bez toho, aby sme museli nastavovať custom properties, a samozrejme, ak sa hodnota color zmení, currentColor sa automaticky aktualizuje, aby jej zodpovedal.

Aj keď to nie je to isté, ako byť schopný získať farbu doslova čohokoľvek, je to stále celkom užitočné. Vlastne, ak niečo podobné ako compute(background-color) jednoducho nie je možné, bol by som spokojný s viacerými CSS kľúčovými slovami ako currentColor.

V skutočnosti, currentBackgroundColor/currentBackgroundbolo navrhnuté. Použitím napríklad currentBackgroundColor by sme mohli nastaviť farbu okraja tak, aby bola o niečo tmavšia ako farba pozadia (border-color: hsl(from currentBackgroundColor h s calc(l - 30))), alebo zmiešať farbu pozadia s inou farbou a potom ju použiť ako farbu okraja (border-color: color-mix(currentBackgroundColor, black, 30)).

Ale prečo sa zastaviť tam? Prečo nie currentWidth, currentHeight a tak ďalej?

CSS kľúčové slovo from-font

CSS kľúčové slovo from-font je exkluzívne pre vlastnosť text-decoration-thickness, ktorú možno použiť na nastavenie hrúbky podčiarknutí. Ak ste niekedy nenávideli skutočnosť, že podčiarknutia sú vždy 1px bez ohľadu na font-size a font-weight, potom to môže text-decoration-thickness napraviť.

Kľúčové slovo from-font však negeneruje hodnotu - je voliteľne poskytnuté tvorcom písma a vložené do súboru písma, takže sa vám nemusí páčiť hodnota, ktorú poskytujú, ak vôbec nejakú poskytnú. Ak neposkytujú, použije sa ako náhrada auto, ktoré webové prehliadače preložia na 1px. To je v poriadku, ak nie ste vyberavý, ale je to napriek tomu nespoľahlivé (a zjavne celkem špecifické).

Môžeme však namiesto toho určiť percentuálnu hodnotu, ktorá zabezpečí, že hrúbka je relatívna k font-size. Takže, ak text-decoration-thickness: from-font jednoducho nestačí, máme to ako zálohu (niečo medzi 8% a 12% by malo stačiť).

Nepodceňujte CSS jednotky

Pravdepodobne už viete o jednotkách vw a vh (jednotky šírky a výšky viewportu). Tieto predstavujú percento šírky a výšky viewportu, takže napríklad 1vw by bolo 1% šírky viewportu. Tieto jednotky môžu byť užitočné samé osebe alebo v rámci funkcie calc(), a použité v akejkoľvek vlastnosti, ktorá akceptuje jednotku <length>.

Avšak, existuje množstvo ďalších, menej známych jednotiek, ktoré môžu byť užitočné podobným způsobom:

  • 1ex: rovná sa vypočítanej x-výške
  • 1cap: rovná sa vypočítanej cap výške
  • 1ch: rovná sa vypočítanej šírke glyphu 0
  • 1lh: rovná sa vypočítanému line-height (pokiaľ neodstraňujete alebo nepridávate k jeho content boxu, napríklad pomocou text-box alebo padding, jednotky lh by sa mohli použiť na určenie výšky boxu, ktorý má fixný počet riadkov)
Zdroj: W3

A opäť, môžete ich použiť, ich logické varianty (napr. vi a vb), a ich koreňové varianty (napr. rex a rcap) v akejkoľvek vlastnosti, ktorá akceptuje jednotku <length>.

Okrem toho, ak používate container size queries, môžete tiež voľne používať nasledujúce jednotky container query v kontextoch containmentu:

  • 1cqw: rovná sa 1% vypočítanej šírky containera
  • 1cqh: rovná sa 1% vypočítanej výšky containera
  • 1cqi: rovná sa 1% vypočítanej inline veľkosti containera
  • 1cqb: rovná sa 1% vypočítanej block veľkosti containera
  • 1cqmin: rovná sa 1cqi alebo 1cqb, podľa toho, čo je menšie
  • 1cqmax: rovná sa 1cqi alebo 1cqb, podľa toho, čo je väčšie

Ten príklad inherit() z predtým, viete, ten, ktorý momentálne nie je podporovaný žiadnym webovým prehliadačom? Tu je to isté, ale s container size queries:

header { height: 3rem; container: header / size; @container header (width) { button { height: 100%; border-radius: calc(100cqh * 0.3); padding-inline: calc(100cqh * 0.5); } }
}

Alebo, keďže hovoríme o containeri a jeho priamom potomkovi, môžeme použiť nasledujúcu kratšiu verziu, ktorá nevytvára a nedopytuje pomenovaný container (nepotrebujeme dopytovať container tak či tak, keďže všetko, čo robíme, je kradnutie jeho jednotiek!):

header { height: 3rem; container-type: size; button { height: 100%; border-radius: calc(100cqh * 0.3); padding-inline: calc(100cqh * 0.5); }
}

Avšak majte na pamäti, že inherit() by nám umožnil dediť čokoľvek, zatiaľ čo container size queries nám umožňujú dediť len veľkosti. Okrem toho, container size queries nefungujú s inline containermi (preto je táto verzia containera horizontálne roztiahnutá), takže aj tak nemôžu vyriešiť každý problém.

V kostce

Znova len vyhodím compute(), pretože si myslím, že by to bol skutočne skvelý spôsob, ako získať hodnoty iných CSS vlastností:

button { /* self by mohlo byť predvolené */ border-radius: compute(height, self); /* inherit by mohlo fungovať ako inherit() */ border-radius: compute(height, inherit); /* Pekné mať, ale nie tak dôležité */ border-radius: compute(height, #this);
}

Ale ak to jednoducho nie je možné, veľmi sa mi páči myšlienka zavedenia viacerých kľúčových slov podobných currentColor. S výnimkou kľúčových slov ako from-font, kde tvorca písma poskytuje hodnotu (alebo nie, vzdych), kľúčové slová ako currentWidth a currentHeight by boli neuveriteľne užitočné. Urobili by CSS ľahšie čitateľným a nemuseli by sme vytvárať toľko custom properties.

Medzitým však custom properties, aspect-ratio a určité CSS jednotky nám môžu pomôcť v správnych okolnostiach, nehovoriac o tom, že v budúcnosti dostaneme inherit(). Tieto sú silne zamerané na získavanie šírok a výšok, čo je v poriadku, pretože to je nepochybne najväčší problém, ale dúfam, že na obzore sú ďalšie CSS funkcie, ktoré umožnia použiť hodnoty na viacerých miestach.

webdizajncssfrontendcustom-propertiescontainer-queries

Nenechajte si ujsť žiadny článok

Prihláste sa na odber newslettera a dostávajte najnovšie tipy a trendy priamo do emailu.