Zmienne CSS – dlaczego jest to ważne?

Zmienne CSS, ściślej mówiąc właściwości niestandardowe CSS, są dostępne w Chrome 49. Mogą one służyć do zmniejszania powtórzeń w CSS-ie, a także do tworzenia zaawansowanych efektów w czasie wykonywania, takich jak przełączanie motywów czy potencjalne rozszerzanie lub wypełnianie przyszłych funkcji CSS.

Zaśmiecanie kodu CSS

Podczas projektowania aplikacji warto zarezerwować zestaw kolorów marki, które będą używane wielokrotnie, aby zachować spójność wyglądu aplikacji. Niestety powtarzanie tych wartości kolorów w CSS jest nie tylko uciążliwe, ale też może powodować błędy. Jeśli w jakimś momencie trzeba zmienić jeden z kolorów, możesz zapomnieć o ostrożności i zrobić „znajdź i wymień” we wszystkich elementach, ale w przypadku dużego projektu może to być niebezpieczne.

Ostatnio wielu deweloperów zaczęło używać preprocesorów CSS, takich jak SASS czy LESS, które rozwiązują ten problem dzięki zmiennym preprocesora. Chociaż te narzędzia znacznie zwiększyły wydajność programistów, zmienne, których używają, mają jedną poważną wadę: są statyczne i nie można ich zmieniać w czasie wykonywania. Dodanie możliwości zmiany zmiennych w czasie wykonywania kodu nie tylko umożliwia tworzenie dynamicznych motywów aplikacji, ale też ma duże znaczenie dla projektowania responsywnego i możliwości polyfillowania przyszłych funkcji CSS. Wraz z wydaniem Chrome 49 te możliwości są dostępne w postaci właściwości niestandardowych w CSS.

Właściwości niestandardowe w skrócie

Właściwości niestandardowe wprowadzają do naszego narzędzia CSS 2 nowe funkcje:

  • Umożliwienie autorowi przypisywania dowolnych wartości właściwości z nazwą wybraną przez autora.
  • Funkcja var(), która pozwala autorowi używać tych wartości w innych właściwościach.

Oto krótki przykład:

:root {
    --main-color: #06c;
}

#foo h1 {
    color: var(--main-color);
}

--main-color to zdefiniowana przez autora właściwość niestandardowa o wartości #06c. Pamiętaj, że wszystkie właściwości niestandardowe zaczynają się od 2 kresek.

Funkcja var() pobiera i zastępuje siebie wartością właściwości niestandardowej, co powoduje, że color: #06c;. Dopóki właściwości niestandardowej nie zdefiniowano nigdzie w swojej liście stylów, powinna być ona dostępna dla funkcji var.

Składnia może na początku wyglądać trochę dziwnie. Wielu deweloperów pyta: „Dlaczego nie użyć w nazwach zmiennych wartości $foo?”. Podejście zostało wybrane tak, aby było jak najbardziej elastyczne i aby w przyszłości można było stosować w nim makra $foo. Aby poznać historię, przeczytaj ten post autorstwa Tab Atkins, jednej z autorów specyfikacji.

Składnia właściwości niestandardowych

Składnia właściwości niestandardowej jest prosta.

--header-color: #06c;

Pamiętaj, że w przypadku właściwości niestandardowych wielkość liter ma znaczenie, więc --header-color--Header-Color to różne właściwości niestandardowe. Chociaż na pierwszy rzut oka mogą wydawać się proste, dozwolona składnia w przypadku właściwości niestandardowych jest dość liberalna. Przykład prawidłowej usługi niestandardowej:

--foo: if(x > 5) this.width = 10;

Nie jest ona przydatna jako zmienna, ponieważ jest nieprawidłowa w przypadku zwykłych właściwości, ale może być odczytywana i używana w JavaScript w czasie wykonywania. Oznacza to, że właściwości niestandardowe mogą odblokować różne interesujące techniki, które nie są obecnie możliwe w ramach obecnych preprocesorów CSS. Jeśli więc myślisz „Yawn Mam SASS, więc kogo to obchodzi…”, spójrz jeszcze raz. Nie są to zmienne, z którymi zwykle pracujesz.

Kaskada

Własne właściwości podlegają standardowym regułom kaskadowym, dzięki czemu możesz definiować tę samą właściwość na różnych poziomach szczegółowości.

:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
    While I got red set directly on me!
    <p>I’m red too, because of inheritance!</p>
</div>

Oznacza to, że możesz wykorzystywać właściwości niestandardowe w zapytaniach o media, aby ułatwić projektowanie stron responsywnych. Jednym z takich przypadków może być zwiększanie marginesu wokół głównych elementów sekcji wraz ze wzrostem rozmiaru ekranu:

:root {
    --gutter: 4px;
}

section {
    margin: var(--gutter);
}

@media (min-width: 600px) {
    :root {
    --gutter: 16px;
    }
}

Należy pamiętać, że powyższy fragment kodu nie jest możliwy do użycia w obecnych preprocesorach CSS, które nie mogą definiować zmiennych w zapytaniach o media. Ta umiejętność otwiera wiele możliwości.

Możesz też mieć właściwości niestandardowe, których wartości pochodzą z innych właściwości niestandardowych. Może to być bardzo przydatne podczas projektowania:

:root {
    --primary-color: red;
    --logo-text: var(--primary-color);
}

Funkcja var()

Aby pobrać i użyć wartości właściwości niestandardowej, musisz użyć funkcji var(). Składnia funkcji var() wygląda tak:

var(<custom-property-name> [, <declaration-value> ]? )

Gdzie <custom-property-name> to nazwa właściwości niestandardowej zdefiniowanej przez autora, np. --foo, a <declaration-value> to wartość zastępcza, która jest używana, gdy odwołana właściwość niestandardowa jest nieprawidłowa. Wartości zastępcze mogą być listą rozdzieloną przecinkami, która zostanie połączona w jedną wartość. Na przykład var(--font-stack, "Roboto", "Helvetica"); definiuje wartość zastępczą dla "Roboto", "Helvetica". Pamiętaj, że wartości skrótów, takie jak te używane do marginesów i dopełnień, nie są rozdzielane przecinkami, więc odpowiednia wartość zastępcza dla dopełnienia będzie wyglądać tak.

p {
    padding: var(--pad, 10px 15px 20px);
}

Korzystając z tych wartości zastępczych, autor komponentu może napisać style obronne dla swojego elementu:

/* In the component’s style: */
.component .header {
    color: var(--header-color, blue);
}
.component .text {
    color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
    --text-color: #080;
    /* header-color isn’t set,
        and so remains blue,
        the fallback value */
}

Ta technika jest szczególnie przydatna do stylizacji komponentów internetowych, które korzystają z cienia DOM, ponieważ właściwości niestandardowe mogą przekraczać granice cienia. Autor komponentu internetowego może utworzyć początkowy projekt, używając wartości zastępczych, i ujawnić elementy motywu w postaci właściwości niestandardowych.

<!-- In the web component's definition: -->
<x-foo>
    #shadow
    <style>
        p {
        background-color: var(--text-background, blue);
        }
    </style>
    <p>
        This text has a yellow background because the document styled me! Otherwise it
        would be blue.
    </p>
</x-foo>
/* In the larger application's style: */
x-foo {
    --text-background: yellow;
}

Podczas korzystania z var() należy pamiętać o kilku kwestiach. Zmiennymi nie mogą być nazwy właściwości. Przykład:

.foo {
    --side: margin-top;
    var(--side): 20px;
}

Nie jest to jednak równoznaczne z ustawieniem margin-top: 20px;. Druga deklaracja jest nieprawidłowa i zostaje odrzucona jako błąd.

Podobnie nie możesz (nieprawidłowo) tworzyć wartości, której część jest podawana przez zmienną:

.foo {
    --gap: 20;
    margin-top: var(--gap)px;
}

Ponownie: to nie jest to samo co ustawienie margin-top: 20px;. Aby uzyskać wartość, musisz użyć czegoś innego: funkcji calc().

Tworzenie wartości za pomocą funkcji calc()

Jeśli nigdy wcześniej nie korzystałeś(-aś) z funkcji calc(), to jest ona przydatnym narzędziem, które pozwala wykonywać obliczenia w celu określenia wartości CSS. Jest on obsługiwany we wszystkich nowoczesnych przeglądarkach i może być łączony z właściwościami niestandardowymi w celu tworzenia nowych wartości. Na przykład:

.foo {
    --gap: 20;
    margin-top: calc(var(--gap) * 1px); /* niiiiice */
}

Praca z właściwościami niestandardowymi w JavaScript

Aby uzyskać wartość właściwości niestandardowej w czasie wykonywania kodu, użyj metody getPropertyValue() obiektu obliczonych deklaracji stylu CSS.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'

Aby w czasie wykonywania kodu ustawić wartość właściwości niestandardowej, użyj metody setProperty() obiektu CSSStyleDeclaration.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');

Wartość właściwości niestandardowej możesz też ustawić tak, aby w czasie wykonywania kodu odwoływała się do innej właściwości niestandardowej. W tym celu w wywołaniu funkcji setProperty() użyj funkcji var().

/* CSS */
:root {
    --primary-color: red;
    --secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');

Właściwości niestandardowe mogą się odwoływać do innych właściwości niestandardowych w Twoich arkuszach stylów, co może prowadzić do różnych ciekawych efektów w czasie wykonywania.

Obsługa przeglądarek

Obecnie właściwości niestandardowe są obsługiwane w Chrome 49, Firefox 42, Safari 9.1 i Safari na iOS 9.3.

Prezentacja

Wypróbuj przykład, aby zapoznać się ze wszystkimi interesującymi technikami, których możesz teraz używać dzięki usługom niestandardowym.

Więcej informacji

Jeśli chcesz dowiedzieć się więcej o usługach niestandardowych, przeczytaj artykuł Philipa Waltona z zespołu Google Analytics, w którym wyjaśnia on, dlaczego jest tak podekscytowany usługami niestandardowymi. Możesz też śledzić postępy w wdrażaniu tych usług w innych przeglądarkach na stronie chromestatus.com.