@larfeus

БЭМ. Как реализовать вложенность однотипных блоков друг в друга без перекрытия стилей?

Есть компонент:

<table class="table">
    <tbody class="table__body">
        <tr class="table__row">
            <td class="table__cell">
                ...
            </td>
        </tr>
    </tbody>
</table>


Таблица может иметь несколько вариантов темизации:

.table {
    &__body { }
    &__row { }
    &__cell { }
    
    &_dark &__cell {
        background: black;
        color: white;
    }
}


Допустим в рамках реализации приложения появляется вложенность одной таблицы в другую. Такое может запросто произойти при наличии модального окна (с кнопкой-активатором) в одной из ячеек "таблицы-родителя".

<td class="table__cell">
    <modal title="Редактировать">
        <table class="table">
            <tbody class="table__body">
                <tr class="table__row">
                    <td class="table__cell">
                        ...
                    </td>
                </tr>
            </tbody>
        </table>
    </modal>
</td>


Нам надо, чтобы у таблицы на первом уровне была темная тема, а в модальных окнах стандартная. Но из-за приоритизации селекторов внутри второй таблицы все ячейки будут так же с темой `dark`.

Окей.

Вариант 1. Использовать более специфические селекторы стилей.

.table {
    ...

    &_dark > &__body > &__row > &__cell {
        background: black;
        color: white;
    }
}


А если в блоке вложенность 10 и более элементов? А если поменяется верстка? Портянка в стилях получается так себе. Решение заведомо плохое и костыльное.

Вариант 2. Использовать явную "дефолтную" тему.

<table class="table table_dark">
    ...
    <td class="table__cell">
        ...
        <table class="table table_default">
            ...
        </table>
    </td>
</table>


.table {
    &_default {
        &__body { }
        &__row { }
        &__cell { }
    }

    &_dark {
        &__body { }
        &__row { }
        &__cell {
            background: black;
            color: white;
        }
    }
}


А если темизация состоит из нескольких параметров (цвет, размер, наличие бордеров, шрифт и тп)? Стили получаются более структурированы, чем в 1 варианте. Но:

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

&_default &__body,
&_dark &__body {
    ...
}

&_default &__cell,
&_small &__cell {
    ...
}


Вариант 3. Не допускать вложенности однотипных элементов.

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

Если говорить о конкретных решениях, например на vuejs - то это vue-portal/vue-teleport. Но на самом деле проблема может возникнуть не только с модальными окнами, которые приведены в примере как наиболее яркий пример. Для card-inside-card использование портала не оправдано.

___________

Как проблему решаете Вы?
  • Вопрос задан
  • 183 просмотра
Пригласить эксперта
Ответы на вопрос 1
@BigSmoke
Наверное это нужно делать как-то так:
Стили, которые не изменяются записываем в блок или в элемент
Стили, которые изменяются записываем в модификаторы
Все блоки и элементы всегда используем с модификаторами

Получится что-то вроде этого https://jsfiddle.net/termitkin/as0vLjo1/
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы