Mixiny

V této části se dozvíte jak používat mixiny. Mixiny nám umožňují získat vlastnosti z jedné třídy nebo ID do druhé třídy nebo id tím, že zapíšeme jméno třídy nebo id do těla selektoru jak ukazuje následující ukázka. Rozdíl mezi extendnutím a mixiny je ten, že mixiny vlastnosti z třídy/id zkopírují, extend jen připíše nový selektor k selektoru z kterého extenduje.

// LESS

.a, #b {
    color: red;
}

.mixin-trida {
    // závorky v době psaní tutoriálu nejsou povinné, ale mohou
    // být povinné v budoucnu, takže je lepší je používat
    .a();
}

#mixin-id {
    #b();
}
/* zkompilované CSS */

.a, #b {
    color: red;
}

.mixin-trida {
    color: red;
}

#mixin-id {
    color: red;
}

Vytváření mixinů které nebudou ve zkompilovaném CSS

Pokud nechceme aby byla naše třída/id, kterou používáme jako mixin v souboru se zkompilovaným CSS kódem, tak můžeme při jejím vytváření přidat na konec závorky.

// LESS

.muj-mixin {
    color: red;
}

// tato třída nebude ve zkompilovaném CSS
.muj-dalsi-mixin() {
    background: white;
}

.trida {
    .muj-mixin();
    .muj-dalsi-mixin();
}
/* zkompilované CSS */

.muj-mixin {
    color: red;
}

.trida {
    color: red;
    background: white;
}

Selektory v mixinech

Mixiny mohou obsahovat více než vlastnosti. Mohou obsahovat také selektory.

// LESS

.muj-hover-mixin() {
    &:hover {
        border: 2px solid red;
    }
}

button {
    .muj-hover-mixin();
}
/* zkompilované CSS */

button:hover {
    border: 2px solid red;
}

Jmenné prostory

Pokud máme třeba více podobných mixinů a chceme si je seskupit dohromady aby byl náš kód čitelnější, tak si můžeme vytvořit selektor do kterého je všechny umístíme. Jak to udělat ukazuje následující ukázka kódu.

// LESS

#moje-mixiny() {
    .prvni-mixin {
        color: black;
    }
    .druhy-mixin {
        color: yellow;
    }
}

.trida {
    // použití mixinu z jmenného prostoru
    #moje-mixiny.prvni-mixin();
}
/* zkompilované CSS */

.trida {
    color: black;
}

Jmenné prostory mohou obsahovat také podmínku, která musí platit aby se mixin aplikoval. Jak takovou podmínku vytvořit ukazuje následující ukázka.

// LESS

@mode: huge;

// mixiny v tomto jmenném prostoru se aplikují jen
// když se bude proměnná @mode rovnat huge
#moje-mixiny() when (@mode = huge) {
    .prvni-mixin {
        color: black;
    }
    .druhy-mixin {
        color: yellow;
    }
}

.trida {
    // protože podmínka jmenného prostoru platí tak se mixin aplikuje
    #moje-mixiny.prvni-mixin();
}
/* zkompilované CSS */

.trida {
    color: black;
}

Podmínky nemusíme aplikovat jen na jmenné prostory, ale také na samotné mixiny jak ukazuje následující ukázka.

// LESS

@mode: huge;

// mixin s podmínkou
#muj-mixin() when (@mode = huge) {
    color: lightgreen;
}

h1 {
    // protože podmínka mixinu platí tak se mixin aplikuje
    #muj-mixin();
}
/* zkompilované CSS */

h1 {
    color: lightgreen;
}

Klíčové slovo !important

Pokud při použití mixinu připíšeme na konec klíčové slovo !important, tak se všechny vlastnosti v mixinu označí jako důležité (zapíše se za ně !important). Klíčové slovo !important označuje v CSS vlastnost u které by se neměla přepsat hodnota (například jinými selektory).

// LESS

#muj-mixin() {
    color: lightgreen;
}

h1 {
    // použití mixinu s připsáním !important ke všem jeho vlastnostem
    #muj-mixin() !important;
}
/* zkompilované CSS */

h1 {
    color: lightgreen !important;
}

Mixiny s parametry

Mixiny mohou také přijímat argumenty. Když bychom mixin, který přijímá argumenty někde chtěli použít, tak mu musíme předat nějakou hodnotu s kterou bude pracovat. Následující ukázka ukazuje jak mixin, který přijímá argumenty vytvořit a jak ho použít.

// LESS

// mixin přijímající argument
.border(@radius) {
    border: 2px solid yellow;
    border-radius: @radius;
}

button {
    // použití mixinu s předáním argumentu
    .border(10px);
}

a {
    .border(5px);
}
/* zkompilované CSS */

button {
    border: 2px solid yellow;
    border-radius: 10px;
}

a {
    border: 2px solid yellow;
    border-radius: 5px;
}

Pokud chceme, tak můžeme nastavit argumentům nějakou defaultní hodnotu a umožnit tak jejich použití i bez argumentu.

// LESS

// mixin s parametrem, který má defaultní hodnotu
.border(@radius: 5px) {
    border: 2px solid yellow;
    border-radius: @radius;
}

button {
    // použití mixinu s předáním argumentu
    .border(10px);
}

a {
    // použití mixinu bez předání argumentu
    .border();
}
/* zkompilované CSS */

button {
    border: 2px solid yellow;
    border-radius: 10px;
}

a {
    border: 2px solid yellow;
    border-radius: 5px;
}

Mixiny mohou přijímat více parametrů, stačí je oddělit čárkou nebo středníkem.

// LESS

// mixin přijímající více argumentů
.border(@width, @radius) {
    border-width: @width;
    border-style: solid;
    border-color: yellow;
    border-radius: @radius;
}

button {
    .border(2px, 10px);
}
/* zkompilované CSS */

button {
    border-width: 2px;
    border-style: solid;
    border-color: yellow;
    border-radius: 10px;
}

Když používáme mixiny přijímající více argumentů, tak nemusíme dodržovat pořadí ve kterém jednotlivé argumenty předáváme. Musíme ale určit pro jakou proměnnou v parametrech mixinu daný argument je. Následující ukázka ukazuje jak to provést.

// LESS

.border(@width, @radius) {
    border: @width solid orange;
    border-radius: @radius;
}

button {
    .border(@radius: 10px, @width: 3px);
}
/* zkompilované CSS */

button {
    border: 3px solid orange;
    border-radius: 10px;
}

Speciální @arguments proměnná

Uvnitř mixinu můžeme použít speciální proměnnou, která se jmenuje @arguments. Tato proměnná obsahuje všechny hodnoty argumentů předaných do mixinu. Může se nám to hodit např. u některých zkratek vlastností, abychom nemuseli všechny hodnoty vypisovat ručně.

// LESS

.box-shadow(@x: 0, @y: 0, @blur: 1px, @color: #ffffff) {
    box-shadow: @arguments;
}

button {
    .box-shadow(3px, 3px);
}
/* zkompilované CSS */

button {
    box-shadow: 3px 3px 1px #ffffff;
}

Přijímání neurčitého počtu argumentů

Pokud chceme, tak můžeme vytvořit mixin, který bude přijímat neurčitý počet argumentů. Můžeme například určit že se bude zadávat jeden argument a ostatní necháme na uživateli, který bude s mixinem pracovat. Neurčitý počet argumentů zapíšeme pomocí tří teček, jak ukazuje následující ukázka a tyto argumenty potom obsahuje speciální proměnná, která se jmenuje @rest.

// LESS

// mixin s neurčitým počtem argumentů
.mixin(@color, ...) {
    color: @color;
    margin: @rest;
}

button {
    // zavolání mixinu s jedním povinným
    // parametrem a dvěma navíc
    .mixin(#de1258, 5px, 10px);
}
/* zkompilované CSS */

button {
    color: #de1258;
    margin: 5px 10px;
}

Přetěžování mixinů

Pokud chceme, můžeme si vytvořit více mixinů se stejným názvem, ale s jinými parametry. Když potom mixin použijeme, tak se podle argumentů vybere jaké mixiny se aplikují a jaké ne.

// LESS

// mixiny se stejným jménem ale jinými parametry
.mixin(@color) { // aplikuje se
    color: @color;
}
.mixin(@color, @padding: 2px) { // aplikuje se
    color: @color;
    padding: @padding;
}
.mixin(@color, @padding, @margin: 2px) { // neaplikuje se
    color: @color;
    padding: @padding;
    margin: @margin @margin @margin @margin;
}

p {
    // jaké mixiny se aplikují se rozhodne podle předaných argumentů
    .mixin(#ffffff);
}
/* zkompilované CSS */

p {
    color: #ffffff;
    padding: 2px;
}

Výběr mixinu podle předané hodnoty

Někdy můžeme chtít změnit chování mixinu podle hodnoty předaného argumentu. Následující ukázka ukazuje jak to udělat. Namísto proměnné napíšeme k mixinu do závorek hodnotu, kterou musí argument mít aby se mixin aplikoval.

// LESS

.mixin(dark, @color) { // neaplikuje se
    color: darken(@color, 10%);
}
.mixin(light, @color) { // aplikuje se
    color: lighten(@color, 10%);
}
.mixin(@_, @color) { // aplikuje se (neobsahuje hodnotu, jen proměnné)
    display: block;
}

@switch: light;

.trida {
    .mixin(@switch, #888888);
}
/* zkompilované CSS */

.trida {
    color: #a2a2a2;
    display: block;
}

Používání mixinů jako funkcí

V LESS můžeme získat pomocí hranatých závorek při použití mixinu nějakou hodnotu, která se v mixinu nachází. Následující ukázka kódu používá mixin k určení průměru dvou hodnot.

// LESS

.prumer(@a, @b) {
    @vysledek: ((@a + @b) / 2);
}

div {
    // použití mixinu a získání hodnoty proměnné
    // @vysledek, která se uvnitř mixinu nachází
    padding: .prumer(16px, 50px)[@vysledek];
}
/* zkompilované CSS */

div {
    padding: 33px;
}

U předchozí ukázky jsme ani nemuseli určovat jakou proměnnou/vlastnost chceme a mohli jsme nechat závorky prázdné, protože se v mixinu nachází jen jedna proměnná. Pokud necháme závorky prázdné, tak se vezme poslední položka v mixinu.

// LESS

.prumer(@a, @b) {
    @vysledek: ((@a + @b) / 2);
}

div {
    // takto také můžeme získat výsledek mixinu .prumer
    padding: .prumer(16px, 50px)[];
}
/* zkompilované CSS */

div {
    padding: 33px;
}

Rekurzivní mixiny

V LESS mohou mixiny mohou volat sami sebe. S použitím podmínek můžeme vytvořit různé cyklické struktury. Ukázka kódu níže ukazuje co bychom díky tomu mohli například vytvořit.

// LESS

.generate-columns(@n, @i: 1) when (@i =< @n) {
    .column-@{i} {
        width: (@i * 100% / @n);
    }

    // mixin volá sám sebe
    .generate-columns(@n, (@i + 1));
}

.generate-columns(4);
/* zkompilované CSS */

.column-1 {
    width: 25%;
}
.column-2 {
    width: 50%;
}
.column-3 {
    width: 75%;
}
.column-4 {
    width: 100%;
}

Mixiny s podmínkami

Jak už bylo ukázáno v této části u jmenných prostorů, mixiny mohou obsahovat podmínku. Mixin s podmínkou vytvoříme tak, že za název mixinu napíšeme slovo "when" a za něj do závorek podmínku, která musí platit aby se mixin aplikoval.

// LESS

// tento mixin se aplikuje jen pokud bude platit podmínka
.mixin(@a) when (lightness(@a) >= 50%) {
    background-color: black;
}
// tento mixin se aplikuje jen pokud bude platit podmínka
.mixin(@a) when (lightness(@a) < 50%) {
    background-color: white;
}
.mixin(@a) {
    color: @a;
}

.trida1 { .mixin(#ddd) }
.trida2 { .mixin(#555) }
/* zkompilované CSS */

.trida1 {
    background-color: black;
    color: #ddd;
}
.trida2 {
    background-color: white;
    color: #555;
}

Operátory, které můžeme při vytváření podmínek použít jsou následující: >, >=, =, =<, <. Pokud potřebujeme pro mixin vytvořit více podmínek, tak můžeme použít logický operátor and jak ukazuje následující ukázka.

// LESS

.mixin(@a) when (isnumber(@a)) and (@a > 0) {
    width: @a;
}

.trida { .mixin(30px) }
/* zkompilované CSS */

.trida {
    width: 30px;
}

Pokud chceme mít více podmínek u kterých chceme aby alespoň jedna platila, můžeme je oddělit čárkou jak ukazuje následující ukázka.

// LESS

// alespoň jedna z těchto dvou podmínek
// musí platit aby se mixin aplikoval
.mixin(@a) when (@a > 10), (@a < -10) {
    width: @a;
}

.trida { .mixin(30px) }
/* zkompilované CSS */

.trida {
    width: 30px;
}

Občas můžeme chtít aby se mixin aplikoval když podmínka neplatí. To můžeme zajistit připsáním slova "not" před podmínku.

// LESS

// tento mixin se aplikuje když
// bude argument záporné číslo
.mixin(@a) when not (@a > 0) {
    margin-left: @a;
}

.trida { .mixin(-5px) }
/* zkompilované CSS */

.trida {
    margin-left: -5px;
}

V podmínkách se nám také může hodit kontrolovat typ hodnoty, kterou argumenty obsahují. Můžeme k tomu použít tyto funkce: iscolor, isnumber, isstring, iskeyword, isurl, ispixel, ispercentage, isem, isunit.

Uložení mixinu do proměnné

Mixiny je možné uložit do proměnné a později tuto proměnnou použít stejným způsobem jako mixin samotný.

// LESS

#library() {
    .colors() {
        background: green;
    }
}

.box {
    // uložení mixinu do proměnné
    @alias: #library.colors();
    // použití mixinu přes proměnnou
    @alias();
}
/* zkompilované CSS */

.box {
    background: green;
}

Sloučení hodnot stejných vlastností

Pokud to CSS vlastnosti dovolují, tak můžeme mixiny nastavit tak, aby některé vlastnosti nepřepisovali ale jen k nim přidali další hodnotu. To zajistíme přidáním znaku "+" za vlastnost, ke které chceme přidat hodnotu.

// LESS

.mixin() {
    box-shadow+: inset 0 0 10px #555;
}

.moje-trida {
    .mixin();
    // připojení hodnoty na konec
    box-shadow+: 0 0 20px black;
}
/* zkompilované CSS */

.moje-trida {
    // hodnoty vlastnosti box-shadow se sloučili dohromady
    box-shadow: inset 0 0 10px #555, 0 0 20px black;
}

V předchozí ukázce znak "+" zajistí, že se hodnota připojí na konec hodnot vlastnosti. Pokud bychom ale chtěli hodnotu připojit na začátek, tak za znak "+" napíšeme ještě podtržítko.

// LESS

.mixin() {
    box-shadow+_: inset 0 0 10px #555;
}

.moje-trida {
    .mixin();
    // připojení hodnoty na začátek
    box-shadow+_: 0 0 20px black;
}
/* zkompilované CSS */

.moje-trida {
    box-shadow: 0 0 20px black, inset 0 0 10px #555;
}
pokračovat na další část