Sass (Syntactically Awesome Style Sheets) - модуль, включенный в HAML (HTML Abstraction Markup Language - язык разметки для упрощённой генерации HTML. HAML компилируется в HTML.). Sass - это метаязык на основе CSS, предназначенный для увеличения уровня абстракции CSS кода и упрощения файлов каскадных таблиц стилей.

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


Синтаксис

Для Sass доступно два синтаксиса. Первый, известный как SCSS (Sassy CSS) и используемый повсюду в этой статье - это расширенный синтаксис CSS. Это означает, что каждая валидная таблица стилей CSS это валидный SCSS файл, несущий в себе туже самую логику. Более того, SCSS понимает большинство хаков в CSS и вендорные синтаксисы, например такой как синтаксис фильтра в старом IE. Этот синтаксис улучшен Sass функционалом описанным ниже. Файлы использующие этот синтаксис имеют .scss расширение.

Второй и более старый синтаксис, даёт более сжатую возможность работы с CSS. Он использует отступы вместо скобок, чтобы отделить вложения селекторов и новые строки вместо точек с запятой для разделения свойств. Иногда люди находят такой способ проще для понимания и быстрее для написания, чем SCSS. По факту, такой синтаксис имеет тот же функционал, хотя некоторые из них имеют слегка другой подход. Файлы используемые этот синтаксис имеют расширение .sass.

Любой синтаксис может импортировать файлы, написанные в другом. Файлы могут быть автоматически сконвертированы из одного в другой, используя sass-convert команду:

# Convert Sass to SCSS
$ sass-convert style.sass style.scss

# Convert SCSS to Sass
$ sass-convert style.scss style.sass

Использование Sass

Sass может быть использован тремя способами: как командной строкой, как отдельный модуль Ruby и как плагин для rack-фреймворка, включая Ruby on Rails и Merb. Первым делом для всего этого надо установить Sass gem:

gem install sass

Если вы на Windows, то возможно вам надо установить сначала Ruby.

Для запуска Sass из командной строки просто используйте:

sass input.scss output.css

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

sass --watch input.scss:output.css

Если у вас есть директория с множеством Sass файлов, то вы также можете указать Sass следить за всей директорией:

sass --watch app/sass:public/stylesheets

Используйте sass --help для полной документации.


Селекторы

#main {
    color: #999;
}

#main .content {
    color: #bfbfbf;
}

CSS отрывок выше, может быть написан в SCSS таким образом:

#main {
    color: #999;
    
    .content {
        color: #bfbfbf;
    }
}

Как мы можем видеть, SCSS структура более схожа с DOM структурой. Это позволяет нам организовать наш CSS более эффективно.

Ссылаясь на родительский селектор:

#wrapper h1 {
    width: 20px;

    &:hover {
        width: 25px;
    }
}

& будет заменен родительским селектором. То есть код выше, будет эквиалентен:

#wrapper h1 {
    width: 20px;
}

#wrapper h1:hover {
    width: 25px;
}

Импорты

- Нормальный импорт

@import “foo.css”;    // импортирует foo.css
@import “foo” screen;    / /импортирует foo.scss
@import “foo.scss” screen;    // импортирует foo.scss
@import “foo1”, ”foo2" screen;    //импортирует foo1.scss и foo2 scss

- Частичный

Если вы не хотите компилировать SCSS файл как CSS, вы можете использовать “_” перед названием файла.

@import “_colors”;    / /_colors.scss будет импортирован
@import “utils/foo.scss”;    // Это импортирует fo.scss в папку utils

- Вложенные импорты

Если demo.scss включает в себя:

.example {
    color: red;
}

то:

#main {
    @import “demo”;
}

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

#main .example {
    color: red;
}

Переменные

SCSS переменные начинаются с символа $.

$width: 10px;
$headercolor:red;

#main h1 {
    width: $width;
    color: $headercolor;
}

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

#main h1 {
    width: 10px;
    color: red;
}

Переменные доступны только внутри уровня вложенного селектора где они объявляются. Если вы хотите хотите, чтобы переменная была доступна за пределами скоупа, то вам нужно добавить к ней !global:

#main {
    $width: 5em !global;
    width: $width;
}

#sidebar {
    width: $width;
}

Вы можете указывать переменные в отдельном файле и вы можете импортировать этот scss файл, чтобы использовать эти переменные. Это как конфиг файл для вашего проекта. Если вы меняете значение переменных, то оно будет изменено везде, где вы его используете. Это очень эффективно для больших проектов. Мы увидим это чуть позже.

Вы также можете производить разные операции в SCSS. Для примера:

p {
    font: 10px/8px; // Чистый CSS без деления
    $width: 1000px;
    width: $width/2; // Использование переменных в делении
    height: (500px/2); // Использование скобок и деления
    margin-left: 5px + 8px/2px; // Использование сложения и деления
}

Скомпилируется в:

p {
    font: 10px/8px;
    width: 500px;
    height: 250px;
    margin-left: 9px;
}

Вставка: #{}

Вы можете использовать переменные в свойствах имен и значения, используя #{}. Для примера:

$name: foo;
$attr: border;

p.#{$name} {
    #{$attr}-color: blue;
}

Скомпилируется в:

p.foo {
    border-color: blue;
}

Управляющие директивы

@if

p {
    @if 1 + 1 == 2 { border: 1px solid; }
    @if 5 < 3 { border: 2px dotted; }
    @if null { border: 3px double; }
}

Скомпилируется в:

p {
    border: 1px solid;
}

- @for

@for $i from 1 through 3 {
    .item-#{$i} { width: 2em * $i; }
}

Скомпилируется в:

.item-1 { width: 2em; }
.item-2 { width: 4em; }
.item-3 { width: 6em; }

@each

@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) {
    #{$header} {
        font-size: $size;
    }
}

Скомпилируется в:

h1 { font-size: 2em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.2em; }

@while

$i: 6;

@while $i > 0 {
    .item-#{$i} {
        width: 2em * $i;
    }

    $i: $i - 2;
}

Скомпилируется в:

.item-6 { width: 12em; }
.item-4 { width: 8em; }
.item-2 { width: 4em; }

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

Миксины позволяют вам определять стили, которые могут быть переиспользованы на протяжении всей таблицы стилей. Вы можете думать о миксинах, как о функциях в каком-либо другом языке програмирования. Вы можете передавать переменные, также как в функциях любого другого языка програмирования. В SCSS миксины возврашают набор CSS правил. Вы можете использовать миксины так: @include имя-миксина, определенное директивой @mixin.

Рассмотрите следующий пример:

@mixin large-text {
    font: {
        family: Arial;
        size: 20px;
        weight: bold;
    }
    color: #ff0000;
}

.page-title {
    @include large-text;
    padding: 4px;
    margin-top: 10px;
}

Скомпилируется в:

.page-title {
    font-family: Arial;
    font-size: 20px;
    font-weight: bold;
    color: #ff0000;
    padding: 4px;
    margin-top: 10px;
}

Вы также можете использовать составные миксины, например как:

@mixin mixin-one {
    color: red;
}

@mixin mixin-two {
    width: 20px;
}

.page-title {
    @include mixin-one;
    @include mixin-two;
}

Вы также можете передавать переменные в миксинах:

$global-prefixes: webkit moz ms o;

@mixin prefixer ($property, $value, $prefixes:null) {
    @if $prefixes == null {
        @each $prefix in $global-prefixes {
            -#{$prefix}-#{$property}: $value;
        }
    } @else {
        @each $prefix in $prefixes {
            -#{$prefix}-#{$property}: $value;
        }
    }

    #{$property}: $value;
}

*{
    @include prefixer(box-sizing, border-box);
}

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

*{
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -ms-box-sizing: border-box;
    -o-box-sizing: border-box;
    box-sizing: border-box;
}

Функции

Вы также можете определять функции, возвращающие значение. Для примера:

$no-of-columns: 12;
$gutter-width: 2%;

@function get-column-width($i) {
    @return (100% - ($no-of-columns/$i - 1) * $gutter-width) / $no-of-columns * $i;
}

.col-6 {
    width: get-column-width(6);
}

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

.col-6 {
    width: 49%;
}

Расширения

Вы столкнетесь с ситуацией, когда вам нужно будет переиспользовать стили. Рассмотрите следующий пример:

<button class="btn">Normal</button>
<button class="btn-blue">Blue</button>

Оба будут иметь одинаковые стили, кроме цвета:

.btn {
    margin: 10px;
    color: black;
    width: 200px;
    height: 100px;
}

.btn-blue {
    @extend .btn;
    background: blue;
}

Это будет скомпилировано в:

.btn,.btn-blue {
    margin: 10px;
    color: black;
    width: 200px;
    height: 100px;
}

.btn-blue {
    background: blue;
}

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

%btn {
    margin: 10px;
    color: black;
    width: 200px;
    height: 100px;
}

.btn-blue {
    @extend %btn;
    background: blue;
}

.btn-red {
    @extend %btn;
    background: red;
}

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

.btn-blue {
    margin: 10px;
    color: black;
    width: 200px;
    height: 100px;
    background: blue;
}

.btn-red {
    margin: 10px;
    color: black;
    width: 200px;
    height: 100px;
    background: red;
}