Sass, LESS, Stylus - какой лучше: перепроцессор Shootout
Russian (Pусский) translation by Liliya (you can also view the original English article)
Использование действительной мощности препроцессора CSS - это приключение. Есть бесчисленные языки, синтаксисы и функции, готовые к использованию прямо сейчас.
В этой статье мы рассмотрим различные функции и преимущества использования трех разных препроцессоров: Sass, LESS и Stylus.
Вступление
Препроцессоры создают CSS, который работает во всех браузерах.
Препроцессоры CSS3 - это языки, написанные с единственной целью добавления классных, изобретательных функций в CSS без нарушения совместимости браузера. Они делают это, компилируя код, который мы пишем, в обычный CSS, который можно использовать в любом браузере, вплоть до возвращения в каменный век. Есть тысячи функций, которые препроцессоры приносят в таблицу, и в этой статье мы рассмотрим некоторые известные и некоторые не известные. Давайте начнем.
Синтаксих
Наиболее важной частью написания кода в препроцессоре CSS является понимание синтаксиса. К счастью для нас, синтаксис (или может быть) идентичен регулярному CSS для всех трех препроцессоров.
Sass & LESS
Sass и LESS используют стандартный синтаксис CSS. Это упрощает преобразование существующего файла CSS в препроцессор. Sass использует расширение .scss, а LESS использует расширение .less. Базовый файл Sass или LESS можно настроить следующим образом:
1 |
/* style.scss or style.less */
|
2 |
h1 { |
3 |
color: #0982C1; |
4 |
}
|
Как вы могли заметить, это просто обычный CSS, который отлично компилируется как в Sass, так и в LESS.
Важно отметить, что Sass также имеет более старый синтаксис, который пропускает точки с запятой и фигурные скобки. Хотя это все еще используют, оно устарело, и мы не будем использовать его в этом примере. Синтаксис использует расширение .sass и выглядит так:
1 |
/* style.sass */
|
2 |
h1
|
3 |
color: #0982c1 |
Stylus
Синтаксис для Stylus более подробный. Используя расширение файла .styl, Stylus принимает стандартный синтаксис CSS, но также принимает некоторые другие варианты, в которых скобки, двоеточия и полуколоны являются необязательными. Пример:
1 |
/* style.styl */
|
2 |
h1 { |
3 |
color: #0982C1; |
4 |
}
|
5 |
|
6 |
/* omit brackets */
|
7 |
h1
|
8 |
color: #0982C1; |
9 |
|
10 |
/* omit colons and semi-colons */
|
11 |
h1
|
12 |
color #0982C1 |
Использование разных вариаций в одной таблице стилей также является допустимым, поэтому следующее будет компилироваться без ошибок.
1 |
h1 { |
2 |
color #0982c1 |
3 |
}
|
4 |
h2
|
5 |
font-size: 1.2em |
Переменные
Переменные могут быть объявлены и использованы во всей таблице стилей. Они могут иметь любое значение, которое является значением CSS (например, цветами, числами [включенными единицами] или текстом.), и на них можно ссылаться везде в нашей таблице стилей.
Sass
Переменные Sass добавляются с символом $, а значение и имя разделяются точкой с запятой, как и свойство CSS.
1 |
$mainColor: #0982c1; |
2 |
$siteWidth: 1024px; |
3 |
$borderStyle: dotted; |
4 |
|
5 |
body { |
6 |
color: $mainColor; |
7 |
border: 1px $borderStyle $mainColor; |
8 |
max-width: $siteWidth; |
9 |
}
|
LESS
LESS переменные точно такие же, как переменные Sass, за исключением того, что имена переменных добавляются символом @
1 |
@mainColor: #0982c1; |
2 |
@siteWidth: 1024px; |
3 |
@borderStyle: dotted; |
4 |
|
5 |
body { |
6 |
color: @mainColor; |
7 |
border: 1px @borderStyle @mainColor; |
8 |
max-width: @siteWidth; |
9 |
}
|
Stylus
Переменные Stylus не требуют, чтобы что-то было добавлено к ним, хотя оно допускает символ $. Как всегда, конечная точка с запятой не требуется, но знак равенства между значением и переменной есть. Следует отметить, что Stylus (0.22.4) компилируется, если мы добавим символ @ к имени переменной, но не будем применять значение при ссылке. Другими словами, не делайте этого.
1 |
mainColor = #0982c1 |
2 |
siteWidth = 1024px |
3 |
$borderStyle = dotted |
4 |
|
5 |
body
|
6 |
color mainColor |
7 |
border 1px $borderStyle mainColor |
8 |
max-width siteWidth |
Скомпилированный CSS
Каждый из вышеуказанных файлов будет скомпилирован с тем же CSS. Вы можете использовать свое воображение, чтобы узнать, насколько полезны переменные. Нам больше не нужно будет менять один цвет и повторить его двадцать раз, или мы хотим изменить ширину нашего сайта и вынуждены его искать, чтобы найти его. Вот CSS после компиляции:
1 |
body { |
2 |
color: #0982c1; |
3 |
border: 1px dotted #0982c1; |
4 |
max-width: 1024px; |
5 |
}
|
Nesting
Если нам нужно ссылаться на несколько элементов с одним и тем же источником в нашем CSS, это может быть утомительно писать его снова и снова.
1 |
section { |
2 |
margin: 10px; |
3 |
}
|
4 |
section nav { |
5 |
height: 25px; |
6 |
}
|
7 |
section nav a { |
8 |
color: #0982C1; |
9 |
}
|
10 |
section nav a:hover { |
11 |
text-decoration: underline; |
12 |
}
|
Вместо этого, используя препроцессор, мы можем записать дочерние селекторы внутри скобок родителя. Кроме того, символ & обозначает родительский селектор.
Sass, LESS, и Stylus
Все три препроцессора имеют одинаковый синтаксис для селекторов вложенности.
1 |
section { |
2 |
margin: 10px; |
3 |
|
4 |
nav { |
5 |
height: 25px; |
6 |
|
7 |
a { |
8 |
color: #0982C1; |
9 |
|
10 |
&:hover { |
11 |
text-decoration: underline; |
12 |
}
|
13 |
}
|
14 |
}
|
15 |
}
|
Скомпилированный CSS
Это скомпилированный CSS из приведенного выше кода. Это точно так же, как то когда мы начали то что удобно!
1 |
section { |
2 |
margin: 10px; |
3 |
}
|
4 |
section nav { |
5 |
height: 25px; |
6 |
}
|
7 |
section nav a { |
8 |
color: #0982C1; |
9 |
}
|
10 |
section nav a:hover { |
11 |
text-decoration: underline; |
12 |
}
|
Mixins
Mixins - это функции, которые позволяют повторно использовать свойства во всей нашей таблице стилей. Вместо того, чтобы идти по всей нашей таблице стилей и менять свойство несколько раз, теперь мы можем просто изменить его внутри нашего mixin. Это может быть действительно полезно для конкретного стиля элементов и префиксов поставщиков. Когда mixins вызывается из селектора CSS, аргументы mixin распознаются, а стили внутри mixin применяются к селектору.
Sass
1 |
/* Sass mixin error with (optional) argument $borderWidth which defaults to 2px if not specified */
|
2 |
@mixin error($borderWidth: 2px) { |
3 |
border: $borderWidth solid #F00; |
4 |
color: #F00; |
5 |
}
|
6 |
|
7 |
.generic-error { |
8 |
padding: 20px; |
9 |
margin: 4px; |
10 |
@include error(); /* Applies styles from mixin error */ |
11 |
}
|
12 |
.login-error { |
13 |
left: 12px; |
14 |
position: absolute; |
15 |
top: 20px; |
16 |
@include error(5px); /* Applies styles from mixin error with argument $borderWidth equal to 5px*/ |
17 |
}
|
LESS
1 |
/* LESS mixin error with (optional) argument @borderWidth which defaults to 2px if not specified */
|
2 |
.error(@borderWidth: 2px) { |
3 |
border: @borderWidth solid #F00; |
4 |
color: #F00; |
5 |
}
|
6 |
|
7 |
.generic-error { |
8 |
padding: 20px; |
9 |
margin: 4px; |
10 |
.error(); /* Applies styles from mixin error */ |
11 |
}
|
12 |
.login-error { |
13 |
left: 12px; |
14 |
position: absolute; |
15 |
top: 20px; |
16 |
.error(5px); /* Applies styles from mixin error with argument @borderWidth equal to 5px */ |
17 |
}
|
Stylus
1 |
/* Stylus mixin error with (optional) argument borderWidth which defaults to 2px if not specified */
|
2 |
error(borderWidth= 2px) { |
3 |
border: borderWidth solid #F00; |
4 |
color: #F00; |
5 |
}
|
6 |
|
7 |
.generic-error { |
8 |
padding: 20px; |
9 |
margin: 4px; |
10 |
error(); /* Applies styles from mixin error */ |
11 |
}
|
12 |
.login-error { |
13 |
left: 12px; |
14 |
position: absolute; |
15 |
top: 20px; |
16 |
error(5px); /* Applies styles from mixin error with argument borderWidth equal to 5px */ |
17 |
}
|
Скомпилированный CSS
Все препроцессоры составляют один и тот же код:
1 |
.generic-error { |
2 |
padding: 20px; |
3 |
margin: 4px; |
4 |
border: 2px solid #f00; |
5 |
color: #f00; |
6 |
}
|
7 |
.login-error { |
8 |
left: 12px; |
9 |
position: absolute; |
10 |
top: 20px; |
11 |
border: 5px solid #f00; |
12 |
color: #f00; |
13 |
}
|
Наследственность
При написании CSS старомодным способом мы могли бы использовать следующий код для одновременного применения одних и тех же стилей к нескольким элементам:
1 |
p, |
2 |
ul, |
3 |
ol { |
4 |
/* styles here */
|
5 |
}
|
Это отлично работает, но если нам нужно дополнительно стилизовать элементы по отдельности, для каждого из них должен быть создан другой селектор, и он может быстро стать более беспорядочным и сложным в обслуживании. Чтобы противостоять этому, можно использовать наследие. Наследие - это способность других селекторов CSS наследовать свойства другого селектора.
Sass & Stylus
1 |
.block { |
2 |
margin: 10px 5px; |
3 |
padding: 2px; |
4 |
}
|
5 |
|
6 |
p { |
7 |
@extend .block; /* Inherit styles from '.block' */ |
8 |
border: 1px solid #EEE; |
9 |
}
|
10 |
ul, ol { |
11 |
@extend .block; /* Inherit styles from '.block' */ |
12 |
color: #333; |
13 |
text-transform: uppercase; |
14 |
}
|
Скомпилированный CSS (Sass & Stylus)
1 |
.block, p, ul, ol { |
2 |
margin: 10px 5px; |
3 |
padding: 2px; |
4 |
}
|
5 |
p { |
6 |
border: 1px solid #EEE; |
7 |
}
|
8 |
ul, ol { |
9 |
color: #333; |
10 |
text-transform: uppercase; |
11 |
}
|
LESS
LESS действительно не наследует стили Sass и Stylus. Вместо добавления нескольких селекторов к одному набору свойств он рассматривает наследование как mixin без аргументов и импортирует стили в свои собственные селекторы. Недостатком этого является то, что свойства повторяются в вашей скомпилированной таблице стилей. Вот как вы его настроили:
1 |
.block { |
2 |
margin: 10px 5px; |
3 |
padding: 2px; |
4 |
}
|
5 |
|
6 |
p { |
7 |
.block; /* Inherit styles from '.block' */ |
8 |
border: 1px solid #EEE; |
9 |
}
|
10 |
ul, ol { |
11 |
.block; /* Inherit styles from '.block' */ |
12 |
color: #333; |
13 |
text-transform: uppercase; |
14 |
}
|
Скомпилированный CSS (LESS)
1 |
.block { |
2 |
margin: 10px 5px; |
3 |
padding: 2px; |
4 |
}
|
5 |
p { |
6 |
margin: 10px 5px; |
7 |
padding: 2px; |
8 |
border: 1px solid #EEE; |
9 |
}
|
10 |
ul, |
11 |
ol { |
12 |
margin: 10px 5px; |
13 |
padding: 2px; |
14 |
color: #333; |
15 |
text-transform: uppercase; |
16 |
}
|
Как вы можете видеть, стили из .block были вставлены в селектора, которые мы хотели бы наследовать. Важно отметить, что приоритет может стать проблемой здесь, поэтому будьте осторожны.
Импортирующий
В сообществе CSS импорт CSS не одобряется, поскольку ему требуется несколько HTTP-запросов. Однако импорт с препроцессором работает по-разному. Если вы импортируете файл из любого из трех препроцессоров, он будет буквально включать импорт во время компиляции, создавая только один файл. Имейте в виду, что импортирование обычных файлов .css компилируется по умолчанию с помощью @import «file.css»; code. Кроме того, mixins и переменные могут быть импортированы и использованы в вашей основной таблице стилей. Импорт делает создание отдельных файлов для организации очень хорошо.
Sass, LESS, и Stylus
1 |
/* file.{type} */
|
2 |
body { |
3 |
background: #EEE; |
4 |
}
|
1 |
@import "reset.css"; |
2 |
@import "file.{type}"; |
3 |
|
4 |
p { |
5 |
background: #0982C1; |
6 |
}
|
Скомпилированный CSS
1 |
@import "reset.css"; |
2 |
body { |
3 |
background: #EEE; |
4 |
}
|
5 |
p { |
6 |
background: #0982C1; |
7 |
}
|
Цветовые возможности
Цветовые функции встроены в функции, которые преобразуют цвет при компиляции. Это может быть чрезвычайно полезно для создания градиентов, более темных цветов и многое другое.
Sass
1 |
lighten($color, 10%); /* returns a color 10% lighter than $color */ |
2 |
darken($color, 10%); /* returns a color 10% darker than $color */ |
3 |
|
4 |
saturate($color, 10%); /* returns a color 10% more saturated than $color */ |
5 |
desaturate($color, 10%); /* returns a color 10% less saturated than $color */ |
6 |
|
7 |
grayscale($color); /* returns grayscale of $color */ |
8 |
complement($color); /* returns complement color of $color */ |
9 |
invert($color); /* returns inverted color of $color */ |
10 |
|
11 |
mix($color1, $color2, 50%); /* mix $color1 with $color2 with a weight of 50% */ |
Это всего лишь короткий список доступных цветовых функций в Sass, полный список доступных цветовых функций Sass можно найти, прочитав документацию Sass.
Цветовые функции можно использовать в любом месте, где используется цвет. Вот пример:
1 |
$color: #0982C1; |
2 |
|
3 |
h1 { |
4 |
background: $color; |
5 |
border: 3px solid darken($color, 50%); |
6 |
}
|
LESS
1 |
lighten(@color, 10%); /* returns a color 10% lighter than @color */ |
2 |
darken(@color, 10%); /* returns a color 10% darker than @color */ |
3 |
|
4 |
saturate(@color, 10%); /* returns a color 10% more saturated than @color */ |
5 |
desaturate(@color, 10%); /* returns a color 10% less saturated than @color */ |
6 |
|
7 |
spin(@color, 10); /* returns a color with a 10 degree larger in hue than @color */ |
8 |
spin(@color, -10); /* returns a color with a 10 degree smaller hue than @color */ |
9 |
|
10 |
mix(@color1, @color2); /* return a mix of @color1 and @color2 */ |
Список всех функций LESS можно найти, прочитав LESS Документацию.
Вот пример использования цветовой функции в LESS:
1 |
@color: #0982C1; |
2 |
|
3 |
h1 { |
4 |
background: @color; |
5 |
border: 3px solid darken(@color, 50%); |
6 |
}
|
Stylus
1 |
lighten(color, 10%); /* returns a color 10% lighter than 'color' */ |
2 |
darken(color, 10%); /* returns a color 10% darker than 'color' */ |
3 |
|
4 |
saturate(color, 10%); /* returns a color 10% more saturated than 'color' */ |
5 |
desaturate(color, 10%); /* returns a color 10% less saturated than 'color' */ |
Полный список всех функций цвета Stylus можно найти, прочитав Документацию Stylus.
Вот пример использования цветовых функций Stylus:
1 |
color = #0982C1 |
2 |
|
3 |
h1
|
4 |
background color |
5 |
border 3px solid darken(color, 50%) |
Эксплуатация
Выполнение математики в CSS очень полезно и теперь вполне возможно. Это просто, и вот как это сделать:
Sass, LESS, и Stylus
1 |
body { |
2 |
margin: (14px/2); |
3 |
top: 50px + 100px; |
4 |
right: 100px - 50px; |
5 |
left: 10 * 10; |
6 |
}
|
Практическое применение
Мы рассмотрели множество возможностей и новых возможностей, которые могут выполнять препроцессоры, но мы не затронули практику. Вот краткий список приложений реального мира, где использование препроцессора - спасатель.
Приставка поставщиков
Это одна из раздутых причин использовать препроцессор и по очень веской причине - это экономит массу времени и слез. Создание mixin для обработки префиксов поставщиков это легко и экономит много повторений и болезненного редактирования. Вот как это сделать:
Sass
1 |
@mixin border-radius($values) { |
2 |
-webkit-border-radius: $values; |
3 |
-moz-border-radius: $values; |
4 |
border-radius: $values; |
5 |
}
|
6 |
|
7 |
div { |
8 |
@include border-radius(10px); |
9 |
}
|
LESS
1 |
.border-radius(@values) { |
2 |
-webkit-border-radius: @values; |
3 |
-moz-border-radius: @values; |
4 |
border-radius: @values; |
5 |
}
|
6 |
|
7 |
div { |
8 |
.border-radius(10px);
|
9 |
}
|
Stylus
1 |
border-radius(values) { |
2 |
-webkit-border-radius: values; |
3 |
-moz-border-radius: values; |
4 |
border-radius: values; |
5 |
}
|
6 |
|
7 |
div { |
8 |
border-radius(10px);
|
9 |
}
|
Скомпилированный CSS
1 |
div { |
2 |
-webkit-border-radius: 10px; |
3 |
-moz-border-radius: 10px; |
4 |
border-radius: 10px; |
5 |
}
|
3D-текст
Подделка 3D-текста с использованием нескольких текстовых теней - умная идея. Единственная проблема в изменении цвета когда факт трудный и громоздкий. Используя mixins и цветовые функции, мы можем создавать 3D-текст и менять цвет «на лету»!
Sass
1 |
@mixin text3d($color) { |
2 |
color: $color; |
3 |
text-shadow: 1px 1px 0px darken($color, 5%), |
4 |
2px 2px 0px darken($color, 10%), |
5 |
3px 3px 0px darken($color, 15%), |
6 |
4px 4px 0px darken($color, 20%), |
7 |
4px 4px 2px #000; |
8 |
}
|
9 |
|
10 |
h1 { |
11 |
font-size: 32pt; |
12 |
@include text3d(#0982c1); |
13 |
}
|
LESS
1 |
.text3d(@color) { |
2 |
color: @color; |
3 |
text-shadow: 1px 1px 0px darken(@color, 5%), |
4 |
2px 2px 0px darken(@color, 10%), |
5 |
3px 3px 0px darken(@color, 15%), |
6 |
4px 4px 0px darken(@color, 20%), |
7 |
4px 4px 2px #000; |
8 |
}
|
9 |
|
10 |
span { |
11 |
font-size: 32pt; |
12 |
.text3d(#0982c1);
|
13 |
}
|
Stylus
1 |
text3d(color) |
2 |
color: color |
3 |
text-shadow: 1px 1px 0px darken(color, 5%), 2px 2px 0px darken(color, 10%), 3px 3px 0px darken(color, 15%), 4px 4px 0px darken(color, 20%), 4px 4px 2px #000 |
4 |
span
|
5 |
font-size: 32pt |
6 |
text3d(#0982c1) |
Я решил написать текстовые тени Stylus на одной строке, потому что я опустил фигурные скобки.
Скомпилированный CSS
1 |
span { |
2 |
font-size: 32pt; |
3 |
color: #0982c1; |
4 |
text-shadow: 1px 1px 0px #097bb7, |
5 |
2px 2px 0px #0875ae, |
6 |
3px 3px 0px #086fa4, |
7 |
4px 4px 0px #07689a, |
8 |
4px 4px 2px #000; |
9 |
}
|
Конечный результат

Столбец
Использование числовых операций и переменных для столбцов - это идея, которую я придумал, когда я впервые играл с препроцессорами CSS. Объявив желаемую ширину в переменной, мы можем легко изменить ее в течении работы без какой-либо сложной математики. Вот как это делается:
Sass
1 |
$siteWidth: 1024px; |
2 |
$gutterWidth: 20px; |
3 |
$sidebarWidth: 300px; |
4 |
|
5 |
body { |
6 |
margin: 0 auto; |
7 |
width: $siteWidth; |
8 |
}
|
9 |
.content { |
10 |
float: left; |
11 |
width: $siteWidth - ($sidebarWidth+$gutterWidth); |
12 |
}
|
13 |
.sidebar { |
14 |
float: left; |
15 |
margin-left: $gutterWidth; |
16 |
width: $sidebarWidth; |
17 |
}
|
LESS
1 |
@siteWidth: 1024px; |
2 |
@gutterWidth: 20px; |
3 |
@sidebarWidth: 300px; |
4 |
|
5 |
body { |
6 |
margin: 0 auto; |
7 |
width: @siteWidth; |
8 |
}
|
9 |
.content { |
10 |
float: left; |
11 |
width: @siteWidth - (@sidebarWidth+@gutterWidth); |
12 |
}
|
13 |
.sidebar { |
14 |
float: left; |
15 |
margin-left: @gutterWidth; |
16 |
width: @sidebarWidth; |
17 |
}
|
Stylus
1 |
siteWidth = 1024px; |
2 |
gutterWidth = 20px; |
3 |
sidebarWidth = 300px; |
4 |
|
5 |
body { |
6 |
margin: 0 auto; |
7 |
width: siteWidth; |
8 |
}
|
9 |
.content { |
10 |
float: left; |
11 |
width: siteWidth - (sidebarWidth+gutterWidth); |
12 |
}
|
13 |
.sidebar { |
14 |
float: left; |
15 |
margin-left: gutterWidth; |
16 |
width: sidebarWidth; |
17 |
}
|
Скомпилированный CSS
1 |
body { |
2 |
margin: 0 auto; |
3 |
width: 1024px; |
4 |
}
|
5 |
.content { |
6 |
float: left; |
7 |
width: 704px; |
8 |
}
|
9 |
.sidebar { |
10 |
float: left; |
11 |
margin-left: 20px; |
12 |
width: 300px; |
13 |
}
|
Известные причуды
Существует несколько приколов к использованию препроцессора CSS. Я собираюсь перечислить некоторые причуды, но если вам действительно интересно узнать все, я рекомендую вам изучать документацию или, еще лучше, просто начните использовать препроцессор в ежедневной кодировке.
Отчет об ошибках
Если вы написали CSS за какое-то приличное время, я уверен, что вы достигли точки, где вы где-то ошиблись, и просто не могли ее найти. Если вы похожи на меня, вы, вероятно, провели день, дергая свои волосы и комментируя различные вещи, чтобы найти ошибку.
Препроцессоры CSS сообщают об ошибках. Все просто. Если что-то не так с вашим кодом, он сообщает вам, где именно ошибка, и если вам повезло: почему. Ваш перевод будет отображаться на этом посте. Используйте левую сторону, чтобы ввести его.
Комментарии
При компиляции с препроцессором CSS любой комментарий с двойной косой чертой удаляется (например, // комментарий) и сохраняется любой комментарий косой черты (например, /* comment */). При этом используйте двойную косую черту для комментариев, которые вы хотите на не скомпилированной стороне, и слэш-звездочкой для комментариев, которые вы хотите видеть после компиляции.
Просто примечание: если вы компилируете minified, все комментарии удаляются.
Заключение
Каждый препроцессор CSS, который мы рассмотрели (Sass, LESS и Stylus), имеет свой собственный уникальный способ выполнения той же задачи, предоставляя разработчикам возможность использовать полезные неподдерживаемые функции, сохраняя при этом совместимость браузера и чистоту кода.
Хотя это не требование для разработки, препроцессоры могут сэкономить много времени и иметь некоторые очень полезные функции.
Я призываю всех вас попробовать как можно больше препроцессоров, чтобы вы могли эффективно выбирать фаворита и знать, почему его предпочитают другие. Если вы еще не пытались использовать препроцессор для написания CSS, я настоятельно рекомендую вам попробовать.
У вас есть любимая функция препроцессора CSS, о которой я не упоминал? Есть ли что-то, что можно сделать иначе? Дайте нам знать в комментариях ниже!
Особая благодарность Karissa Smith, супер-талантливому другу, которая создала миниатюру для этой статьи.



