Jak poprawić wydajność CSSów

Pierwszy wpis, na początek, mam nadzieję, że przyda się Wam do optymalizacji CSSów 🙂

W dzisiejszym poście opiszę jak bardziej efektywnie pisać CSS-y, żeby docelowo zmniejszyć rozmiar strony internetowej i poprawić czas ładowania.

CSSy czytane są przez przeglądarkę od strony prawej do lewej. Im mniej selektorów, zagnieżdżeń – tym lepiej, ponieważ przeglądarka musi „przekopać się” przez strukturę drzewiastą – im jest dłuższa, tym wymaga więcej „nakładu pracy”.

Na wstępie opiszę, w jaki sposób klasyfikowany jest system reguł CSS.

Reguła, to cały ciąg selektorów, na podstawie których „wybierane” są elementy dokumentu HTML do ostylowania np. regułą jest wyrażenie:

#container .middle p > span { …… }

System stylów dzieli reguły CSS na cztery główne kategorie:

  1. ID – selektory ID, których nazwa poprzedzona jest znaczkiem hasz „#”, a w znaczniku posiadają atrybut id ( np. <div id=”container”></div>) i mogą być raz użyte w obrębie dokumentu
  2. CLASS – selektory klasy, których nazwa poprzedzona jest znakiem kropki (.klasa), a w znaczniku HTML posiadają atrybut class ( np. <nav class=”main”></nav> ), nazwa klasy może być użyta w obrębie dokumentu wielokrotnie i do wielu różnych znaczników, dzięki czemu konkretnym stylem możemy upiększyć wiele różnych elementów ( <p class=”red”>, <span class=”red”> – poprawnie )
  3. TAG – selektory tagów, są to selektory bez klas i id, klasyczne np. p, span, i, td, ul, img
  4. UNIWERSALNE – to selektory nie będące tagami, wszystkie pozostałe reguły

Istotne jest, żeby zrozumieć te kategorie, jako podstawę budowania bloków reguł dopasowywania.

Ostatnią część reguły CSS (część, która pasuje do dopasowywanego elementu, a nie przodków), nazywa się selektorem kluczowym, np selektorami kluczowymi wyrażeń :

a img, ul li a, div > p, h1 + title { … }

będą

img, a, p, title.

 

BIERZEMY POD UWAGĘ SELEKTOR KLUCZOWY I REGUŁY KLASYFIKUJEMY NA:

REGUŁY ID

Pierwsza kategoria systemu reguł składa się z tych reguł, które jako selektor kluczowy mają selektor ID ( w kodzie html zawierają atrybut id=”nazwaID” ) , np

buton#submitBtn {…}

#label[for=”name”] {…}

nav > ul > li#item1:active { … }

 

REGUŁY KLAS

Zawiera te reguły, które w selektorze kluczowym posiadają klasę ( a w kodzie html zawierają atrybut class=”nazwaKlasy” ):

buton.help {…}

.boldText {…}

nav.generalMenu > .menuLeft[checked=”true”] {…}

 

REGUŁY TAGÓW

W przypadku braku określonych klas lub id w selektorze kluczowym, to kategorią jest tag.

div { …}

.tree > p { … }

input[type=”checkbox”] { … }

 

REGUŁY UNIWERSALNE

To wszystkie pozostałe reguły, np.

input > [checked=”checked”] { … }  – selektor kluczowy to atrybut wewnątrz elementu input

[hidden=”true”] – to jest atrybut nie tag

 

ZASADY DOPASOWYWANIA REGUŁ PRZEZ SYSTEM STYLÓW CSS

System stylów dopasowuje reguły od prawej do lewej – rozpoczyna od selektora klucza, następnie przemieszcza się w lewo ( szukając przodków danej reguły ). Dopóki poddrzewo selektora kontynuuje sprawdzanie, tak długo system stylów kontynuuje przemieszczanie się w lewo aż do momentu, kiedy dopasuje elementy do reguły, albo zrezygnuje z powodu niedopasowania, czyli np.

Mając regułę : .section ul li p – system stylów najpierw wybierze z dokumentu wszystkie elementy <p>, następnie kierując się w lewo, będzie filtrować elementy p i zostawi tylko te, które jako swojego przodka mają element <li>, zaś następnie pozostałe elementy będą filtrowane i pozostaną tylko te, które mają przodka <ul>, a następnie te element o klasie section.

Kategorie, wg których podzielone są reguły CSS stworzone są po to, by móc szybciej odfiltrować nieistotne reguły ( dzięki czemu system nie traci czasu próbując je dopasować ). I to jest klucz do znacznego zwiększenia wydajności CSS. Im mniej reguł jest wymaganych w celu sprawdzenia danego elementu, tym style będą szybciej analizowane.

Przykład:

Jeśli element zawiera ID, to zostaną sprawdzone tylko reguły ID pasujące do wskazanego elementu ID. Z kolei tylko reguły klasy będą sprawdzane dla elementów klasy i tagi dla tagów.

 

WSKAZÓWKI OPTYMALIZACYJNE

1.  UNIKAJ UNIWERSALNYCH REGUŁ CSS ( np. [checked=”checked”])

2.  Nie łącz reguł ID z nazwami klas lub tagów. 

Jeśli reguła ma selektor ID jako kluczowy selektor, to nie dodawaj nazwy tagu do reguły CSS. Dopóki ID są unikatowe, dodawanie nazwy tagu niepotrzebnie spowolni proces dopasowywania.

    NIEPRAWIDŁOWO:

buton#register {…}    // tag button łączony jest z id

.oferts#ofert-1 {…} // klasa łączona z id

    PRAWIDŁOWO:

#register {… }

#ofert-1 {…}

Wyjątkiem jest sytuacja, kiedy zmieniamy dynamicznie jakąś klasę elementu w celu zastosowania różnych stylów w różnych sytuacjach,      ale te elementy powinny posiadać wspólną klasę.

3.  Nie łącz reguł klasy z nazwami tagów

poprzednia koncepcja odnosi się także w tym przypadku. Choć klasy mogą być używane na stronie wielokrotnie, to nadal są bardziej unikatowe niż tagi, dlatego nie ma potrzeby ich niepotrzebnie łączyć.  Jedną z konwencji, jaką można zastosować jest użycie nazwy znacznika w nazwie klasy. Może to kosztować pewną elastyczność, ponieważ jeśli mamy w projekcie zmiany w znaczniku, to nazwy klas też musimy zmienić. Najlepiej jest wybrać nazwy ściśle semantyczne, jeśli elastyczność jest jednym z celów oddzielenia stylów – przykład:

BŁĘDNIE:

p.alert {}

LEPIEJ:

.alert-p {}

NAJLEPIEJ: 

.marginBtm { … }

4. Stosuj najbardziej specyficzne, konkretne kategorie klasyfikacji stylów, jak to możliwe.

NAJWIĘKSZYM POWODEM SPOWOLNIENIA CSS JEST ZBYT WIELE REGUŁ W KATEGORII TAGÓW.

Poprzez dodanie klas do elementów, możemy dodatkowo podzielić te reguły na reguły klasy, a to wyeliminuje czas potrzebny na próbę dopasowania zasad dla danego tagu.

Np. zamiast

li p span { color: red;… }

należy zapisać:

li p span.red { color: red; } ( ALE TU MAMY NIEPOTRZEBNĄ KATEGORIĘ TAGU PRZED KATEGORIĄ KLASY )

a najlepiej

.red { color: red; } i klasę „red” przypisać znacznikowi <span>

5.  Unikaj selektora potomka 

Selektor potomka jest najdroższym selektorem w CSS. Jest piekielnie drogi – szczególnie, jeśli selektor jest w kategorii tagu lub kategorii uniwersalnej i jest ustawiony najbardziej po prawo i jest dużo elementów na stronie. Przodek leży wyżej w drzewie dokumentu, nie koniecznie musi być jeden rząd wyżej potomka.

przodek1 przodek2 … potomek { cecha: wartość }

Najbardziej pożądanym rozwiązaniem jest selektor dziecka.

rodzic > dziecko { cecha: wartość }

Znacznik, będący dzieckiem, musi znajdować się bezpośrednio wewnątrz znacznika rodzica. Nie należy ich jednak nadużywać bez konkretnego uzasadnienia. Przykład złego użycia:

BŁĘDNIE:

table tr td span { … }

LEPIEJ, ALE NADAL ŹLE:

table > tr > td > span { … }

6.  Reguły kategorii tagów nigdy nie powinny zawierać selektorów dziecka – unikaj używania selektora dziecka z regułami z kategorii tagów.

To dramatycznie wydłuża czas dopasowywania ( zwłaszcza , jeśli reguła może zostać dopasowana ) dla wszystkich wystąpień tego elementu. Lepiej selektorowi nadać klasę. Wracając do poprzedniego przykładu,

BŁĘDNIE:

table > tr > td > span { color: red; … }

DOBRZE: 

.span-red { … }, albo po prostu .red { … }

7.  Pozwól na dziedziczenie cech

Dowiedz się, które cechy są dziedziczone i pozwól im na to. Niektóre reguły są rodzica są dziedziczone w dół, tj. np niektóre cechy elementów listy, np obrazki.

Zamiast np. ustawiać znacznik i obraz na początku każdego elementu listy, można ustawić go na elemencie rodzica ( ul ) ponieważ właściwość ta jest dziedziczona do wszystkich elementów listy.

 

BŁĘDNIE:

#bookmarkMenuItem >  .menu-left { list-style-image: url(image.png) }

 

W powyższym przykładzie, przede wszystkim należałoby zakończyć regułę CSS na poziomie ID, ponieważ jest to najbardziej szczegółowy selektor. Poza tym właściwość list-style-image można ustawić już na poziomie rodzica i wartość będzie dziedziczona na elementach, należy zrobić tak:

DOBRZE:

#bookmarkMenuItem { list-style-image: url(image.png) }

8.  Unikaj specyficznych tagów i właściwości ( np. prefixy, tagi eksperymentalne )

chyba, że to konieczne. Nieaktualne USUWAJ.

Czasem występują specyficzne dla przeglądarki eksperymentalne tagi lub właściwości CSS, które są prefiksowane ( ze słowem kluczowym identyfikującym przeglądarkę, np. –webkit, -moz, -o, -ms ). Z czasem pojedynczy tag lub właściwość są normalizowane, prefiksy są usuwane. Np. zanim border-radius został ustandaryzowany i zaimplementowany przez wszystkie główne przeglądarki, trzeba było używać –webkit-border-radius i –moz-border-radius, itp. Mając na uwadze to i zmiany, jakie zachodzą w standaryzacji tagów i właściwości, starajmy się nie używać ich w regułach, a jeśli chcemy – pamiętać o ich późniejszym usunięciu.

 

PODSUMOWANIE

1. Unikaj uniwersalnych reguł CSS ( np. [checked=”checked”] )

2. Nie łącz reguł ID z nazwami klas lub tagów ( nie łączyć: li#item_1, .wrapper#container => zamiast tego: #item_1, #container)

3. Nie łącz reguł Klasy z nazwami tagów ( np. p.red, span.description => zamiast tego: .red, .description )

4. Szybka ścieżka – Stosuj najbardziej specyficzne, konkretne ( id, klasy)  kategorie klasyfikacji stylów.

5. Unikaj selektora potomka ( przodek1 przodek2 … potomek { cecha: wartość } ) , Jeśli już musisz, stosuj selektor dziecka ( rodzic > dziecko, gdzie rodzic leży o jeden rząd wyżej w hierarchii drzewa dokumentu )

6. Unikaj używania selektora dziecka z regułami z kategorii tagów. Lepiej selektorowi nadać klasę .

7. Pozwól na dziedziczenie cech po rodzicach.

8. Unikaj specyficznych tagów i właściwości  ( np. prefixy, tagi eksperymentalne ), nieaktualne USUWAJ.

9. Stosuj shorthandy

10. Unikaj obciążających stylów CSS, tj. opacity, animation

 

Zapraszam do komentowania, opiniowania i pytań.

Dodaj komentarz