Подтвердить что ты не робот

Подход BEM для элемента, который может принадлежать и выглядит другим в зависимости от блока?

Скажем, у меня есть стилизованный флажок (подумайте о материальном дизайне, где немного идет, чтобы достичь желаемого стиля флажка). Какой блок отвечает за изменение дочернего блока, зависящего от родителя?

Пример компонента - флажок

Итак, у меня есть следующее:

<div class="Checkbox">
    <label class="Checkbox__label">
        <input class="Checkbox__input" type="checkbox" checked=true />
        <span class="Checkbox__icon glyphicon glyphicon-ok"></span>
        <span class="Checkbox__text">{label}</span>
    </label>
</div>

Я создаю каждый элемент в блоке для базы. В контексте приложения блок флажка может жить во многих других блоках (со своими собственными структурами BEM).

Пример других блоков

Флажок с изображением слегка отличается, если говорить в "Компактной панели":

<div class="Panel Panel--compact">
    <p>Disclaimer.. [text]</p>
    <Checkbox label="I Agree" /> 
</div> 

Вариант один - родительский "знает" о ребенке

Итак, если Compact Panel будет "осведомлен" о различных дочерних блоках и будет стилизовать их, так:

// Checkbox.scss 
.Checkbox {
    margin: 15px;
    // .. other
}


// Panel.scss
.Panel {
    &.Panel--compact {
        margin: 0;
        padding: 2px;
    }
    &.Panel--compact .Checkbox {
        margin: 0;
        padding: 1px;
    }
}

Вариант второй - ребенок "знает" о родителях

Или панель имеет нулевую осведомленность, а флажок проверяется для родительской области.

// Checkbox.scss 
.Checkbox {
    margin: 15px;
    padding: 15px;
    // .. other
}
.Panel.Panel--compact .Checkbox {
    margin: 0;
    padding: 1px;
}


// Panel.scss
.Panel {
    &.Panel--compact {
        margin: 0;
        padding: 2px;
    }
}

Вариант три -?

Возможно, есть и другие варианты.

4b9b3361

Ответ 1

Обычно с BEM, если они выглядят иначе, они разные.

Обычно.

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

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


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


Селектор потомков

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

<Суб > widget.lessсуб >
.widget {
  &__container {
    ...
  }
  ...
}
<Суб > checkbox.lessсуб >
.checkbox {
  &__label {
    ...
  }
  ...

  // using inversion to override checkbox styles in a widget
  // this will render to `.widget .checkbox` instead of
  // `.checkbox .widget` due to the `&` placement
  .widget & {
  }
}

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

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

Рассмотрим этот порядок включения:

<Суб > site.lessсуб >
@import 'widget';
@import 'checkbox';

Если стили были частью виджета, они могут быть переопределены селектором с равной специфичностью в checkbox.less.

Модификаторы

Я рекомендую использовать модификаторы для состояния. Обычно я не считаю положение или контекст "состоянием", поэтому модификаторы могут быть неприемлемыми. Кроме того, несколько модификаторов на одном и том же элементе могут быть трудноразрешимыми и поэтому сложны в стиле.

Предполагая, что вы не используете модификатор в блоке checkbox, тогда может быть проще добавить модификатор для случая, когда он использовался в панели.

.checkbox {
  &__label {
    ...defaults...
  }
  ...defaults...

  &--alt {
    &__label {
      ...overrides...
    }
    ...overrides...
  }
}

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

Разный селектор

Я повторю свой первый пункт: Если они выглядят по-другому, они разные.

Это не значит, что вам нужно начинать с нуля на флажке. BEM позволяет создавать объектно-ориентированные стили. Придумайте новое имя и установите * флажок:

<Суб > checkbox.lessсуб >
.checkbox {
  &__label {
    ...
  }
  ...
}
<Суб > Флажок-2.Lessсуб >
@import (reference) 'checkbox';
.checkbox-2 {
  .checkbox;

  &__label {
    ...overrides...
  }
  ...overrides...
}

* в LESS Я использую mixin для этого, поскольку он обычно лучше подходит для расширения и переопределения стилей, чем использование функции :extend для языка. Не стесняйтесь использовать функцию :extend, просто помните, что порядок выбора имеет значение.

Refactor the Need Away

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

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

  • поля
  • набивка
  • Позиция
  • верхний, правый, нижний, левый
  • ширина
  • Высота
  • прогибается

Рефакторинг имеет другие проблемы, однако я часто заканчиваю использование контейнеров divs для нормализации области вставки для блоков, которые содержат другие блоки; YMMV.


tl; dr: Что я должен выбрать?

Можете ли вы (разумно) обновить разметку?

ДА: Если вы можете легко обновить разметку для использования разных классов, я бы рекомендовал расширить ваш блок checkbox как новый блок. Именование вещей сложно, поэтому обязательно укажите, какой из них где-то.

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

Ответ 2

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

Я думаю, что лучшим подходом было бы добавить модификаторы к блокам .Pannel и .Checkbox, например: .Panel--compact и .Checkbox--context-compact. Таким образом, вы не будете создавать зависимость между ними, которая является принципом BEM.

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

Ответ 3

Недавно я начал проект реагирования, и я хотел бы поделиться своим опытом по компоновке реагирующих компонентов.

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

.panel {
  .checkbox {

  }
}

Я использую css-modules. Это супер удивительно. Этот инструмент может создавать уникальные классы, поэтому вам не нужно беспокоиться о дублировании имени в других компонентах. Вы можете узнать больше со своей страницы git, и есть много статей в Интернете.

Если вы используете sass и вам нужно использовать переменные, вы можете определить отдельный sass файл в другой папке (пусть ../assets/variables.scss), в вашем файле scss-компонента вы можете импортировать его и использовать все переменные. То же самое относится к mixins и функциям.

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

Хорошее чтение