Двадцать шестой урок. Основы Sass. Настройка UniCSS

Sass позволяет разделить css/scss-код на отдельные файлы. Скажем — отдельно типографику, отдельно сбросы, отдельно формы и т.п. Такое деление упрощает поддержку проекта: найти нужный фрагмент в коротком коде намного проще.

На выходе обычно формируется один css-файл, который и подключается к странице. Здесь есть один нюанс, о котором вам обязательно следует знать.

Результирующий css-код может оказаться довольно большим: сейчас 200-400Кб не редкость. С точки зрения браузера, это не совсем хорошо, поскольку посетителю требуется больше времени на загрузку стилей, без которых страница отображается некорректно. Поэтому считается, что чем меньше размер css-файла, тем лучше. Но уменьшить файл можно только убрав существующие классы, что уменьшает возможности вёрстки.

Решения этой проблемы в реальности не существует, но есть различные иммитации такого решения. Например можно разделить файл на несколько частей и загружать их последовательно: вначале самая важная часть стилей, после всё остальное. Проблема здесь в том, что css-стили обязательно должны загружаться в секции HEAD перед отображением всей страницы. Поэтому если использовать несколько раздельных файлов, то браузер всё-равно должен загрузить их все, а уже после отобразить страницу. (Сейчас это уже не совсем так. В новой редакции HTML разрешено загружать css-стили в конце BODY.)

На самом же деле, браузеры так не поступают. Они сразу начинают отображать HTML, даже если он частично загружен, при этом они как бы угадывают (по открытым тэгам) дальнейших код, чтобы корректно отобразить содержимое. Одновременно с этим организуется загрузка содержимого из секции HEAD (css-стили и js-скрипты). Как только файлы загружены, они сразу же применяются к странице. На медленных соединениях хорошо видно перестраивание страницы в процессе загрузки.

Основная проблема в том, что http-соединения имеют некоторые ограничения на количество одновременных загрузок, например не более 20 потоков. И под потоками подразумевается абсолютно все загрузки: картинки, скрипты, стили и все их дополнительные подкачки. Для любого сервера количество соединений довольно ресурсоёмкая операция. Иногда время на создание соединения больше, чем время передачи файла. Имено поэтому нужно стремиться уменьшать количество загружаемых служебных файлов.

Для того, чтобы ускорить время загрузки используется gzip-сжатие трафика. Сервер налету сжимает файл и в таком виде передает его браузеру. Браузер также быстро распаковывает файл до обычного. Когда выполняется обновление страницы, то браузер уже не загружает файл с сервера, а использует свою локальную копию. Таким образом загрузка страниц значительно ускоряется.

Степень сжатия текстовых css-файлов достаточно большая. Например в UniCSS style.css уменьшаются с 123Кб до 21Кб, то есть примерно в 5-6 раз. Следовательно трафик для загрузки такого файла создается небольшой и он выгодней, чем создавать множество раздельных http-соединений.

Исходя из всего сказанного, как правило, все исходные scss-файлы объединяются в один css-файл. Делается это с помощью команды @import. Откройте файл style.scss и посмотрите как это сделано в UniCSS.

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

@import 'unicss/normalize';

Здесь в реальности будет подключен файл unicss/_normalize.scss.

UniCSS используется каталог unicss для файлов «ядра» фреймворка. Каталог main используется верстальщиком для размещения своих файлов и редактирования существующих. Таким образом, когда стоит задача настроить UniCSS под себя, следует использовать только каталог main.

Если проект достаточно большой, то можно создать под него отдельный каталог, например template, где размещать свои файлы. Естественно в style.scss нужно прописать подключение файлов с помощью @import.

Технически Sass может подключать все файлы из указанного каталога, а не по одному. Но в Windows такая работа @import происходит с ошибками (во всяком случае на старых версиях Sass), поэтому принято указывать каждый файл отдельно. К тому же такой подход позволяет подключать только нужные файлы.

Подключение файлов в любом Sass-проекте выполняется примерно по одному алгоритму.

В первую очередь подключаются все константы. Технически это те же переменные, но они очень редко меняются или вообще несут служебную нагрузку. Примеры: main/_colors-gmd.scss — это цвета из Google Material Design, main/_fontawesome.scss — коды иконок FontAwesome.

После этого загружаются общие/глобальные переменные. Обычно это размеры, цвета и т.п. Данное размещение решает две задачи. Первая — все эти переменные доступны из одного места, что само по себе удобно, и вторая — они будут доступны во всех scss-файлах.

Дальше идёт загрузка css-сбросов — они должны быть первыми по коду. После следует основное «ядро» (каталог unicss). В «ядре» содержатся не только стили, но и миксины — это пользовательские функции Sass. Обычно они загружаются раньше, чтобы быть доступными для файлов ниже по коду.

Ближе к концу загружаются уже свои пользовательские файлы (каталог main). Обратите внимание, что unicss/colors так же загружается в конце. Сделано это для того, чтобы придать классам цвета больший приоритет (при равном весе селектора).

Предусмотрено два специальных файла: main/_extension-unicss.scss используется для классов построенных по правилам UniCSS и расширяющие его возможности. Второй файл main/_my-template.scss используется для размещения своих стилей. Если проект небольшой (как в нашем курсе), то одного файла будет вполне достаточно.

Знакомство с устройством UniCSS лучше начать с файлов каталога main. Во многих файлах вы увидите обычный css-код. Он 100% совместим с Sass.

Для создания комментариев в Sass используется два варианта. Первый — однострочный, который начинается с двойного слэша // и действует до конца строки. Второй — многострочный, который обрамляется в css-стиле /* */.

// однострочный комментарий

/*
	многострочный
*/

С вложенностью мы уже знакомы с прошлого урока. Расмотрим несколько типовых примеров.

table {
	width: 100%;

	th { 
		text-align: left;
		background: #EEEEEE;
	}
	
	td { 
		vertical-align: top; 
	}

	th, td {
		padding: 3px 5px;
	}
}

Данный пример интуитивно понят. Селектор «table» будет подставлен под каждый «подселектор», включая перечисленные через запятую. Получится такой css-код:

table { width: 100%; }

table th { text-align: left; background: #EEEEEE; }
	
table td { vertical-align: top; }

table th, table td { padding: 3px 5px; }

То есть подстановка происходит через пробел, что формирует вложенные селекторы.

Там, где нужно сформировать селекторы класса и другие аналогичные, используется специальный символ &. Он заменяется на «этот же» селектор (родителя). Рассмотрим пример:

hr {
	display: block;
	padding: 0;
	border: 0;
	border-top: 1px solid #AAAAAA;
	
	&.dashed {
		border-top-style: dashed;
	}
	
	&.dotted {
		border-top-style: dotted;
	}
}

Символ & заменится на hr:

hr { display: block; padding: 0; border: 0; border-top: 1px solid #AAAAAA; }

hr.dashed { border-top-style: dashed; }

hr.dotted { border-top-style: dotted; }

Вложенности могут быть достаточно сложными. Тут следует ориентироваться в первую очередь на два момента. Первый — css-код не должен быть усложнен там, где не следует, и второй — удобство чтения. Скажем в вышеприведенном примере селекторы table th, table td явно излишни, поскольку th и td используются только внутри table. Но зато такой код намного читабельней и сразу видно, что он описывает таблицу.

Рассмотрим еще один пример, где & вложен во вложение.

a {
	&.hover-no-color {
		&:hover {
			color: inherit;
		}
	}
	
	&.hover-no-underline {
		&:hover {
			text-decoration: none;
		}
	}
}

Результат:

a.hover-no-color:hover { color:inherit; }
a.hover-no-underline:hover { text-decoration:none; }

То есть Sass достаточно сообразителен, чтобы понять как правильно сформировать css-правило.

Для гибкого управления кодом в Sass используются переменные. Все переменные начинаются с символа $, а после через : указывается значение:

$layout_max_width: 992px;
$icon_size: 32px;
$colorLink: #002DB3;
$color1: $g_pink500;
$rounded_list: 0, 5, 10;

В UniCSS все глобальные переменные хранятся в файле main/_variables.scss. В переменной могут храниться числа, код цвета, другая переменная и т.п. Также Sass поддерживает списки — это наборы значений, которые указываются через запятую. Есть еще ассоциативные списки, похожие на массивы. Они указываются в скобках:

$color_step_list: (
	"red":     $red, 
	"green":   $green, 
	"blue":    $blue
);

Такие вещи достаточно специфичны и используются в css-фреймворках или других сложных проектах.

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

$SCREEN_DESKTOP: "(max-width: 1100px)";

Чтобы её использовать в Sass-коде нужно применить дополнительное «обрамление» #{ }:

@media #{$SCREEN_DESKTOP} {
	.visible-desktop { 
		display: block; 
	}
}

Что приведет к результату:

@media (max-width: 1100px) {
	.visible-desktop {
		display:block;
	}
}

При попытке скомпилировать такой код без «обрамления», Sass выдаст ошибку «Error: Invalid CSS after "@media"».

Если же стоит задача просто передать переменную как есть, то не нужно указывать кавычки:

$font: Arial, Helvetica, Verdana, sans-serif;

.t-arial { 
	font-family: $font; 
}

Главное условие, чтобы в значении переменной не было служебных символов, как они присутствуют в $SCREEN_DESKTOP (например двоеточие).

Если какая-то часть кода повторяется, то используются миксины (или примеси). Например нужно оформить несколько блоков, которые содержат одинаковые css-стили, но с разными значениями. Создается миксин у которого параметры будут отвечать за значения свойств. Для создания миксина используется служебное слово @mixin:

@mixin set_block($color, $margin, $padding) {
	color: $color;
	margin: $margin;
	padding: $padding;
}
Для того, чтобы использовать миксин применяют @include:
.block1 { @include set_block(red, 10px, 20px); }
.block2 { @include set_block(#f08040, 10px 0, 20px 20px 0 10px); }

Что приведет к такому результату:

.block1 {
	color: red;
	margin: 10px;
	padding: 20px; 
}

.block2 {
	color: #f08040;
	margin: 10px 0;
	padding: 20px 20px 0 10px; 
}

Иногда стоит задача включить в стили какой-то уже существующий класс. Делается это с помощью команды @extend:

.bold { font-weight: bold; } 
.red { color: red; }

.bold-red {
	@extend .bold;
	@extend .red;
}

Результат:

.bold, 
.bold-red {
	font-weight: bold; 
}

.red, 
.bold-red {
	color: red; 
}

То есть Sass объединил классы с одинаковыми свойствами. Такой подход позволяет сократить результирующий css-код и очень часто используется когда вопрос оптимизации кода стоит остро.

Sass поддерживает основные математические операции: + - * / %. Работают они как обычно, поэтому досконально рассматривать не будем. Более интересны собственные функции Sass, которые позволяют решать действительно сложные задачи. Таких функций очень много и все их изучать смысла нет, достаточно просто ознакомиться с общим списком. Как правило при верстке часто используются функции для работы с цветом.

Например нужно использовать оттенок базового цвета, но чуть светлее или темнее. Для этого применяют функции lighten() и darken().

$color: #f08040;

.block1 { color: lighten($color, 10%); } 
.block2 { color: darken($color, 10%); }

Первый блок получит цвет на 10% светлее (#f49f6f) базового, а второй на 10% темнее (#eb6112)

Полностью вся документация по Sass доступна на официальном сайте, но для большинства работ вам будет вполне достаточно приведенной мной информации.

Задания

Задания доступны только после авторизации.