Я люблю БЭМ как метод именования CSS-селекторов (полный стек ощутимо сложнее и для меня дает больше ограничений, чем выгоды) и я люблю Bootstrap. Увы, последний написан не по БЭМ (и в обозримом будущем на этот метод именования селекторов переходить не планирует), однако очень хочется использовать любимый фреймворк в работе с любимой методологией.

В этой заметке я опишу возможные варианты использования Bootstrap для тех, кто использует БЭМ как метод именования селекторов.

Речь пойдет о версии 3.x.x. Подразумевается, что:

На самом деле, статья ориентирована на студентов продвинутых курсов ЭпикСкиллс и HTML Academy, где я преподаю.

1. Миксование

Просто подключаем Bootstrap (компилируя нужные компоненты из less- или scss-файлов) и используем его классы вместе со своими, БЭМ-овскими. В разметке используем css-классы Bootstrap как обёртки (применимо для модульных сеток) или миксуем со своими классами (у тегов есть и наш класс, и bootstrap-овский).

Плюсы:

Минусы:

2. Bootstrap как примесь

В LESS есть интересная возможность импорта файла:

@import (reference) "FILE";

При таком импорте все селекторы внутри файла будут доступны как примеси, но не попадут в стилевой файл. Формально. Дело в том, что если внутри файла (или внутри тех файлов, что импортируются в нем) есть расширения (:extend() ), то они таки попадут в скомпилированный CSS.

Таким образом, что-то вроде @import (reference) "bootstrap/bootstrap.less"; или отдельный импорт компонент даст много совершенно ненужного кода из-за выводящихся в CSS экстендов.

Экспериментальным путем мне удалось выяснить, что можно подключить некоторые компоненты Bootstrap (не имеющие внутри расширений) и потом использовать селекторы как примеси, сохранив все плюсы сборки из препроцессорных файлов. Импорт «проблемных» компонентов закомментирован:

// Core variables and mixins
@import "bootstrap/variables.less";
@import (reference) "bootstrap/mixins.less";

// Reset and dependencies
// @import "bootstrap/normalize.less";
// @import (reference) "bootstrap/print.less";
// @import (reference) "bootstrap/glyphicons.less";

// Core CSS
@import (reference) "bootstrap/scaffolding.less";
// @import (reference) "bootstrap/type.less";
@import (reference) "bootstrap/code.less";
// @import (reference) "bootstrap/grid.less";
@import (reference) "bootstrap/tables.less";
// @import (reference) "bootstrap/forms.less";
@import (reference) "bootstrap/buttons.less";

// Components
@import (reference) "bootstrap/component-animations.less";
@import (reference) "bootstrap/dropdowns.less";
// @import (reference) "bootstrap/button-groups.less";
// @import (reference) "bootstrap/input-groups.less";
// @import (reference) "bootstrap/navs.less";
// @import (reference) "bootstrap/navbar.less";
@import (reference) "bootstrap/breadcrumbs.less";
@import (reference) "bootstrap/pagination.less";
// @import (reference) "bootstrap/pager.less";
@import (reference) "bootstrap/labels.less";
@import (reference) "bootstrap/badges.less";
@import (reference) "bootstrap/jumbotron.less";
// @import (reference) "bootstrap/thumbnails.less";
@import (reference) "bootstrap/alerts.less";
@import (reference) "bootstrap/progress-bars.less";
@import (reference) "bootstrap/media.less";
@import (reference) "bootstrap/list-group.less";
// @import (reference) "bootstrap/panels.less";
@import (reference) "bootstrap/responsive-embed.less";
@import (reference) "bootstrap/wells.less";
@import (reference) "bootstrap/close.less";

// Components w/ JavaScript
// @import (reference) "bootstrap/modals.less";
@import (reference) "bootstrap/tooltip.less";
@import (reference) "bootstrap/popovers.less";
// @import (reference) "bootstrap/carousel.less";

// Utility classes
@import (reference) "bootstrap/utilities.less";
@import (reference) "bootstrap/responsive-utilities.less";

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

Вариант с импортом CSS

Можно, однако, импортировать «как примесь» css-файл Bootstrap-а и использовать его селекторы как простые примеси. Важно взять неминимизированый файл, ибо, по крайней мере, в версии 3.3.5 минимизированный (bootstrap.min.css) вызывает ошибку компиляции LESS.

@import (less, reference) "bootstrap/bootstrap.css";

И потом в своих файлах что-то наподобие:

.my-selector {
  .col-sm-2();  // СЮРПРИЗ! В CSS не будет ширины и @media-условия
}

Тут, как видно из кода, нас ожидает «сюрприз». Связан он, возможно, с тем, что компилятор останавливается, найдя в импортируемом файле первую примесь с именем .col-sm-2 . Это можно было бы объяснить несовпадением контекста, в котором я вызываю примесь и контекстом, в котором указана ширина для этого селектора, но даже при совпадении:

@import (less, reference) "bootstrap/bootstrap.css";
@import "bootstrap/variables.less";

.my-selector {
  @media (min-width: @screen-sm) {
    .col-sm-2();
  }
}

На выходе всё равно имеем только общие свойства:

@media (min-width: 768px) {
  .my-selector {
    position: relative;
    min-height: 1px;
    padding-left: 15px;
    padding-right: 15px;
  }
}

В общем, пока проблему решить не удалось, такой вариант использования Bootstrap + БЭМ представляется попыткой крутить педали велосипеда при помощи костылей.

Итого

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

Не нужно быстро что-то менять (есть готовый дизайн, сделанный без оглядки на Bootstrap) и хочется красивого оптимального кода — используйте Bootstrap только как источник переменных, примесей, CSS-нормализатора и, возможно, типографики. Пишите свои стили (возможно, опираясь на компоненты Bootstrap). Для модульных сеток есть отличные примеси, дающие ширины колонок любой модульной сетки.

Дополнительно: как перестать использовать Bootstrap

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

  1. Изучите то, как сделан Bootstrap — как на уровне файловой организации, так и на уровне разметки/стилизации компонентов — там почти всё хорошо (плоха только зависимость модулей друг от друга и неполная настраиваемость модулей с уровня переменных).
  2. Возьмите на вооружение некоторые примеси Bootstrap (генератор модульных сеток, к примеру).
  3. Накапливайте свою библиотеку компонентов, заточенную под Ваш рабочий процесс (примеси, типовые компоненты).

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