CSS i Javascript

Do tej pory posługiwaliśmy się DOM, który umożliwiał nam działanie na elementach.

Dla CSS mamy podobną rzecz czyli CSSOM (The CSS Object Model), który jest zestawem różnych API służących do zarządzania stylami na stronie.

classList

Po pierwsze możemy utworzyć odpowiednie klasy, a następnie aplikować je dla danych elementów. Aby zarządzać klasami css danego elementu użyjemy interfejsu element.classList, która udostępnia nam kilka metod:

add(className) dodawanie klasy lub kilku klas
remove(className) usuwanie klasy lub kilku klas
toggle(className, *force) przełączanie (jak nie ma to dodaje, jak jest to usuwa) klasy. Dodatkowy drugi parametr wymusza dodanie (jeżeli jest true) lub usunięcie (jeżeli jest false) klasy.
contains(className) sprawdza czy element ma taką klasę

el.classList.add("btn");
el.classList.add("btn", "btn-primary", "inna-klasa");
el.classList.remove("btn", "inna-klasa");
el.classList.toggle("btn"); //dodaję jak nie ma, usuwam jak już jest
el.classList.toggle("btn", true); //dodaję
el.classList.contains("btn"); //true bo powyżej dodałem tą klasę

A dodatkowo jest tego jeszcze kilka. Wystarczy złapać dowolny element ze strony, wypisać go za pomocą console.dir, a następnie rozwinąć właściwość classList.

Spróbuj. Klikasz prawym dowolny element na stornie i wybierasz "Zbadaj element". Powinien ci się podświetlić w debuggerze. Przechodzisz do zakładki Console (ESC) i wpisujesz $0.classList.

Mamy też drugą właściwość - className.

Zwraca ona listę klas danego elementu w formie tekstowej. Możemy ją też wykorzystać do dodania wielu klas na raz:


element.className = "button button-big button-important";
element.className += " inna-klasa inna-klasa2";

style

Kolejnym sposobem dodawania styli jest użycie właściwości style. Dzięki niej możemy ustawić ale i odczytać style inline nadane dla danego elementu.


btn.style.backgroundColor = "#4BA2EA";
btn.style.fontSize = "1.6rem";
btn.style.borderRadius = "3rem";
btn.style.color = "#F7F781";

console.log("Kolor przycisku to: ", btn.style.backgroundColor);
console.log("Kolor tekstu to: ", btn.style.color);
console.log("A wielkość tekstu to: ", btn.style.fontSize);

Jeżeli właściwość składa się z jednego słowa, to zapisujemy ją tak jak w css. Jeżeli właściwość składa się z kilku słów oddzielonych myślnikiem, wtedy dla takiej właściwości musimy zastosować zapis camelCase. Możemy tutaj też zastosować zapis znany z obiektów:


el.style.fontSize = "1rem";
el.style.background = "linear-gradient(#fff, #ddd)";
el.style.backgroundColor = "rgba(255,255,255,0.5)";

//lub
el.style["font-size"] = "1rem";
el.style["background"] = "linear-gradient(#fff, #ddd)";
el.style["background-color"] = "rgba(255,255,255,0.5)";

Jeżeli chcielibyśmy ustawić kilka wartości na raz, możemy to zrobić tak jak powyżej, ale też skorzystać z właściwości cssText:


el.style.cssText = `
    color: red;
    background: blue;
    padding: 10px;
`;

Staraj się nie nadawać całych styli za pomocą powyższych właściwości. Stosuj je raczej tylko w przypadku, gdy dane style muszą być dynamicznie - np. gdy generujesz losowe tło dla elementu. Jeżeli jednak style są statyczne, o wiele lepszym rozwiązaniem będzie trzymanie ich w pliku css w postaci dodatkowej klasy i dodawanie jej do elementu za pomocą classList. Dzięki temu oddzielasz warstwę wizualną od logicznej*

getComputedStyle()

Jeżeli ustawiamy style za pomocą powyższych sposobów, są one wstawiane inline w atrybucie style danego elementu.

style przycisku

Podobna zasada tyczy się odczytu. Jeżeli dany element nie ma ustawionych styli inline (wpisanych z palca w HTML, lub za pomocą JavaScript), to nie jesteśmy w stanie ich pobrać.


<button class="btn" style="height: 100px;">
    klik
</button>

const btn = document.querySelector(".btn");

console.log(btn.style.fontSize); //""
console.log(btn.style.backgroundColor); //""
console.log(btn.style.height); //"100px"

//ustawiamy style inline
btn.style.fontSize = "1.5rem";
btn.style.backgroundColor = "#4BA2EA";

console.log(btn.style.fontSize); //"1.5rem"
console.log(btn.style.backgroundColor); //"#4BA2EA"

W wielu sytuacjach praca na stylach inline nie będzie wystarczająca. Gdy badasz dany element w debuggerze, w zakładce Elements pokazuje ci po prawej stronie jego style. Tuż obok zakładki Styles jest zakładka Computed, która pokazuje style przeliczone, czyli takie, jak je widzi przeglądarka (np. ty ustawiasz wielkość 2em, a przeglądarka widzi to jako 32px).

Zakładka computed

Żeby pobrać takie przeliczone stylowanie musimy skorzystać z funkcji
window.getComputedStyle(elem, pseudoElement*).

Pierwszy parametr tej metody określa element, dla którego chcemy pobrać przeliczone style. Drugi - opcjonalny - pozwala pobierać style dla pseudo elementów (wtedy podajemy selektor jako np. ::before lub ::after):


const btn = document.querySelector(".button");
const style = getComputedStyle(btn);

console.log( style.height );
console.log( style.backgroundColor );

Jak zauważysz, nie zawsze będą to style identyczne do tych jakie wpisałeś w pliku css. Przykładowo jeżeli my ustawimy kolor red, pobierzemy go w postaci rgb(255, 0, 0), jeżeli ustawimy wielkość w em lub rem, zwracana wartość będzie w px, bo tak te wartości widzi przeglądarka.

Style pobrane za pomocą getComputedStyle() są tylko do odczytu. Próba zmiany ich wartości zakończy się błędem. Dodatkowo style takie odzwierciedlają aktualne style na stronie, co oznacza, że raz pobrane, automatycznie będą się aktualizować:


const btn = document.querySelector("button");
const s = getComputedStyle(btn);
console.log(s.width);

btn.addEventListener("click", () => {
    btn.style.width = "10em";
    console.log(s.width); //automatycznie się zaktualizowało
});

setProperty() i getPropertyValue()

Gdy wypiszesz sobie w konsoli debuggera właściwość element.style, zobaczysz, że udostępnia ona nam jeszcze kilka ciekawych rzeczy.

Wśród nich są dwie metody:

setProperty(propertyName, value, priority*) służy do ustawiania stylowania. Ostatni opcjonalny parametr priority służy do ewentualnego dodania deklaracji !important. Najczęściej jest pomijany.
getPropertyValue(property) służy do pobierania stylowania

document.body.style.setProperty("background-color", "#4BA2EA");
document.body.style.setProperty("font-size", "1.5rem");

document.body.style.getProperty("background-color");
document.body.style.getProperty("font-size");

Zastosowanie tych metod jak w powyższym kodzie jest raczej bez sensu, ponieważ właściwości takie możesz bez problemu ustawiać i pobierać za pomocą wcześniej pokazanej krótszej składni. Metody te mają jednak zastosowanie przy pracy ze zmiennymi css:


el.style.setProperty("--size", "1em");
el.style.getPropertyValue("--size"); //"1em"

A jeżeli połączymy to z pobieraniem przeliczonych styli, zmienne takie stają się swoistą furtką, która może łączyć css z Javascriptem:


const size = getComputedStyle(element).getPropertyValue("--size");

element.setProperty("--size:", `{++size}`);

Co pozwala nam traktować to jako swoisty kolejny punkt komunikacji między JS - CSS.

Poniżej mini przykład korzystający z tej techniki:


<div class="demo">
    <div class="element"></div>

    <div class="controls">
        <span>Kolor: <input type="range" min="0" max="360" value="0"></span>
    </div>
</div>

const demo = document.querySelector(".demo");
const el = demo.querySelector(".element");
const input = demo.querySelector("input");

//domyślną wartość pobieram z pliku css
input.value = getComputedStyle(demo).getPropertyValue("--hue");

input.addEventListener("input", () => {
    demo.style.setProperty(`--hue`, input.value);
})

.demo {
    --hue: 40;
    --color: hsl(var(--hue), 90%, 50%);
    --shadow: hsl(var(--hue), 90%, 20%);

    border: 10px solid var(--color);
}
.demo .element {
    ...
    ...
    background: var(--color);
    color: var(--color);
    box-shadow: 0 0 430px 130px var(--color);
}
A
Kolor:

Inne przykłady możesz znaleźć w jednych z kilku moich eksperymentów np. tutaj i tutaj

Trening czyni mistrza

Jeżeli chcesz sobie potrenować zdobytą wiedzę, zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania

Wszelkie prawa zastrzeżone. Jeżeli chcesz używać jakiejś części tego kursu, skontaktuj się z autorem.
Aha - i ta strona korzysta z ciasteczek.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.