frontend-разработчик. Фотографирую в инстаграме, готовлю и пишу тексты. Всё написанное не отражает мнения работодателя. 18+

1 заметка с тегом

bash

Модифицировать и положить на место

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

Чтобы этого избежать, стоит определить общие правила и их придерживаться.

В Яндексе продвигают методологию БЭМ, но ей пользуются не только там.

Я попробовал, разобрался и мне понравилось.

По БЭМ весь ваш код делится на три части: блок элемент и модификатор.

Приведу аналогию:

  • у вас есть полка. Полку можно поставить в любое место и она всегда останется полкой.
  • у вас есть книга. Книга останется книгой и на полке и у вас в руках. Это тоже блок.
  • если вы поставите книгу на полку, то книга станет элементом полки с книгами.
  • а если вы поместите книгу в суперобложку, то она будет выделяться, и станет блоком с модификатором.

Больше всего вопросов вызывают следующие вещи:

  • у вас есть несколько блоков, как их расположить относительно друг друга, если описывать положение в стилях блока нельзя?
  • как сделать файловую структуру?
  • модификатор не изменяет значение родительского блока, если создать правильную файловую структуру!!!

Разберёмся по очереди.

Как поместить один блок в другой

Блок действительно не должен влиять на своё положение в пространстве.

Согласитесь, если бы ваша полка говорила: «я стою у окна» — то вы не смогли бы поставить её в другое место, и блок потерял бы главное свойство блока в методологии БЭМ: свою универсальность.

Поэтому блок управляет только внутренними элементами и своими размерами. А если вы привезли в квартиру полку, которая не помещается: надо было думать при покупке.

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

Посмотрим на код на примере полки на книге.


<div class="shelf">
     <div class="shelf__book book"></div>
</div>

Теперь книга это и блок сам по себе, и элемент родительского блока. Если посмотрите внимательно, то .book — это класс обозначающий стили блока «книга», а .shelf__book — это описание, где книга лежит на полке, как элемент «полки». Такое использование двух классов вместе называется миксами. А правила такого расположения написаны в официальной документации.

Как сделать файловую структуру

Если вы делаете проект по БЭМ и хотите получить один стиль, вы всегда можете взять кусок кода из одной страницы или с одного своего сайта и вставить в другой. Ничего не сломается.

Чтобы вы не искали код в длинном CSS-файле, frontend-разработчики, которые выбрали БЭМ, помещают каждое описание классов: блоков, элементов, модификаторов — в отдельные файлы и папки.

Выглядеть ваш сайт будет следующим образом:



src
 blocks
  shelf
   __book
    shelf__book.css
   _library
    shelf_library.css
   _kitchen
    shelf_kitchen.css
  shelf.css
  book
   _red
    book_red.css
   book.css
 pages
  index
   index.html
   index.css
   index.js

Внутри всё это дело подключается через @import url();, поэтому файл index.css выглядел бы так:


@import url(../../blocks/shelf.css);
@import url(../../blocks/book.css);

/* тут можно указать какие-то глобальные стили, но по правилам БЭМ. Например, задать шрифт странице */

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

Поэтому модификаторы элементов подключаются в корневых *.css-файлах элементов.

Создать подобную структуру, конечно, занимает время, но задачу можно легко решить при помощи терминала. Если у вас macOS или Linux, устанавливать ничего не надо: Git Bash уже установлен в системе, а если вы работаете под Windows, стоит зайти по ссылке и скачать файл.

После этого вы сможете через простое перечисление создать нужную структуру.


$ mkdir src #создали папки
$ mkdir src/blocks src/pages
$ touch src/pages/index.html src/pages/index.css src/pages/index.js #создали файлы
$ cd src/blocks #зашли в папку
$ mkdir shelf book
$ mkdir shelf/_library shelf/_kitchen shelf/__book book/_red
$ touch shelf/_library/shelf_library.css shelf/_kitchen/shelf_kitchen.css shelf/__book/shelf__book.css shelf/shelf.css book/_red/bookd_red.css book/book.css

Повторять команду можно переходя по стрелочке вверх. А после того, как вся структура будет собрана, останется только добавить подключения дочерних файлов и всё заработает.

Модификатор не изменяет значения родительского блока

Это происходит потому, что у модификатора не хватает «веса», а подключается он, как и положено, в начале страницы, поэтому родительский класс его переписывает. Подробнее про специфичность есть в статье.

Исправить эту вещь можно двумя способами:

Добавить «вес»

Модификатор элемента никогда не используется без родительского элемента. Поэтому, если вы не можете поправить файл родительского элемента, или это супер-исключение из правил и больше оно нигде не применяется, можно сделать так.

Если у нас все книги синие, и только одна в красной супер-обложке, то запишем код:


/* файл book_red.css*/
.book.book_red {
    color: red;
}


/* файл book.css*/
@import url(_red/book_red.css);
.book {
    color: blue;
}

То же самое будет справедливо, если вы хотите «усилить» элемент блока. Ведь элемент не может использоваться в отрыве от блока.


/* файл shelf__book.css*/
.shelf .shelf__book {
    margin-right: 10px;
}


/* файл shelf.css*/
@import url(__book/shelf__book.css);
.shelf {
    margin: 0;
}

Тут стоит быть внимательным и «усиливать» элементы только родительским блоком. С чужим блоком такой фокус не пройдет.

На самом деле, этот способ не совсем корректный и применяется только в виде исключения из правил. Правильно делать так:

Не указывайте свойства, которые могут измениться

Вернёмся к книгам. У нас есть книги одинакового размера и формы, но разного цвета. Все синие и одна красная. Правильная запись в таком случае будет выглядеть так:


/* файл book_red.css*/
.book_red {
    color: red;
}


/* файл book_blue.css*/
.book_blue {
    color: blue;
}


/* файл book.css*/
@import url(_red/book_red.css);
@import url(_blue/book_blue.css);
.book {
    width: 200px;
    height: 400px;
}


/* файл index.html*/
<div class="shelf">
    <div class="book book_blue"></div>
    <div class="book book_red"></div>
    <div class="book book_blue"></div>
</div>

Немного более загруженный *.html-файл, но всё работает так, как нужно.

1 мес   bash   css   html   БЭМ   код   учебник