Wprowadzenie do preprocesorów ~ SASS


  • Admin

    Cześć w dzisiejszym wpisie omówimy sobie jeden z preprocesorów jakim jest SASS.

    Co to jest SASS?

    Dobra wstęp mamy już za sobą, teraz czas na szybki przegląd - przede wszystkim istnieją dwie implementacje (jak wszystko w informatyce - nie ma jednej, jedynej słusznej drogi). Istnieje SCSS oraz SASS i takie też mamy rozszerzenia dla tych plików - różnią się praktycznie wyłącznie składnią i kilkoma mało istotnymi niuansami.

    Dla jasności w tym wprowadzeniu skupimy się głównie na SCSS z racji tego, że jest on bliższy temu co zapewne znacie czyli zwykłemu CSS'owi, składnia tego drugiego jest nieco bardziej przejrzysta ponieważ bazuje na wcięciach (nie klamrach) dlatego przypomina trochę pisanie w Python'ie.

    Aby zacząć praktycznie będziemy potrzebować wyłącznie VScode i dwóch dodatków Live Server oraz Live Sass Compiler. Instalacje dodatków jak i samego IDE pozostawiam Wam, nie ma chyba nic co mogłoby spędzić sen z powiek komukolwiek kto czyta ten tutorial.

    Myślę, że jest to najprostszy set-up bez kombinowania z skryptami w Node.js, Ruby czy dedykowanymi kompilatorami z GUI jak Koala i inne.

    Gdy to będziemy mieli tworzymy prosty plik HTML:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
    </body>
    </html>
    

    VS ma wbudowanego Emmet'a więc wystarczy utworzyć plik index.html a następnie napisać napisać ! i nacisnąć Tab potem wystarczy dopisać w head link:css i zrobić dokładnie analogicznie (lub ręcznie klepać całość).

    Oczywiście jeszcze nie mamy naszego pliku style.css ale tym się na razie przejmujemy za chwile go zbudujemy.

    Tak więc pozostaje nam stworzyć przykładowy plik z rozszerzeniem .scss i/lub .sass (w naszym przypadku style.scss) i dodać do niego przykładową zawartość:

    $dark: #333;
    
    body {
        background-color: $dark;
    }
    
    

    Wszystkie słowa rozpoczynające się od $ oznaczają zmienne do których możemy przypisywać własne wartości.

    Następnie będąc (wciąż w widoku dokumentu) nacisnąć w prawym dolnym rogu:
    Run sass compile

    Dzięki temu uruchomi się konsola która uruchomi kompilator.
    Watcher wygenerował nam plik style.css i dalej będzie śledził jego zawartość.

    Ok, czas na drugi etap, przechodzimy do naszego index.html i PPM (prawy przycisk myszy) i odpalamy :

    PPM > Live Server

    Powinno nam to uruchomić prosty serwer developerski i uruchomić go w przeglądarce (domyślnie na porcie 5500). Gdyby tak się nie stało możecie ręcznie udać się pod adres http://localhost:5500/.

    To co powinniśmy zobaczyć to efekt naszego stylowania, jak pamiętamy był to ciemny kolor tła, i taki też jest:

    Dark background

    Zagnieżdżanie elementów

    Dobra wydaje mi się, że nie było to większym zaskoczeniem - czas na coś ciekawszego, jak wspomniałem SASS ma sporo dodatkowych opcji jednak dzięki następnej świat staje się łatwiejszy, wyżej przedstawiliśmy sobie zmienne to teraz czas na zagnieżdżenia.

    Sporym ułatwieniem jest możliwość zagnieżdżenia kodu wewnątrz samego siebie, załóżmy taki scenariusz - mamy przycisk który ma być podświetlany w chwili najechania na niego. Tworzymy sobie prosty kod w naszym html:

    <button>Witaj Świecie</button>
    

    Ok, aby to ostylować a robimy to w taki sposób:

    // Colors
    $dark: #333;
    $blue: #20b2f7;
    $white: #fff;
    $red: #ff4e4e;
    $red-dark: #d24646;
    
    // Fonts size
    $sm: 0.5em;
    $md: 1em;
    $lg: 2em;
    
    button {
    	background-color: $red;
    	border-radius: 25px;
    	border: none;
    	padding: $sm $md;
    	color: $white;
    
    	&:hover {
    		background-color: $red-dark;
    	}
    }
    

    Sam przycisk (z kodu powyżej) zostanie przerobiony do takiej postaci:
    Red button

    button {
    	background-color: #ff4e4e;
    	border-radius: 25px;
    	border: none;
    	padding: 0.5em  1em;
    	color: #fff;
    }
    
    button:hover {
    	background-color: #d24646;
    }
    

    Jak się domyślanie zbyt wiele zagnieżdżeń wcale nie ułatwia analizy kodu a w przypadku składni scss nawet utrudnia, dlatego starajmy się je mimo wszystko ograniczać, tutaj przykład kodu który poszedł zdecydowanie za daleko:

    #menu {
    	ul{
    		list-style: none;
    		
    		li {
    			float: left;
    				
    			a {
    				display: block;
    				padding: 10px 20px;
    				background-color: #777;
    			}
    		}
    	}
    }
    

    Modułowość

    Dobra ale wróćmy do poprzedniego przykładu dodaliśmy sobie sporo dodatkowych zbędnych zmiennych (kolory, rozmiary fontów), pewnie już rodzi się Wam pytanie po co? Z bardzo prostej przyczyny, po pierwsze aby unaocznić nieco bardziej ich wykorzystanie a po drugie aby pokazać teraz modularność SASS'a.

    Swoją drogą jest to częściowo funkcjonalność zwykłego CSS'a jednak działająca nieco inaczej. Przy zwykłych importach CSS tworzy kolejne zapytania sieciowe natomiast SASS bierze wszystkie wymienione (zazwyczaj w głównym pliku) moduły i łączy w jeden plik który następnie przetwarza.

    Stwórzmy sobie folder modules (choć nazwa nie ma tak naprawdę znaczenia) i dodajmy sobie dwa pliki, tak to wyglądać będzie w naszej drzewku katalogów:

    App

    • modules
      • _colors.scss
      • _fonts.scss
    • index.html
    • style.scss
    • style.css

    W przypadku modułów ważne aby na początku w nazwie było słowo kluczowe _ mówiące SASS'owi, że jest to część (która może być dołączana w innym miejscu).

    Jak się domyślacie w jednym pliku będą znajdować się nasze kolory a w drugim wszystko co związane z czcionkami, rozmiary itd. Utwórzmy więc na bazie tego co sobie dotychczas powiedzieliśmy oba pliki:

    modules/_colors.scss:

    // Colors
    $dark: #333;
    $blue: #20b2f7;
    $white: #fff;
    $red: #ff4e4e;
    $red-dark: #d24646;
    

    modules/_fonts.scss

    // Fonts size
    $sm: 0.5em;
    $md: 1em;
    $lg: 2em;
    

    Ostatnim co nam pozostaje aby całość zadziałała to zmodyfikowanie głównego pliku o dodatkowe dwa wpisy:

    style.scss:

    @import 'modules/colors';
    @import 'modules/fonts';
    
    button {
    	background-color: $red;
    	border-radius: 25px;
    	border: none;
    	padding: $sm $md;
    	color: $white;
    
    	&:hover {
    		background-color: $red-dark;
    	}
    }
    

    Importy nie muszą już zawierać _ ani rozszerzenia. Oczywiście można by wrzucić powyższy plik do tego samego folderu co moduły ale my tego nie zrobimy - ze względu na dodatkowe konfigurowanie pluginu (domyślnie generuje plik css w folderze w którym znajduje się plik źródłowy scss).

    Mixins, funkcje

    Kolejną opcją którą przetestujemy są tzw. mixins czyli tak bardziej po naszemu są to (prawie) funkcje. Prawie bo jeżeli spojrzymy na jakikolwiek język programowania to funkcja zazwyczaj zwraca jakąś (jedną) wartość natomiast mixin zawiera kilka wartości które bezpośrednio dodaje do kodu CSS. Oczywiście zwykłe funkcje także istnieją i możemy je uzyskać poprzez znacznik @function.

    Pewnie zastanawiasz gdzie w CSS mogę mieć potrzebę używania takich struktur? Odpowiedź - wszędzie gdzie musimy wykonywać powtarzalną się zbędną prace.

    Przejdźmy do praktyki, stworzymy sobie kolejne dwa moduły w naszym folderze:

    modules/_mixins.scss

    // Mixins
    @mixin transform($property) {
      -webkit-transform: $property;
      -ms-transform: $property;
      transform: $property;
    }
    

    Działa to w bardzo prosty sposób nasza mixin nazywa się transform a wszystko co posiada w nawiasie nazywamy parametrem, mamy więc jeden parametr $property który jest widoczny jako zmienna ale tylko w obrębie tego mixinu (czyli tam gdzie zaczynają i kończą się klamry).

    Nie jest to może bardzo wyszukany przykład ~ pochodzi z dokumentacji projektu ale bardzo dobrze pokazuje istotę działania w warunkach bojowych.

    Jeżeli robiliście już coś w CSS3 to zapisy wewnątrz tego mixinu nie powinny być dla Was obce, a nawet jeśli są to całe działanie w tym przypadku polega na dodaniu prefix'ow dla odpowiednich przeglądarek (natywnie) nie wspierających danej funkcjonalności (obecnie można by było użyć jakiegoś auto-prefixera ale to innym razem).

    modules/_functions.scss

    // Functions
    @function divide($val){
    	@return  $val  /  2;
    }
    

    Podobnie jeżeli robimy zwykłą funkcje divide tak jak powyżej której zadaniem jest wziąć parametr $val i podzielić na 2. Oczywiście parametr jest w tej chwili dowolny i nie musi być to wcale liczba (można to także bardziej doprecyzować).

    Dobra czas to wreszcie wypróbować wbijamy do naszego głównego pliku i go lekko przerabiamy:

    style.scss

    @import  'modules/functions';
    @import  'modules/mixins';
    @import  'modules/colors';
    @import  'modules/fonts';
      
    button {
    	background-color: $red;
    	border-radius: 25px;
    	border: none;
    	padding: $sm  $md;
    	margin: divide(25px);
    	color: $white;
    	transition: .5s all;
    
    	&:hover {
    		background-color: $red-dark;
    		@include transform(scale(1.1));
    	}
    }
    

    Pamiętamy o imporcie na samej górze, dodatkowo tutaj dla niepoznaki dorzuciłem jeszcze transition: .5s all aby całość nie była taka sztywna.

    Z pomocą @include użyliśmy stworzonego przez nas mixin'a a także własnej funkcji - ale co tak naprawdę się stało możemy zobaczyć dopiero w wynikowym CSS:

    button {
    	background-color: #ff4e4e;
    	border-radius: 25px;
    	border: none;
    	padding: 0.5em  1em;
    	margin: 12.5px;
    	color: #fff;
    	-webkit-transition: .5s  all;
    	transition: .5s  all;
    }
    
    button:hover {
    	background-color: #d24646;
    	-webkit-transform: scale(1.1);
    	transform: scale(1.1);
    }
    

    Tutaj uwidacznia się również pierwsza różnica między scss i sass, chcąc zrobić to samo w sass zamiast @mixins użylibyśmy przedrostka = przed nazwą funkcji a chcąc ją wywołać wystarczyłoby ponownie użyć przedrostka + oraz nazwa funkcji.

    Dziedziczenie, rozszerzanie

    Kolejną świetną sprawą jest dziedziczenie oraz rozszerzanie elementów, wyobraźcie sobie proste pudełko albo nawet dwa. Zróbmy je dodając w index.html:

    <div id="box1">Box 1</div>
    <div id="box2">Box 2</div>
    

    Oba z nich mają mieć taki sam cień wokół pudełka oraz podobne style dotyczące wyświetlanego wewnątrz tekstu, różnica w tym wypadku polega jedynie na zmianie koloru tła. Niech tych właściwości będzie nieco więcej, kopiowanie tego (już nie mówię nawet o przepisywaniu) to droga donikąd. Kompletnie nieoptymalnie i karkołomnie - kompletnie wbrew wszelkim regułą jak np. DRY (Don't repeat yourself ~ nie powtarzaj się!).

    Dlatego robimy to w ten sposób:

    @import 'modules/functions';
    @import 'modules/mixins';
    @import 'modules/colors';
    @import 'modules/fonts';
    
    %universal {
    	width: calc(1/6  *  100vw);
    	height: calc(1/4  *  100vh);
    	margin: 2rem;
    	font-size: $lg;
    	display: flex;
    	justify-content: center;
    	align-items: center;
    	color: $white;
    	box-shadow: 0  4px  8px  0  rgba(0, 0, 0, 0.2), 0  6px  20px  0  rgba(0, 0, 0, 0.19);
    }
    
    #box1 {
    	background-color: $dark;
    	@extend  %universal;
    }
    
    #box2 {
    	background-color: $blue;
    	@extend  %universal;
    }
    
    button {
    	background-color: $red;
    	border-radius: 25px;
    	border: none;
    	padding: $sm  $md;
    	margin: divide(25px);
    	color: $white;
    	transition: .5s  all;
    
    	&:hover {
    		background-color: $red-dark;
    		@include  transform(scale(1.1));
    	}
    }
    

    Dzięki czemu mamy jeden kod który daje nam dwa identyczne pudełka w różnych kolorach ~ czyż to nie jest lepsze? Co więcej jeżeli zrobimy taki element ogólnego przeznaczenia i nigdzie go nie załączymy przez @extend to nie zostanie on zupełnie uwzględniony w kodzie.

    Two boxes

    Sass wspiera także wykonywania zwykłych działań matematycznych, to samo co możecie zobaczyć tutaj powyżej natywnie w funkcji calc można zrobić zwyczajnie przy zwykłych właściwościach, przykład:

    margin: 50px + 23px;
    

    Poza tym dostępne są także instrukcje warunkowe czy pętle na tym, jednak SASS się nie kończą zachęcam do dalszego odkrywania możliwości jakie daje zaglądając na oficjalną stronę projektu,


Log in to reply