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

Две из наиболее важных функций Sass – это примеси и наследование. Несмотря на то, что их обычно группируют ввиду их способности генерировать дополнительные стили, каждая из них предлагает уникальный подход для решения привычных проблем с CSS.

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


Скромная примесь


Примеси – это основные «кирпичи» для построения Sass. Просто заверните группу свойств или селекторов в примеси, и код можно будет использовать повторно, включив примесь чуть позже.
Единоразовое написание общего кода позволяет вносить дальнейшие изменения в одном месте – ключевом участнике методологии DRY. Данный пример примеси кнопки содержит свойство border, которое потом используется различными классами кнопок:

SCSS
@mixin button {
    border-radius: 4px;
    border: 4px solid black;
}

.search-button {
    @include button;
    background-color: blue;
}

.cancel-button {
    @include button;
    background-color: red;
}


CSS
.search-button {
    border-radius: 4px;
    border: 4px solid black;
    background-color: blue;
}

.cancel-button {
    border-radius: 4px;
    border: 4px solid black;
    background-color: red;
}


Чтобы генерировать уникальный CSS для каждого класса, включите примесь в значения каждого аргумента:

SCSS
@include button('search', blue);
@include button('cancel', red);


CSS
.search-button {
    background-color: blue;
    border-radius: 4px;
    border: 4px solid black;
}
.cancel-button {
    background-color: red;
    border-radius: 4px;
    border: 4px solid black;
}


Даже в этом небольшом примере легко увидеть рост эффективности Sass.

Негативные аспекты и дублирование


Несмотря на то, что проще всего использовать примеси для повторяющихся блоков CSS, это не всегда является наиболее разумным выходом. Вывод CSS, который генерируется примесями, теперь содержит два класса с одинаковым свойством border.
Если постоянно использовать примеси таким образом, это приведет к тому, что CSS раздуется от большого количества дублированного кода. К счастью, мы можем использовать наследование, чтобы найти места, в которых примеси окажутся лишними.

«Сушим» код с помощью наследования


Функция наследования позволяет классам наследовать все свойства другого класса путем группировки селекторов. Вместо дублирования CSS каждый раз, как это делает примесь, селектор группируется с классом, который он наследует:

SCSS
.button {
    border-radius: 4px;
    border: 4px solid black;
}

.search-button {
    @extend .button;
    background: blue;
}


CSS
.button,
.search-button {
    border-radius: 4px;
    border: 4px solid black;
}

.search-button {
    background: blue;
}


Теперь у нашего вывода есть только одно значение свойств границы, которое поддерживают наши кнопки.

Счастливы вместе


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

SCSS
.button {
    border-radius: 4px;
    border: 4px solid black;
}

@mixin button($name, $background-color) {
    .#{$name}-button {
        background-color: $background-color;
        @extend .button;
    }
}

@include button('search', blue);
@include button('cancel', red);


Классы, которые наследуют общие свойства кнопки, сгруппированы с классом .button, что исключает дублирование свойств границы.

CSS
.buton, .search-button, .cancel-button {
    border-radius: 4px;
    border: 4px solid black; 
}

.search-button {
    background-color: blue; 
}

.cancel-button {
    background-color: red;
}


Такое сочетание примеси и наследования можно использовать для генерации большого количества кнопок, тем самым снижая количество дублируемого CSS.

Ищем золотую середину


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

Экспериментируйте с различными методиками и смотрите, как эти функции можно переплетать, создавая мощные примеси и чистые таблицы стилей. Наличие активной аудитории Sass означает, что всегда существуют новые идеи, которые можно исследовать, изучать и дополнять.

Комментарии (36)


  1. s_kozlov
    17.04.2015 14:45
    +2

    В тексте немного код сбился, не на месте. В разделе про наследование существующего класса блок с результирующим CSS улетел в предыдущий раздел, по-моему. Если это так, поправьте пожалуйста.


  1. Andchir
    17.04.2015 23:28
    +1

    Обычно CSS в данном случае выглядел бы так
    .buton {
        border-radius: 4px;
        border: 4px solid black; 
    }
    
    .search-button {
        background-color: blue; 
    }
    
    .cancel-button {
        background-color: red;
    }
    


    1. Andchir
      17.04.2015 23:44
      +2

      Ещё плюс:
      3. Сравните синтаксис и попробуйте его понять. В моем примере он читается очень быстро. В примере выше вызывает зависание на пару минут. Найти и что-то исправить в обычном CSS проще, чем в коде с mixin.


    1. Punk_UnDeaD
      18.04.2015 01:08

      Академический интерес, а сколько строк css кода в ваших проектах?


    1. AndersonDunai
      18.04.2015 03:44
      +1

      Частично вы правы. А вот насчёт провосходства минусов над плюсами вынужден не согласиться.

      Чего стоит лишь только вкладывание правил? Конечно, злоупотреблять ими не стоит (да и микс-ины дают очень большой CSS-ный выхлоп), но, как по мне, вкладывание давно пора сделать нативно поддерживаемым в CSS.

      Если бы LESS/SCSS парсился браузером без необходимости прекомпиляции в CSS — цены бы ему не было.


      1. Andchir
        18.04.2015 14:37
        +2

        >>как по мне, вкладывание давно пора сделать нативно поддерживаемым в CSS.

        Честно говоря это единственное, что мне нравится в инструментах подобных SASS. Остальное или очень редко используется, или можно сделать без создания нового языка.


        1. leMar
          18.04.2015 15:01
          +1

          Я из препроцессоров вынес только три вещи:
          1) нахожу возможность писать media внутри класса более удобным и читаемым, чем классы внутри media.
          2) Переменные. Тут без комментариев.
          3) Игры с цветами. Хорошо для генерации всяких цветовых схем. Задал базовый цвет, а в других местах, все поменялось в зависимости от него. Но это спецефично.

          Что же до миксинов. То пример из статьи ужасен на мой взгляд. Сам делаю как у вас. Миксин позволяю себе, когда надо вынести несколько свойств в одну строчку, а в html он смысловой нагрузки не несет. Напимер, button button-succeed, примелимо. button-rounded — нет. То есть вякие вертикальные выравнивания, обтекания, спрос флоатов, выставления позиционирования – тут миксин полезен.


    1. andrewiWD
      18.04.2015 09:06

      Пример здоровский. И он работает. Но когда у вас появятся как минимум 4 похожих кнопки, тогда SASS и LESS будут короче. Вспомните те же бутстраповские кнопки (дефаулт, примари, варн, дангер, линк, инлаин). Кстати, в бутстрапе все классы -варн, -дангер, -инфо и т.д. имеют свой цвет, что так же легче и быстрей сделать миксинами.

      По вашим минусам:
      1. Не увидел совершенно нового синтаксиса, особенно в SCSS (кто вам мешает писать чистый CSS на SCSS в конце концов?)
      2. «Набирая на клавиатуре» — да. «потратил меньше времени» — скорей всего нет. Написать код изящно и кратко занимает гораздо больше времени, чем на скорую руку намазать спагетти.


      1. hell0w0rd
        18.04.2015 12:44

        Эм, в бутстрапе как раз используется описанный выше вариант.

        <button class="btn btn-danger">Alert!</button>
        


        1. andrewiWD
          19.04.2015 17:06

          Эм, исходники бутстрапа написаны на SASS/LESS.

          Bootstrap ships with vanilla CSS, but its source code utilizes the two most popular CSS preprocessors, Less and Sass. Quickly get started with precompiled CSS or build on the source.


          1. MechanisM
            20.04.2015 04:55

            Bootstrap пишется cтрого на LESS, это потом из LESS он конвертится в Sass для аудитории пользователей Sass
            Код с Sass lаже в отдельной репе


      1. Andchir
        18.04.2015 15:47
        +1

        Про бутстрап хороший пример. Но есть одна особенность: это массовый продукт. Сколько вы используете видов кнопок оттуда на своем проекте? (если все 6, то попрошу пруф). В одном конкретном проекте обычно используется 2 — 3 цветовых стиля кнопок. Поэтому выхлоп с использованием CSS процессоров ощутим только на массовых продуктах. (ИМХО) Я к тому, что инструменты надо использовать с умом, а не просто потому что это модно (часто такое встречал).


        1. andrewiWD
          19.04.2015 17:20

          Бутстрап обычно использую для административных интерфейсов, поэтому все 6 зачастую задействованы (тогглы — серый, сохранение — синий, удалить — красный, добавить — зелёный, дебаг — оранжевый и т.д.). Но в целом, с вами согласен, т.к. львиная доля компонентов бутстрапа не используется.

          Однако нашел для себя отличное решение — gridle. В каждом проекте включаешь именно те фичи, которые будут использоваться, как следствие даёт минимальные размеры для генерируемых css файлов (цветов и разукрашек там нет, только лейаут).


    1. wdmaster
      18.04.2015 20:34

      Мне нравится SASS, я люблю SASS, шикарные возможности, очень круто. Но не всегда понимаю, как с его «выхлопом» работать дальше. Сделал я проект, допустим, CSS написал на SASS, отдал клиенту. Проект развивается, пригласили разработчиков, которые не знают SASS, но знают LESS — как быть в такой ситуации. Выход один — править скомпиленный CSS.

      В скорости разработки SASS — лучший помощник. Когда количество строк кода не превышает 2000. Потом ливрелодится компилл долго, Ctrl+S умножается на два с интервалом в 400мс. Может у меня машина слабая, но это немного раздражает.

      Даже свои проекты, которые я писал на SASS — поддерживаю и развиваю только на CSS, так как невозможно становится с этим работать, особенно, когда проект находится на удаленном сервере.

      На мой взгляд SASS подходит для быстрой разработки какого-нибудь LP, который ты потом отдашь клиенту и благополучно о нем забудешь, но преимущество у разработчика безусловное — в скорости разработки.


      1. Punk_UnDeaD
        19.04.2015 02:34
        +1

        Проект развивается, пригласили разработчиков, которые не знают SASS, но знают LESS — как быть в такой ситуации.

        Выход — выучить уже наконец SASS.

        А то может они CSS не знают, тогда выход — писать инлайн стили или теги ?


  1. Punk_UnDeaD
    18.04.2015 01:08

    del


  1. extempl
    18.04.2015 08:07
    +1

    Вообще в данном конкретном случае целесообразнее использовать плейсхолдеры, тогда не создаётся избыточный класс (если он, конечно, не используется, что довольно редко на практике SASS)

    Код с плейсхолдерами
    %button {
        border-radius: 4px;
        border: 4px solid black;
    }
    
    @mixin button($name, $background-color) {
        .#{$name}-button {
            background-color: $background-color;
            @extend %button;
        }
    }
    
    @include button('search', blue);
    @include button('cancel', red);
    

    .search-button, .cancel-button {
      border-radius: 4px;
      border: 4px solid black;
    }
    
    .search-button {
      background-color: blue;
    }
    
    .cancel-button {
      background-color: red;
    }
    
    


  1. hell0w0rd
    18.04.2015 12:49

    На мой взгляд подобные возможности препроцессорных языков для css (less тоже это умеет), скорее костыль, которого стоит избегать. Это примерно как important. Понятно, что gzip обожмет такие повторения, но все же лучше избегать .extend там, где без этого можно обойтись. На пример в примере с button. Просто используйте 2 класса.


  1. namespace
    18.04.2015 13:07

    Всю статью не читал, потому что как обычно, очередная каша про то, как правильно писать SASS, но вот насчет первого примера в «Скромных примесях» выскажусь. Я считаю, что это чистейшей воды антипаттерн и правильно было бы сделать все на чистом CSS и не вы**ываться:

    .button {
        border-radius: 4px;
        border: 4px solid black;
    }
    
    .search.button {
        background-color: blue;
    }
    
    .cancel.button {
        background-color: red;
    }
    


    Не знаю, как с SASS, но LESS позволяет просто сделать так (и я считаю, что это элегантно):

    .button {
        border-radius: 4px;
        border: 4px solid black;
    
        &.search {
            background-color: blue;
        }
    
        &.cancel {
            background-color: red;
        }
    }
    


    Почему нужно делать именно так? Это банально интуитивнее. Потом, в HTML коде вы будете писать все естественным языком, не городить забор. Взгляните на пример:

    <span class="search icon"></span>
    <span class="icon-search"></span>
    


    Cогласитесь, первый вариант будет лучше второго, потому что это естественный язык, естественная подача информации. По большому счету, никакого существенного отличия вроде и нет, но разметку писать стало проще понятней и мы не стали плодить сущности с этими вашими миксинами. Миксины — это хороший пример того, как народ неверно интерпритирует концепцию. Изначально они создавались, чтобы выносить какие-то квирки (хаки/костыли/whatever) в отдельные функциональные единицы кода.


    1. MechanisM
      20.04.2015 04:41

      stylus:

      .button
        border-radius 4px
        border 4px solid black
      
        .search&
            background-color blue
      
        .cancel&
            background-color red
      

      Раньше тоже пользовался и SASS и LESS но в последнее время Stylus применяю


      1. MechanisM
        20.04.2015 04:50

        Мне как питонисту очень удобен Stylus отсутсвием скобочек и привычные отступы))


        1. namespace
          20.04.2015 11:59

          Я тоже питонист, но искринне убежден, что определение семантики кода отступами — это самый худший антипаттерн, который когда либо был представлен в пайтоне. Но, опять-таки, все зависит от команды и инструментария. Ящитаю, что LESS лучше читается, чем стилус, хотя первый однозначно не без недостатков.


          1. MechanisM
            20.04.2015 12:07

            Ну я в Stylus нашел много хорошего, и выбрал его уже после того как несколько лет пользовался LESS/Sass.
            Насчет отступов — я и шаблоны пишу на slm/jade в последнее время))
            Python/Django,Flask или Golang, Erlang только для бэкенда с API, а фронт пишу отдельно, используя средства фронт-енд разработки и MVC-фреймворки(это я к тому, что могут возникнуть вопросы почему я пишу шаблоны на slm а не на jinja2 например)


            1. namespace
              20.04.2015 12:22

              Думаешь, стоит посмотреть в сторону stylus/slm? Я полгодика клепаю приложение на фласке (джанго вызывает у меня небольшое отвращение), от jinja2 люто-бешенно кончаю.


    1. MechanisM
      20.04.2015 04:47

      В вашем же примере LESS не получится того, что выше написано на СSS
      У вас получится .button.search и .button.cancel а не как выше в CSS .search.button .cancel.button


      1. namespace
        20.04.2015 11:56

        Но ведь .button.search это тоже самое, что и .search.button. Мой способ же интуитивнее и проще пишется, без горождения заборов с @extend и прочими миксинами.


        1. MechanisM
          20.04.2015 11:59

          Мой со стилусом приятнее на вид)) без всех этих {:;}


      1. namespace
        20.04.2015 12:01

        А, я кажется понял, о чем ты. Да, конечный код будет не 1:1 c указанным листингом на CSS, но суть, я так понимаю, сохраняется. Согласись, это в любом случае лучше того, что автор проталкивает в статье.


        1. MechanisM
          20.04.2015 13:10

          мой тоже будет не 1:1 — стилус сгенерит цвета в hex типа black -> #000


  1. ambientos
    18.04.2015 21:43
    +1

    По поводу всего этого безобразия у меня есть единственный комментарий: «сами создаём себе проблемы, а потом благополучно их решаем».


  1. vdv73rus
    19.04.2015 20:13

    Чрезмерное увлечение @extend ведёт к космическому росту количества селекторов и, возможно, проблеме 4096 селектора в IE.


  1. artemmalko
    20.04.2015 08:04

    Честно говоря, не понимаю проблемы размера css-файла при использовании примесей. Ведь gzip все это великолепно сожмет же? А большое количество @extend, как верно заметил vdv73rus, может привести к багам в итоге.


    1. MechanisM
      20.04.2015 08:25

      Верно, то что имеется куча примесей в less/stylus/sass это не значит что в результате css cкомпилится с кучей этих миксинов.
      Миксины имеет смысл создавать когда что-то очень часто повторяется.
      Как один из наиболее наглядных примеров плюсов использования миксинов в less/stylus/sass перед использованием чистого сss это конечно использование префиксов браузеров. Например можно сделать миксин типа:

      .blur(@blur) {
        -webkit-filter: blur(@blur);
        -moz-filter: blur(@blur);
        -o-filter: blur(@blur);
        -ms-filter: blur(@blur);
        filter: blur(@blur);
      }
      // и потом везде писать просто:
      .some-class {
        .blur(значение);
      }
      .another-class {
        .blur(значение);
      }
      .one-more-class {
        .blur(значение);
      }
      

      а не расписывать все в кучу строк для каждого браузера.

      В СSS это было бы:
      .some-class {
        -webkit-filter: blur(значение);
        -moz-filter: blur(значение);
        -o-filter: blur(значение);
        -ms-filter: blur(значение);
        filter: blur(значение);
      }
      .another-class {
        -webkit-filter: blur(значение);
        -moz-filter: blur(значение);
        -o-filter: blur(значение);
        -ms-filter: blur(значение);
        filter: blur(значение);
      }
      .one-more-class {
        -webkit-filter: blur(значение);
        -moz-filter: blur(значение);
        -o-filter: blur(значение);
        -ms-filter: blur(значение);
        filter: blur(значение);
      }
      


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


      1. vdv73rus
        20.04.2015 08:59

        В 2015 году не надо так. Читайте про autoprefixer.


        1. MechanisM
          20.04.2015 11:11

          Это было лишь примером))
          вообще у меня в gulpfile автопрефиксер для стилуса стоит: prefixer = require 'autoprefixer-stylus'


        1. namespace
          20.04.2015 13:56

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