Препроцессинг

Написание CSS само по себе весело, но когда таблица стилей становится огромной, то становится и сложно её обслуживать. И вот в таком случае нам поможет препроцессор. Sass позволяет использовать функции недоступные в самом CSS, например, переменные, вложенности, миксины, наследование и другие приятные вещи, возвращающие удобство написания CSS.

Как только Вы начинаете пользоваться Sass, препроцессор обрабатывает ваш Sass-файл и сохраняет его как простой CSS-файл, который Вы сможете использовать на любом сайте.

Самый простой способ получить такой результат - использовать терминал. После того, как Sass установлен, вы можете компилировать ваш Sass в CSS, используя команду sass. Вам всего лишь нужно сообщить Sass, где взять файл Sass и в какой файл CSS его скомпилировать. Например, запустив команду sass input.scss output.css?v=1751815721684 в терминале, вы сообщаете Sass взять один Sass файл, input.scss, и скомпилировать в файл output.css?v=1751815721684.

Также, вы можете следить за изменениями только определенных файлов или папок, используя флаг --watch. Данный флаг сообщает Sass, что необходимо следить за изменениями указанных файлов и при наличии таковых производить перекомпиляцию CSS после сохранения файлов. Если вы хотите отслеживать изменения (вместо ручной перекомпиляции) вашего файла, например, input.scss, то вам необходимо просто добавить флаг в команду:

sass –watch input.scss output.css?v=1751815721684

Вы также можете указать папки для отслеживания изменений и куда сохранять компилированные CSS файлы, для этого достаточно указать пути и разделить их двоеточием, например:

sass --watch app/sass:public/stylesheets

Sass будет отслеживать все файлы в директории app/sass и компилировать CSS в директорию public/stylesheets.

Переменные

Думайте о переменных, как о способе хранения информации, которую вы хотите использовать на протяжении написания всех стилей проекта. Вы можете хранить в переменных цвета, стеки шрифтов или любые другие значения CSS, которые вы хотите использовать. Чтобы создать переменную в Sass нужно использовать символ $. Рассмотрим пример:

scss

$font-stack: Helvetica, sans-serif;
$primary-color: #333;

body {
font : 100% $font-stack
color : $primary-color ;
}

css

body {
font : 100% Helvetica, sans-serif
color : #333 ;
}

Когда Sass обрабатывается, он принимает значения, заданные нами в $font-stack и $primary-color и вставляет их в обычном CSS-файле в тех местах, где мы указывали переменные как значения. Таким образом переменные становятся мощнейшей возможностью, например, при работе с фирменными цветами, используемыми на всем сайте.

Вложенности

При написании HTML, Вы, наверное, заметили, что он имеет четкую вложенную и визуальную иерархию. С CSS это не так.

Sass позволит вам вкладывать CSS селекторы таким же образом, как и в визуальной иерархии HTML. Но помните, что чрезмерное количество вложенностей делает ваш документ менее читабельным и воспринимаемым, что считается плохой практикой.

Чтобы понять что мы имеем ввиду, приведем типичный пример стилей навигации на сайте:

scss

nav {

ul {
margin 0 ;
padding : 0 ;
list-style none
}
li {
display inline-block ;
}
a {
display : block
padding : 6px 12px
text-decoration : none ;
}

}

css

nav ul {
margin : 0 ;
padding : 0 ;
list-style none ;
}
nav li {
display : inline-block ;
}
nav a {
display : block ;
padding : 6px 12px ;
text-decoration : none ;
}

Вы заметили, что селекторы ul, li, и a являются вложенными в селектор nav? Это отличный способ сделать ваш CSS-файл более читабельным. Когда вы сгенерируете CSS-файл, то на выходе вы получите что-то вроде этого:

Фрагментирование

Вы можете создавать фрагменты Sass-файла, которые будут содержать в себе небольшие отрывки CSS, которые можно будет использовать в других Sass-файлах. Это отличный способ сделать ваш CSS модульным, а также облегчить его обслуживание. Фрагмент — это простой Sass-файл, имя которого начинается с нижнего подчеркивания, например, _partial.scss. Нижнее подчеркивание в имени Sass-файла говорит компилятору о том, что это только фрагмент и он не должен компилироваться в CSS. Фрагменты Sass подключаются при помощи директивы @import.

Импорт

CSS имеет возможность импорта, которая позволяет разделить ваш CSS-файл на более мелкие и облегчить@import, то в CSS создается еще один HTTP-запрос. Sass берет идею импорта файлов через директиву @import, но вместо создания отдельного HTTP-запроса Sass импортирует указанный в директиве файл в тот, где он вызывается, т.е. на выходе получается один CSS-файл, скомпилированный из нескольких фрагментов.

Например, у вас есть несколько фрагментов Sass-файлов — _reset.scss и base.scss. И мы хотим импортировать

_reset.scss в base.scss.

scss

// _reset.scss
html,
body,
ul,
ol
{
margin : 0 ;
padding : 0 ;
}

// base.scss
@import 'reset';
body {
font : 100% Helvetica, sans-serif ;
background-color : #efefef ;
}

css

html,
body,
ul,
ol {
margin : 0 ;
padding : 0 ;
}
body {
font : 100% Helvetica, sans-serif ;
background-color : #efefef ; }

Обратите внимание на то, что мы используем @import 'reset'; в base.scss файле. Когда вы импортируете файл, то не нужно указывать расширение .scss. Sass — умный язык и он сам догадается.

Миксины (примеси)

Некоторые вещи в CSS весьма утомительно писать, особенно в CSS3, где плюс ко всему зачастую требуется использовать большое количество вендорных префиксов. Миксины позволяют создавать группы деклараций CSS, которые вам придется использовать по нескольку раз на сайте. Вы даже можете передавать переменные в миксины, чтобы сделать их более гибкими. Так же хорошо использовать миксины для вендорных префиксов. Пример для transform:

scss

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

.box {
@include transform(rotate(30deg)) ;
}

css

.box
-webkit-transform : rotate(30deg) ;
-ms-transform : rotate(30deg) ;
transform : rotate(30deg) ;
}

To create a mixin you use the @mixin directive and give it a name. We've named our mixin transform. We're also using the variable $property inside the parentheses so we can pass in a transform of whatever we want. After you create your mixin, you can then use it as a CSS declaration starting with @include followed by the name of the mixin.

Расширение/Наследование

Это одна из самых полезных функций Sass. Используя директиву @extend можно наследовать наборы свойств CSS от одного селектора другому. Это позволяет держать ваш Sass-файл в «чистоте». В нашем примере мы покажем вам как сделать стили оповещений об ошибках, предупреждениях и удачных исходах, используя другие возможности Sass, которые идут рука-об-руку с расширением, классами-шаблонами. Класс-шаблон - особый тип классов, который выводится только при использовании расширения - это позволит сохранить ваш скомпилированный CSS чистым и аккуратным.

scss

/* This CSS will print because %message-shared is extended. */
%message-shared {
border : 1px solid #ccc ;
padding : 10px ;
color : #333 ;
}

.box {
@include transform(rotate(30deg)) ;
}

// This CSS won't print because %equal-heights is never extended.
%equal-heights {
display : flex ;
flex-wrap : wrap ;
}

.message {
@extend %message-shared ;
}
.success {
@extend %message-shared ;
border-color : green ;
}
.message {
@extend %message-shared ;
border-color : red ;
}
.message {
@extend %message-shared ;
border-color : yellow ;
}

css

.message, .success, .error, .warning {
border : 1px solid #ccc ;
padding : 10px ;
color : #333 ;
}
.success {
border-color : green ;
}
.error {
border-color : red ;
}
.warning {
border-color : yellow ;
}

Вышеуказанный код сообщает классам .message, .success, .error и .warning вести себя как %message-shared. Это означает, что где бы не вызывался %message-shared, то и .message, .success, .error и .warning тоже будут вызваны. Магия происходит в сгенерированном CSS, где каждый из этих классов получает css-свойства, как и %message-shared. Это позволит вам избежать написания множества классов в HTML элементах.

Вы можете расширить большинство простых CSS селекторов прибавление к классам-шаблонам в Sass, однако, использование шаблонов - простейший способ быть уверенным, что вы не расширяете класс везде, где он используется в ваших стилях, что могло бы привести к непреднамеренным наборам стилей в вашем CSS.

Когда вы генерируете ваш CSS, то он будет выглядеть как пример ниже. Обратите внимание, %equal-heights не попадает в CSS, так как ни разу не был использован.

Математические операторы

Использовать математику в CSS очень полезно. Sass имеет несколько стандартных математических операторов, таких как +, -, *, / и %. В нашем примере мы совершаем простые математические вычисления для расчета ширины aside и article.

scss

.container {
width : 100% ;
}

article[role="main"] {
float : left ;
width : 600px / 960px * 100% ;
}

aside[role="complementary"] {
float : right ;
width : 300px / 960px * 100% ;
}

css

.container {
width : 100% ;
}

article[role="main"] {
float : left ;
width : 62.5% ;
}

aside[role="complementary"] {
float : right ;
width : 31.25% ;
}

Мы создали простую адаптивную модульную сетку, с шириной в 960 пикселей. Используя математические операторы, мы использовали полученные данные с пиксельными значениями и конвертировали их в процентные, причем без особых усилий. Скомпилированный CSS выглядит так:

Препроцесор SCSS

SCSS розшифровується як — Sassy CSS

Спочатку зʼявився препроцесор SASS, який був важким для розуміння розробників через новий синтаксис, а потім його варіація — SCSS яка була зрозуміліша через подібний до CSS синтаксис.

Надав можливість використовувати примітивну мову програмування в css та спростити код:

зручно використовувати змінні:

// приклад змінної для фонового кольору,
// (ЗГІДНО З ПРАВИЛ ІМЕНА ЗМІННИХ ПОВИННІ ПОЧИНАТИСЬ З ЛІТЕРИ ПІСЛЯ ЗНАКУ "$")
$main-bg: #ooo;


// використання змінної для відображення фонового кольору
body {
background-color : $color
}

вкладеність:

// приклад вкладеності в якому відбувається звернення до усіх span в блоці block
.block {
background-color : #fff
span {
color : red
}
}

взаємодія з БЕМ:

// при копіюванні класів з методологією БЕМ елементи блоку відносяться до блоку та мають запис
.block {
&__body {
}
&__text {
}
}

клас з класом:

// звернення до елементу .block у якого є клас .page__body
// вигляд у html class="block page__body"
// запис повинен бути без пробілів між класами
.block {
&.page__body {
}
}

клас у батьківського елементу:

// звернення до елементу коли у батівського блоку є клас .loaded
.block {
.loaded & {
}
}

медіазапити:

// приклад запису медіазапиту для .block
.block {
background-color: #fff ;
@media (max-width: 767px;) {
background-color: #000 ;
}
}

псевдокласи та псевдоелементи:

.block {
background-color: #fff ;
position: relative ;
z-index: 2 ;
// приклад написання псевдокласу hover всередині медіазапиту
@media (any-hover: hover) {
&:hover {
background-color: #000 ;
}
}
// приклад написання before
&::before {
content: "" ;
display: inline-block ;
position: absolute ;
width: 100% ;
height: 100% ;
top: 0 ;
left: 0 ;
background-color: rgba(75, 74, 74, 0.3) ;
z-index: -1 ;
}
}

mixins — дозволяють повертати набір властивостей з можливістю передавати різні значення змінних:

// приклад міксину для встановлення колірноїї теми для блоку чи елменту
@mixin blockTheme ($color, $bg-color) {
color: $color ;
background-color: $bg-color ;
}

// використання міксину
.block {
@include blockTheme ("#000")
// вказуємо потрібний колір який буде для шрифту та фону
}

//========================
// нижче код з коментарями для цього блоку
// Оголошення міксіна з ім'ям blockTheme, який приймає один аргумент - $color
@mixin blockTheme ($color, $bg-color) {
// Встановлюємо колір тексту елемента, до якого буде застосовано цей міксін
color: $color ;
// Встановлюємо колір фону елемента, до якого буде застосовано цей міксін
background-color: $bg-color ;
}
// Застосовуємо міксін blockTheme до елементів з класом .block
.block {
// Використовуємо директиву @include для включення міксіна blockTheme
// Передаємо "#fff" (чорний) як аргумент $color та "#000" (білий) як аргумент $bg-color в міксін
@include blockTheme ("#000, #fff")
}

//========================
// другий приклад міксину для бордеру та падінгу
// Оголошення міксіна з ім'ям borderAndPadding, який приймає два аргументи - $border та $padding
@mixin borderAndPadding ($border, $padding) {
// Встановлюємо рамку для елемента, до якого буде застосовано цей міксін
border: $border ;
// Встановлюємо відступи для елемента, до якого буде застосовано цей міксін
padding: $padding ;
}

// Застосовуємо міксін borderAndPadding до елементів з класом .block
.block {
// Використовуємо директиву @include для включення міксіна borderAndPadding
// Передаємо "1px solid black" як аргумент $border та "10px" як аргумент $padding в міксін
@include borderAndPadding ("1px solid black", "10px")

шаблони — міксіни без можливості передавати дані; коли часто використовуємо набір параметрів (якщо шаблон не використати в коди, то він не потрапить в кінцевий файл css):

%black-theme {
background-color: #000 ;
color: #000 ;
}

.block {
@extend %black-theme ;
}

“взяти” стилі в іншого обʼєкту:

// в цьому прикладі ми беремо (наче примусово успадковуємо) стилі у елементу з класом .title
.block {
@extend .title ;
}

коментування:

// однорядковий коментар котрий не потрапляє в css

/* багаторядковий коментар який потрапляє в css */

Функції використовуються для вирахування чогось (приклад для вираховування відсотків)

// підключення математичних вираховувань, потрібно додати @use "sass:math"; зверху коду
@function percent($num1, $num2) {
$rez: math.div($num1, $num2) * 100%
@return $rez ;
}

.block {
width: percent(300, 1200) ;
// відбувається обчислення (300/1200)*100=25%
}

Функції використовуються для вирахування чогось (приклад для вираховування відсотків)

// підключення математичних вираховувань, потрібно додати @use "sass:math"; зверху коду
@use "sass:math" ;

.block {
line-height: math.div(45,20) ;
width: 100 * 200 + px ;
}

Image

цикл (цикли скорочують написання коду):

// додавання затримки анімації до елементів за допомогою циклу
&__items {
&__item {
transform: translate(0px, 0px) ;
// цикл з 5-и повторень циклу
@for $i from 1 through 5 {
// $i назва змінної для циклу
&:nth-child (#{$i}) {
// #{$i} вказуєм змінну замість номеру елементу
animation-delay: #{($i - 1) * 0.2}s ;
// при кожному циклі буде множення номеру на 0.2
// (1*0.2=0.2) (2*0.2=0.4) ... Таким чином для першого елементу затримка буде 0.2s для другого 0.4s ...
}
}
}
}

// додавання затримки анімації до елементів звичайним способом
&__items {
&__item {
transform: translate(0px, 0px) ;
&:nth-child (1) {
transition-delay: 0.3s ;
}
&:nth-child (2) {
transition-delay: 0.6s ;
}
&:nth-child (3) {
transition-delay: 0.9s ;
}
&:nth-child (4) {
transition-delay: 1.2s ;
}
&:nth-child (5) {
transition-delay: 1.5s ;
}
}
}
// а тепер уявіть що таких елементів багато, більше 10-и і на скільки сильно @for спрощує написання коду