Главная » Статьи » Использование адаптивных модификаторов для управления изменениями компоновки в компонентах

Использование адаптивных модификаторов для управления изменениями компоновки в компонентах

Использование адаптивных модификаторов для управления изменениями компоновки в компонентах

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

Например, давайте рассмотрим компонент таблицы. Вы можете решить использовать две различные схемы: одна — оптимизированная для небольших экранов (макет state-a), другая — для больших экранов (макет state-b). Затем вам нужно будет выбрать контрольную точку для изменения макета и установить ее в CSS с помощью медиа-запроса. Однако один и тот же компонент таблицы может иметь два или двадцать столбцов.

Если в таблице мало столбцов, вы можете изменить макет на небольшой контрольной точке:

Использование адаптивных модификаторов для управления изменениями компоновки в компонентах

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

Использование адаптивных модификаторов для управления изменениями компоновки в компонентах

В идеале, вы должны найти контрольную точку, которая работает для обоих (и для всех других таблиц на сайте). Вы можете использовать класс .table для определения стиля макета state-a, и использовать медиа-запрос, чтобы переписать этот стиль для макета state-b:

<table class="table"> <!-- table content -->
</table> <style> .table { /* state-a layout style */ @media (min-width: 600px) { /* state-b layout style */ } }
</style>

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

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

Возможной альтернативой будет определение модификаторов адаптивных классов (классов, которые имеют один и тот же стиль, но нацелены на разные контрольные точки), чтобы иметь возможность инициировать изменение макета в разных контрольных точках.

Если мы рассмотрим пример с двумя контрольными точками (малая и средняя), вы получите:

.table { /* state-a layout style */
} /* small breakpoint */
@media (min-width: 600px) { .table--state-b\@sm { /* state-b layout style */ }
} /* medium breakpoint */
@media (min-width: 1000px) { .table--state-b\@md { /* state-b layout style */ }
}

Затем вы можете применить эти модификаторы к различным элементам table на основе их содержимого:

<!-- switch layout at a small breakpoint -->
<table class="table table--state-b@sm"></table> <!-- switch layout at a medium breakpoint -->
<table class="table table--state-b@md"></table>

Код, определенный в классе .table—state-b@sm, такой же, как и в .table—state-b@md. Помните, что эти два класса используются для создания одинакового макета; он применяется только в разных контрольных точках.

Этот подход имеет два основных недостатка. Первый — это возможность поддержки кода: если вам нужно внести изменения в макет state-b, вам нужно обновить два разных класса (.table—state-b@sm и .table—state-b@md). Это то, что вы можете решить, используя препроцессор CSS (например, миксины SASS).

Вторая проблема заключается в том, что CSS-код для state-b повторяется несколько раз в окончательном CSS-коде (дважды, если у вас есть два модификатора, но может быть и больше, если вам нужны дополнительные варианты!).

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

Решение

Работая над категорией «Таблица» библиотеки компонентов в CodyHouse, мы использовали другой подход; мы определили класс для макета state-b:

.table { /* state-a layout style */
} .table--state-b { /* state-b layout style */
}

Затем мы определили пользовательское свойство CSS —table-layout внутри класса .table и изменили его значение с помощью модификаторов класса:

.table { --table-layout: state-a;
} @media (min-width: 600px) { .table--state-b\@sm { --table-layout: state-b; }
} @media (min-width: 1000px) { .table--state-b\@md { --table-layout: state-b; }
}

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

Используя JavaScript, мы можем проверить, добавлять или удалять класс .table—state-b, основываясь на значении этого пользовательского свойства CSS. В результате будет применен нужный стиль макета!

var layout = getComputedStyle(table).getPropertyValue('--table-layout');
table.classList.toggle('table--state-b', layout == 'state-b');

Этот метод позволяет нам использовать один класс (.table—state-b) для стиля макета, независимо от медиа-запроса. Добавление нового варианта требует только установки значения отдельного пользовательского свойства CSS. Нет повторения кода!

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

Недостатки?

Этот подход требует JavaScript, но это не должно быть проблемой: если JS выключен, мы обслуживаем версию таблицы state-a, которая полностью доступна.

Как насчет поддержки пользовательских свойств CSS? Использование переменных CSS, вероятно, самый чистый и понятный способ. Но если вам нужно поддерживать более старые браузеры (например, IE 11 и ниже), вы можете использовать псевдо-элемент ::before и изменить его содержимое с помощью модификаторов класса:

.table::before { display: none; content: 'state-a';
} @media (min-width: 600px) { .table--state-b\@sm::before { content: 'state-b'; }
} @media (min-width: 1000px) { .table--state-b\@md::before { content: 'state-b'; }
}

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

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

Автор: Claudia Romano

Источник: https://codyhouse.co

Редакция: Команда webformyself.