У меня достаточно неплохой опыт в верстке — несколько лет.
За это время было многое — и табличная верстка, и собственные фреймворки, и IE6, и адаптивный дизайн, да что угодно — я всегда старался быть рядом с bleeding edge, как говорится.
Больше CSS-фреймворков (привет, бутстрап) и Emmet-а мне нравятся препроцессоры и я расскажу, почему. Возможно, покажется, что моя статья несколько устарела и сейчас все используют препроцессоры как само собой разумеющееся, но, увы, это не так. Недавно я встретил человека, который говорил о том, что ему быстрее писать CSS-код, нежели использовать препроцессоры. Мы долго спорили, на самом деле, ну очень долго, в итоге я решил выложить свои мысли здесь, в одном месте.
Less или Sass?
Ну, на самом деле, это дело каждого. Мне не нравился Sass из-за его медлительности — Less побыстрее выполнялся всегда, в итоге в один момент я решил перейти на Less, но через некоторое время оказалось, что мне не хватает его мощности! Увы, я так и не нашел, как реализовать банальный миксин уровня вот этого.
Но и медлительность Sass не устраивала, но именно в тот момент, когда я хотел обратно вернуться на Sass, но терзался сомнениями, мне посоветовали libsass, а т.к. я использую Grunt — мне было достаточно подключить только grunt-sass (и ничего больше, например, установка Ruby и гемов). Для меня выбор был ясен и с тех пор — только libsass. Мощность самого Sass и с скорость C — что еще нужно?
Stylus я пока не пробовал, как-нибудь потом.
Почему все-таки препроцессоры?
Я не скажу ничего нового, скорее всего, но я хочу показать, почему стоит использовать препроцессоры.
Переменные
Переменные — это нечто великолепное. Мне стали в упрек «препроцессоры были придуманы программистом, не верстальщиком», но как можно отказываться от переменных? Простой пример, который сильно облегчает жизнь — так как я в том числе еще и дизайнер, все цвета, настройки шрифтов и т.п. по проекту мне достаточно хранить в файле _variables.scss
$white: rgb(255, 255, 255);
$lightgray: rgb(238, 238, 238);
$gray: rgb(153, 153, 153);
$asphalt: rgb(85, 85, 85);
$black: rgb(17, 17, 17);
$blue: rgb(85, 164, 242);
$lightblue: rgb(91, 192, 222);
$green: rgb(46, 204, 113);
$orange: rgb(230, 126, 34);
$magenta: rgb(228, 183, 240);
$red: rgb(231, 76, 60);
$bgBrand: linear-gradient(to left, rgba(26,214,253,1) 0%, rgba(85,164,242,0.72) 100%) no-repeat center center fixed;
$bgBlueLight: linear-gradient(rgb(26, 214, 253) 0%, rgb(29, 98, 240) 100%) no-repeat center center fixed;
$bgPinkViolet: linear-gradient(#EF4DB6 0%, #C643FC 100%) no-repeat center center fixed;
$bgWhiteGray: linear-gradient(#F7F7F7 0%, #D7D7D7 100%) no-repeat center center fixed;
Затем, когда мне это необходимо, я лишь указываю переменную, а не полное свойство. background: $bgBrand, а т.к. у меня бэкграунды используются во многих местах, мне проще отредактировать свойство переменной в одном месте, а не делать поиск по файлам или даже по одному файлу — все равно дольше, чем отредактировать в одном месте.
Вложенность
Что может быть лучше вложенности :hover, :after, :before, :nth-child в родительский элемент?
Простой, очень простой пример:
a {
color: $blue;
&:hover {
color: darken($blue, 10%);
}
}
В нем я использую переменные, внутреннюю функцию darken()
и ту самую вложенность. Казалось бы, мелочь, но из таких мелочей и состоит верстка. В разы удобнее смотреть, что относится к конкретному блоку, следя за тем, что находится внутри него, а не за тем, что идет ниже. Да и писать каждый раз .my-super-class:hover
все-таки бессмысленно. Сторонники БЭМ-подхода оценили бы такую возможность, но у них там свои инструменты.
Мне нужно было сделать таблицу, где отсутствовали заголовки (я использовал Bootstrap).
.table-information {
tr {
th {
height: 0;
padding: 0;
border: 0;
}
td {
border-top: 0;
border-bottom: 1px solid $lightgray;
}
&:last-child {
td {
border-bottom: 0;
}
}
}
}
Миксины, импорты и т.п.
Самый главный плюс препроцессоров — это в миксинах, экстендах и т.п. Это как функции в нормальном языке — можно использовать бесконечное количество раз, подключая когда необходимо. Лично я не так часто использую миксины, но т.к. я верстаю с подходом mobile first, мне очень сильно помогает один маленький миксин, о котором я уже упомянул:
@mixin responsive($media) {
@if $media == sm {
@media (min-width: 768px) { @content; }
}
@else if $media == md {
@media (min-width: 992px) { @content; }
}
@else if $media == lg {
@media (min-width: 1200px) { @content; }
}
@else if $media == xlg {
@media (min-width: 1700px) { @content; }
}
}
Используется достаточно просто, как @media-queries: @include responsive(sm) { background-color: red }
и это вместе с вложенностью элементов.
Импорты — существуют и в CSS, но не так, как хотелось бы. Т.к. речь идет о препроцессорах, в них в конечном счете все подключенные файлы собираются в один — и это полезно, потому что делается только один запрос на сервер. Для того, чтобы держать архитектуру проекта по неким модулям или просто блокам, импорты достаточно полезны.
«Я не могу разобраться в сгенерированном коде»
Когда я услышал этот аргумент, я не совсем понял, о чем шла речь. Затем мне разъяснили (человек работает на фрилансе) — к нему поступает проект с Sass или Less, но сгенерированный код ужасен, в нем нельзя разобраться. И это неправильный подход, потому что препроцессоры — для людей, для того, чтобы было удобно разрабатывать, держать архитектуру проекта в нормальном состоянии. Если человек пишет нормально, CSS на выходе получается оптимизированным, с этой стороны нет никакой разницы, на чем было написано — на CSS или Sass, Sass лишь помогает разработчику, а не браузеру. Для поддержки браузером есть Source maps, поддержка которых в нормальных инструментах типа Grunt есть из коробки.
Пример
Не так давно я разрабатывал один проект, в котором мне понадобились кнопки социальных сетей — не так много, штук 5, но именно тогда я задумался над тем, чтобы сделать библиотеку с использованием Sass, где хранилось бы огромное количество кнопок. Разумеется, делать это на CSS было бы неудобно, именно поэтому я решил использовать Sass. Тот человек, с которым мы спорили, в итоге отметил изящность решения.
Для того, чтобы сделать Brand Buttons, мне понадобилось совсем немного:
- Один список-массив с
brand: color
- Миксин, где хранятся все свойства
- И одна функция, которая генерирует классы
В итоге 3 файла, в которых я использовал небольшую, но мощную часть возможностей Sass: переменные, импорты, миксины, внутренние функции типа @each/for. Конечный CSS вышел на 687 строк.
Для того, чтобы добавить новую кнопку в этот проект, мне достаточно в _variables.scss вставить одну строчку brand: color и запустить grunt build
, а не создавать новые классы вручную.
Препроцессоры — это история о том, как мелочи типа переменных способны сильно увеличить производительность. Препроцессоры, может быть, и написаны программистами, но при этом они не привносят ничего сложного, лишь улучшают жизнь: код остается читабельным, даже более того — его становится меньше, он становится более стройным. В этой статье я не рассказал о многих возможностях, но у меня было желание показать, почему я использую препроцессоры и какие плюсы они дают тем, кто все-таки решится.
Автор: justusebrain