Полный гайд по SCSS/SASS
В гайде будут разобраны препроцессоры:
Sass
SCSS
Концептуально разница между ними не велика, будем считать, что это одно и тоже. Вы поймёте различия по мере изучения темы. Отмечу, что SCSS
сейчас наиболее популярна, вероятно потому, что является наиболее поздней версией оригинального Sass
.
Всего существует 5
препроцессоров: Sass
, SCSS
, Less
, Stylus
и PostCSS
.
Почему стоит выберать препроцессоры
Пока вы хотя бы раз не попробуете сгенерировать значения для свойств с помощью цикла, вы не познаете настоящую мощь препроцессоров.
Что есть в Sass/SCSS, чего нет в стандартном CSS
- Переменные — в стандартном
CSS
тоже есть понятие переменных, но вSASS
с ними можно работать немного по-другому. Например, повторять их через директиву@for
. Или генерировать свойства динамически, подробнее - Вложенность —
SCSS
позволяет вкладывать правилаCSS
друг в друга. Вложенные правила применяются только для элементов, соответствующих внешним селекторам, а если речь идёт оSASS
, то там и без скобок всё красиво и интуитивно понятно, подробнее - Улучшенные математические операции — можно складывать, вычитать, умножать и делить значения
CSS
. В отличие от стандартногоCSS
,SASS/SCSS
позволяют обойтись безcalc()
, подробнее - Тригонометрия —
SCSS
позволяет писать собственные синусоидальные и косинусоидальные функции, используя только синтаксисSASS/SCSS
, подобно тому, как это можно делать в других языках вродеJavaScript
- Директивы -
@for
,@while
и выражение@if-else
— можно писатьCSS
код, используя знакомые элементы из других языков. Но не обольщайтесь — в итоге на выходе будет обычныйCSS
, подробнее - Миксины (примеси) — можно один раз создать набор
CSS
свойств и работать с ними повторно или смешивать с другими значениями. Миксины можно использовать для создания отдельных тем одного макета. Примеси также могут содержать целыеCSS
правила или что-либо другое, разрешённое вSASS
документе. Они даже могут принимать аргументы, что позволяет создавать большое разнообразие стилей при помощи небольшого количества миксинов, подробнее - Функции — можно создавать определения
CSS
в виде функций для многократного использования, подробнее
Конвертация в командной строке
Расширения .sass
и .scss
похожи, но всё-таки не одинаковы. Ниже представлен способ конвертации SASS
в SCSS
и наоборот:
# конвертация Sass в SCSS
sass-convert style.sass style.scss
# конвертация SCSS в Sass
sass-convert style.scss style.sass
Переменные
В SASS
и SCSS
есть переменные, и они отличаются от переменных в CSS
. В CSS
переменные начинаются с двух тире --color: #9c27b0
. В SCSS
переменная обозначается знаком доллара $color: #9c27b0
.
stule.scss$number: 1;
$color: #FF0000;
$text: "Test";
$text: "Test 2" !default;
$nothing: null;
Можно перезаписать имя переменной или задать для неё значение по умолчанию. Для этого добавьте метку !default
к переменной, и если её значение не изменится в дальнейшем и не будет пустым, то будет использоваться заданное значение по умолчанию.
В примере выше, окончательным значением переменной $text
будет Test
, а не Test 2
, потому что переменная не пуста.
Переменные можно назначить любому свойству:
stule.scss#container {
content: $text;
}
Результат:
stule.css#container {
content: "Test";
}
Вложенные правила
В стандартном CSS, вложенность достигается путём расстановки пробелов:
stule.css#a {
color: red;
}
#a #b {
color: green;
}
С помощью SCSS
этот код можно записать так:
stule.scss#a {
color: red;
#b {
color: green;
}
}
Это помогает работать со сложными макетами. Выравнивание, в котором вложенные свойства записаны в коде, точно соответствует структуре макета приложения.
Оператор &
В SCSS
есть оператор &
, который указывает на родителя:
stule.scss#p {
color: black;
a {
&:hover {
color: red;
}
}
}
Результат:
stule.css#p {
color: black;
}
#p a:hover {
color: red;
}
Вместо символа &
, подставляется имя родительского элемента, a:hover
.
Миксины или примиси
Миксины объявляются директивой @mixin
. После неё должно стоять имя миксина и, опционально, его параметры, а также блок, содержащий тело миксина. Давайте создадим миксин, который определяет поведение элемента как Flex
и далее будет включён в класс elements
:
stule.scss@mixin flex() {
display: flex;
}
.elements {
@include flex();
border: 1px solid #000;
}
Результат:
stule.css.elements {
display: flex;
border: 1px solid #000;
}
В миксины можно передавать аргументы, как если бы это была функция, а затем присваивать их свойствам CSS
:
stule.scss@mixin flex($a) {
display: flex;
border: $a solid #000;
}
.elements {
@include flex(1px);
}
Результат:
stule.css.elements {
display: flex;
border: 1px solid #000;
}
Арифметические операции
Как и в стандартном CSS
, вам доступны операции сложения, вычитания, умножения и деления, но в отличии от классического CSS
синтаксиса, вам необязательно использовать функцию calc()
.
Сложение
Как и в реальной жизни, вы не можете работать с числами, у которых несовместимы типы данных, например сложение рх
и em
. Главное, что-бы оба значения соответствуют одному формату:
stule.scssp {
// error
// font-size: 10px + 2em;
font-size: 10px + 2px;
font-size: 10px + 2;
}
Результат:
stule.cssp {
font-size: 12px;
font-size: 12px;
}
Вычитание
Главное, что-бы оба значения соответствуют одному формату:
stule.scssp {
font-size: 10px - 2px;
}
Результат:
stule.cssp {
font-size: 8px;
}
Умножение
Выполняется точно так же, как в CSS, с помощью calc(a * b)
, но без calc
и круглых скобок. Кроме того, можно ещё отделять знак умножения пробелами от чисел 5*6 == 5 * 6
.
Нельзя умножать пиксели между собой. То есть, 10px * 10px != 100px
. 10px * 10 == 100px
.
stule.scssp {
// error
// font-size: 10px * 10px;
// font-size: 10px * (2px + 5px);
font-size: 10px * 2;
font-size: 10px * 2 + 5px;
font-size: 10px + (10px / 2) * 3;
Результат:
stule.cssp {
font-size: 20px;
font-size: 25px;
font-size: 25px;
}
Деление
В стандартном CSS
, символ деления зарезервирован для других целей, например font: 24/32px
определяет размер шрифта font-size: 25px
и line-height: 32px
.
Чтобы разделить два значения, просто оберните выражение в скобки. Иначе, оператор деления сработает только при использовании с другими операторами или функциями:
stule.scssp {
top: (16px / 16px);
}
Результат:
stule.cssp {
top: 1;
}
Есть три помощника, которые намекнут на возможность деления:
- Значение (или любая его часть) хранится в переменной или возвращается функцией
- Значения заключены в круглые скобки
- Значение используется как часть другого арифметического выражения
stule.scss$var1: 20;
$var2: 4;
p {
// отображается без изменений в стандартном CSS
top: 16px / 24px;
// производится деление (но только при использовании скобок)
top: (20px / 5px);
// выводится как обычный CSS-код, деление не выполняется
top: #{$var1} / #{$var2};
// деление выполняется
top: $var1 / $var2;
// деление выполняется (если использовать в паре с функцией)
top: random(4) / 5;
// деление выполняется, если добавлена ещё одно арифметическое действие
top: 2px / 4px + 3px;
}
Результат:
stule.cssp {
top: 16px / 24px;
top: 4;
top: 20 / 4;
top: 5;
top: 0.6;
top: 3.5px;
}
Остаток
Вы можете вычислить остаток от операции деления. Давайте попробуем создать зебру для набора HTML
элементов:
stule.scss@mixin zebra() {
@for $i from 1 through 7 {
@if ($i % 2 == 1) {
.sprite-#{$i} {
background-color: black;
color: white;
}
}
}
}
@include zebra();
Результат:
stule.scss.sprite-1 {
background-color: black;
color: white;
}
.sprite-3 {
background-color: black;
color: white;
}
.sprite-5 {
background-color: black;
color: white;
}
.sprite-7 {
background-color: black;
color: white;
}
Операторы сравнения
x==y
возвращаетtrue
, еслиx
иy
равныx!=y
возвращаетtrue
, еслиx
иy
не равныx>y
возвращаетtrue
, еслиx
больше, чемy
x<y
возвращаетtrue
, еслиx
меньше, чемy
x>=y
возвращаетtrue
, еслиx
больше или равноy
x<=y
возвращаетtrue
, еслиx
меньше или равноy
Чтобы показать, как операторы сравнения работают на практике, создадим миксин, который будет применять свойство padding
, если его значение больше значения margin
:
stule.scss@mixin spacing($padding, $margin) {
@if ($padding > $margin) {
padding: $padding;
} @else {
margin: $margin;
}
}
.container {
@include spacing(10px, 20px);
}
Результат:
stule.css.container {
padding: 20px;
}
Логические операторы
x and y
возвращаетtrue
, еслиx
иy
равныtrue
x or y
возвращаетtrue
, еслиx
илиy
равныtrue
not x
возвращаетtrue
, еслиx
не равенtrue
Создадим кнопки, у которой будет меняться фон в зависимости от ширины:
stule.scss@mixin button-color($height, $width) {
@if (($height < $width) and ($width >= 35px)) {
background-color: blue;
} @else {
background-color: green;
}
}
.button {
@include button-color(20px, 30px);
}
Результат:
stule.css.button {
background-color: green;
}
Строки
В CSS
определено 2 типа строк, с кавычками и без. SASS
распознаёт и то, и другое. В итоге вы получите в CSS
тот тип строк, который использовали в SASS
.
В некоторых случаях можно добавить строки в допустимые значения CSS
без кавычек, но только если добавленная строка является завершающим элементом:
stule.scssp {
font: 50px Ari + "al";
}
Результат:
stule.cssp {
font: 50px Arial;
}
Следующий пример приводит к строке ненужного типа:
stule.scssp {
font: "50pxArial";
}
Можете складывать строки, соторые нужно взять в кавычки:
stule.scssp:after {
content: "Привет " + "мир!";
}
Результат:
stule.cssp:after {
content: "Привет мир!";
}
Операторы управления потоками
Подобно JavaScript
, SCSS
позволяет работать со стандартным набором операторов управления потоками.
Функция if() и директива @if
В SCSS
есть функции fucntion()
и директивы @directive
, их ещё называю правилами. Отличительные особенности функций и директив:
if()
функция, есть скобки которые ставятся сразу после её имени@if
дириктива, есть знак@
который ставится перед её именим
Применяется очень просто, оператор вернёт одно из двух значений, в зависимости от условия:
stule.scssh2 {
color: if( 1 + 1 == 2 , green , red);
}
Результат:
stule.cssh2 {
color: green;
}
Директива использующаяся для разветвления на основе условия:
stule.scssp {
@if 1 + 1 == 2 { border: 1px solid; }
@if 7 < 5 { border: 2px dotted; }
@if null { border: 3px double; }
}
Результат:
stule.cssp {
border: 1px solid;
}
Ниже показано комбинация разветвлений с добавлением директивы @else
:
stule.scss$type: river;
div {
@if $type == river {
color: blue;
}
}
p {
@if $type == tree {
color: green;
} @else if $type == river {
color: blue;
} @else if $type == dirt {
color: brown;
}
}
Результат:
stule.cssdiv {
color: blue;
}
p {
color: blue;
}
Директива @for
Директива @for
выводит набор стилей заданное число раз. Для каждого повторения используется переменная-счётчик $i
для изменения вывода. from
начальная цифра от которой идет отсчет у цикла, through
конечная цифра до которой идет отсчет:
stule.scss@for $i from 1 through 5 {
.definition-#{$i} { width: 10px * $i; }
}
Результат:
stule.css.definition-1 {
width: 10px;
}
.definition-2 {
width: 20px;
}
.definition-3 {
width: 30px;
}
.definition-4 {
width: 40px;
}
.definition-5 {
width: 50px;
}
Директива @each
Директива @each
устанавливает $var
в каждое из значений списка или словаря и выводит содержащиеся в ней стили, используя соответствующее значение $var
:
stule.scss@each $var in platypus, lion, sheep, dove {
.#{$var}-icon {
background-image: url("/images/#{$var}.png")
}
}
Результат:
stule.css.platypus-icon {
background-image: url("/images/platypus.png");
}
.lion-icon {
background-image: url("/images/lion.png");
}
.sheep-icon {
background-image: url("/images/sheep.png");
}
.dove-icon {
background-image: url("/images/dove.png");
}
Директива @while
Директива @while
принимает выражение и циклично выводит вложенные в неё стили, пока выражение вычисляется как true
. Она может быть использована для создания более сложных циклов, чем таких, для которых подходит @for
, хотя она бывает необходима довольно редко:
stule.scss$index: 5;
@while $index > 0 {
.element-#{$index} { width: 10px * $index; }
$index: $index - 1;
}
Результат:
stule.css.element-5 { width: 50px; }
.element-4 { width: 40px; }
.element-3 { width: 30px; }
.element-2 { width: 20px; }
.element-1 { width: 10px; }
Функции
Используя SASS
и SCSS
можно использовать функции так же, как и в других языках. Создадим функцию three-hundred-px()
, возвращающую 300px
:
stule.scss@function three-hundred-px() {
@return 300px;
}
.name {
width: three-hundred-px();
border: 1px solid gray;
display: block;
position: absolute;
}
Результат:
stule.css.name {
width: 300px;
border: 1px solid gray;
display: block;
position: absolute;
}
Функции могут возвращать любое корректное значение CSS
и могут быть назначены любому свойству. Они даже могут быть рассчитаны на основе переданного аргумента:
stule.scss@function three-hundred-px($width) {
@return $width * 2px;
}
.name {
width: three-hundred-px(150);
border: 1px solid gray;
display: block;
position: absolute;
}
Результат:
stule.css.name {
width: 300px;
border: 1px solid gray;
display: block;
position: absolute;
}