Egyedi CSS vagy Utility class?

Mikor milyen módszerrel érdemes egy komponenst megvalósítani?

2021.11.26 — Posted by Webb & Flow


Törekedni kell arra, hogy az elkészült HTML kód a lehető legrövidebb legyen, azonban emellett arra is figyelni kell, hogy a weblap kiszolgálása során az összes letöltendő kód (HTML + CSS + JS) se legyen túl hosszú.

A következő példában felépítünk egy doboz komponenst, amiben van egy kép, alatta egy title, egy description, az alatt pedig egy link.

A komponensek fejlesztése során két irányba indulhatunk:

Egyedi CSS kód

Ebben az esetben a komponenshez minden szükséges CSS kódot egyedileg írunk meg, a HTML kódban csak annyi kódot írunk, hogy egyértelműen beazonosítható legyen, hogy melyik elem micsoda.

HTML kód

<div class="my-custom-box-with-image">
    <img src="...">
    <div class="title">
        Ez a title
    </div>
    <div class="description">
        Ez a description
    </div>
    <a href="...">
        Tovább
    </a>
</div>

Látszik, hogy maga a HTML kód viszonylag rövid, mert csak egy-egy class-al beazonosítom a különböző elemeket a komponensemen belül. Emiatt viszont a CSS kódomat úgy kell megírnom, hogy az összes, ahhaz a konkrét komponenshez tartozó kód egy logikai egységet alkot. A CSS szelektorok szintaktikája miatt pedig ez egy elég hosszú CSS kódot eredményezhet:

.my-custom-box-with-image {
    border: 1px solid blue;
    padding: 1rem;
}

.my-custom-box-with-image img {
    width: 100%;
}

.my-custom-box-with-image .title {
    font-size: 1.5rem;
    margin-top: 1rem;
    margin-bottom: 1rem;
}

.my-custom-box-with-image .description {
    font-size: 0.75rem;
}

.my-custom-box-with-image a {
    color: green;
}

Reszponzivitás

Amennyiben reszponzív a komponens, például mobilon kisebbnek kell lennie a title-nek, akkor a klasszikus módon (opcionálisan a mobile first elveket betartva) megírhatjuk a különböző képernyő méretekre vonatkozó eltéréseket.

Ehhez kizárólag a CSS kódon kell változtatni:

/* alap esetben minden méreten 1rem legyen a betűméret */
.my-custom-box-with-image .title {
    font-size: 1rem;
    margin-top: 1rem;
    margin-bottom: 1rem;
}

@media (min-width: 992px) {
    /* 992px-től felfele 1.5rem legyen a betűméret */
    .my-custom-box-with-image .title {
        font-size: 1.5rem;
    }
}

Előnyök

  • ha az adott komponens sok helyen van használva, és előre tudjuk, hogy gyakran kell majd a komponens kinézetén változtatni, akkor ez jobban támogatja a fejlesztést, mert elég csak a CSS fájlt módosítani, és a HTML kód módosítása nélkül azonnal az egész oldalon megjelenik a módosított design
  • mivel viszonylag nehéz ebből a komponensből kiindulva egy új, hasonló komponenst csinálni, így nehezebben alakulnak ki komponens mutációk, illetve azonos célú, nagyon hasonló kinézetű komponensek
  • nem kell a HTML kódot módosítani, ha módosítani akarunk a reszponzív viselkedésen

Hátrányok

  • ha egy hasonló komponenst kell csinálni, amit ebből a komponensből kiindulva szeretnénk fejleszteni, akkor először az összes CSS kódot duplikálni kell, átírni a selector-okat, és elvégezni a módosításokat
  • mindenképpen kell tudni CSS-t is fejleszteni, ha el akarunk kezdeni kísérletezni az adott komponens módosításával
  • könnyen előfordulhat, hogy több különböző komponensben, ahol például a title kinézhetne ugyanúgy, mindegyik külön-külön title-t definiál, különböző kinézettel
  • tudni kell CSS kódot módosítani, ha módosítani akarunk a reszponzív viselkedésen

Utility class

Ebben az esetben a CSS kódban nem az egész komponenst fejlesztjük le, csak az egyes építő kockákat. Az építő kockákhoz tartozó CSS class-okat utility class-nak hívjuk, mert tipikusan nem magához az elemhez, hanem annak egy tulajdonságához írjuk meg.

HTML kód

<div class="padding-1 border-blue">
    <img src="..." class="width-100">
    <div class="font-size-1-5 margin-top-1 margin-bottom-1">
        Ez a title
    </div>
    <div class="font-size-0-75">
        Ez a description
    </div>
    <a href="..." class="text-green">
        Tovább
    </a>
</div>

és az ehhez tartozó CSS kód

.padding-1 {
    padding: 1rem;
}

.border-blue {
    border: 1px solid blue;
}

.width-100 {
    width: 100%;
}

.font-size-1-5 {
    font-size: 1.5rem;
}

.font-size-0-75 {
    font-size: 0.75rem;
}

.margin-top-1 {
    margin-top: 1rem;
}

.margin-bottom-1 {
    margin-bottom: 1rem;
}

.text-green {
    color: green;
}

Amennyiben Bootstrap-et használunk, az már eleve ad több utility class-t is, amit fel lehet használni, így kevesebb saját CSS kódot kell megírni, és betölteni a weblap kiszolgálásakor.

HTML kód

<div class="p-3 border-blue">
    <img src="..." class="img-fluid">
    <div class="font-size-1-5 my-3">
        Ez a title
    </div>
    <div class="font-size-0-75">
        Ez a description
    </div>
    <a href="..." class="text-green">
        Tovább
    </a>
</div>

így már csak a következő egyedi CSS kódra van szükség

.border-blue {
    border: 1px solid blue;
}

.font-size-1-5 {
    font-size: 1.5rem;
}

.font-size-0-75 {
    font-size: 0.75rem;
}

.text-green {
    color: green;
}

Reszponzivitás

Amennyiben reszponzív a komponens, akkor a utility class-okat is érdemes reszponzívan megírni, és a HTML kódban a megfelelő class-okat beírni.

HTML kód

<div class="p-3 border-blue">
    <img src="..." class="img-fluid">
    <div class="font-size-1 font-size-lg-1-5 my-3">
        Ez a title
    </div>
    <div class="font-size-0-75">
        Ez a description
    </div>
    <a href="..." class="text-green">
        Tovább
    </a>
</div>

és a szükséges CSS kód

/* alap esetben minden méreten 1rem legyen a betűméret */
.font-size-1 {
    font-size: 1rem;
}

@media (min-width: 992px) {
    /* ha ez a class be van állítva a HTML kódban, akkor 992px-től 1.5rem legyen a betűméret */
    .font-size-lg-1-5 {
        font-size: 1.5rem;
    }
}

Előnyök

  • könnyen lehet új komponenst készíteni, ami belül már létező építőkockákat használ
  • amennyiben az építőkockák halmazát nem kell bővíteni, tisztán HMTL kód módosítással is rengeteg játszóterünk van a komponens módosításához
  • erősen támogatja a módszer, hogy kevés építőkocka alakuljon ki, így például a title különböző dobozokban ugyanúgy nézzen ki
  • nem kell a CSS kódot módosítani, ha módosítani akarunk a reszponzív viselkedésen

Hátrányok

  • ha weblap szinten módosítani kell a komponenst, akkor mindenhol módosítani kell a HTML kódot, ahol használva van, és amennyiben statikus weblapról van szó, újra kell az összes érintett oldalt generálni
    • ezt a ConyCMS leegyszerűsítni a HTML Sablonok és Item Sablonok, illetve Script-et használatával
  • nagyon könnyen kialakulhat a már meglévő építőkockákból egy új olyan komponens, amihez nagyon hasonló már készült korábban, ezért több odafigyelést igényel a tervezés során, hogy elkerüljük a felesleges mutációk bevezetését
  • tudni kell HTML kódot módosítani, ha módosítani akarunk a reszponzív viselkedésen, és ehhez kell, hogy előre ki legyenek alakítva a reszponzív utility class-ok a CSS kódban

Mikor melyik módszert használjam?

Nem lehet egyértelműen azt mondani, hogy vagy az egyik, vagy a másik módszer a jó, minden esetben az adott weblap, vagy akár az adott komponens felhasználási igényeit mérlegelve kell dönteni, hogy melyik a jó megoldás.

Gyakori, hogy vegyesen készülnek wenlapok, azaz vannak olyan komponensek, amik egyedileg le vannak fejlesztve, és vannak olyanok, amik csak utility class-okkat vannak megvalósítva.

Az építőkockák önmagukban is lehetnek összetett komponensek, amik szintén elkészülhettek akár az egyik, akár a másik módszerrel, így akár egy komponensen belül is előfordulhat, hogy vegyesen van a két módszer alkalmazva.

Olyan eset is előfordulhat, hogy elkészül egy komponens egyedi CSS kóddal, és utána utility class-okkal kiegészítve a HTML kódját készítünk egy mutációt.

A Bootstrap vegyesen alkalmazza a két módszert, definiál rengeteg kész, azonnal felhasználható komponenst, amiknél bizonyos mutációkat a kifejezetten az adott komponenshez megírt utility class-okkal érhetünk el (például egy alert doboz színe), plusz kiegészíthetjük az univerzális utility class-okkal is (például egy p-* class, ha nagyobb belső térközt szeretnénk),

Ökölszabályként a következő szempontok szerint dönthetünk:

  • Egyedi CSS kód a jobb, ha
    • sok, azonos template-ű oldalon van felhasználva ugyanaz a komponens, és várhatóan gyakori lesz az utólagos módosítás (nem az átadás-átvétel alatt, hanem már az éles weblapon)
    • teljesen egyedi építőkockákból állnak a komponensek, tehát nincs rá esély, hogy az egyik komponensben használt egyik elemet fel lehet egy másik komponensben használni
    • nem számít, ha több kódot kell betöltenie a böngészőnek (főleg egyszerűbb weblapok esetén, ahol nincs sok komponens)
    • ha tudjuk, hogy a reszponzív viselkedést majd később, már az éles weblapon kell kikísérletezni
  • Utility class a jobb, ha
    • sikerül a komponens standardizálást odáig elvinni, hogy az építőelemeket is tudjuk standardizálni, és azokat több különböző komponensben is felhasználni
    • ha számít, hogy mennyi kódot kell betölteni a weblap kiszolgáláskor