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

У меня имеется такой БЭМ-блок:

.panel {
  background-color: white;
  border: 1px solid black;
}

Он довольно универсальный и используется на проекте во многих местах. Теперь появилась потребность на его основе создать блок .alert по такому типу:

HTML

<div class="panel alert alert_error">
  Invalid value
</div>

CSS

.alert_error {
  background-color: red;
}

.alert_success {
  background-color: green;
}

Проблема тут в том, что я вынужден для алерта изменять одно свойство, определенное для .panel: background-color. И мой вопрос в том, как это сделать правильно.

С одной стороны, я не нуждаюсь в модификаторах .panel_error и .panel_success, ведь эти категории относятся исключительно к .alert и в других местах проекта не используются. С другой стороны, в документации БЭМ сказано, что для случаев переопределения свойств какого-либо компонента мы должны создавать файл с тем же именем, что имеет исходный, где компонент изначально определен, и только там переопределять свойства. Очевидно, это рекомендуется для того, чтобы не забыть, что у нас имеется переопределение, и в index.css можно было явно и наглядно импортировать переопределяющий файл сразу после исходного. Короче говоря, это означает, что переопределять background-color внутри alert.css нежелательно, ибо со временем все забудут, что там что-то переопределено и изменение порядка импорта однажды может сломать стили.

Пока я остановился на таком решении, что в папке alert у меня лежит два файла: panel.css и alert.css, и таким образом я ясно вижу переопределение. Однако такой подход приводит к усложнению селекторной специфичности, приходится писать .panel.alert_success (ведь я не хочу, чтобы соответствующий background-color распространился на другие .panel), а также к неудобному разделению стилей одного по сути блока на два разных файла.

Каково самое "чистое" возможное решение в данном случае?


Ответы (2 шт):

Автор решения: Sergey Glazirin

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

Так как panelсодержит две строки, то нет ничего плохого в том, чтобы скопировать их в класс alert и не использовать panel. Так как alert используется с модификатором, то можно скопировать только свойство border

В результате получим:

  1. Алерты не зависят от панели
  2. Будет один блок навешен и не испортится семантика в шаблоне

.alert {
  border: 1px solid black;
}

.alert_error {
  background-color: red;
}

.alert_success {
  background-color: green;
}
<div class="alert alert_error">
  Invalid value
</div>
<div class="alert alert_success">
  Valid value
</div>

→ Ссылка
Автор решения: VladykoD

Почему бы не завести какой-то отдельный класс для состояний?

.status {background: inherit}    
.status_complete {background: green;}
.status_error {background: red;}
→ Ссылка