От автора: новый подход к адаптивности контент-зависимых компонентов — модификаторы. Планирование адаптивного поведения компонента может быть непростой задачей, особенно когда его содержание сильно влияет на компоновку компонента.
Например, давайте рассмотрим компонент таблицы. Вы можете решить использовать две различные схемы: одна — оптимизированная для небольших экранов (макет state-a), другая — для больших экранов (макет state-b). Затем вам нужно будет выбрать контрольную точку для изменения макета и установить ее в CSS с помощью медиа-запроса. Однако один и тот же компонент таблицы может иметь два или двадцать столбцов.
Если в таблице мало столбцов, вы можете изменить макет на небольшой контрольной точке:
В то же время, для таблицы с большим количеством столбцов или большим количеством содержимого вы можете изменить ее позже, чтобы на маленьких экранах она не выглядела слишком переполненной:
В идеале, вы должны найти контрольную точку, которая работает для обоих (и для всех других таблиц на сайте). Вы можете использовать класс .table для определения стиля макета state-a, и использовать медиа-запрос, чтобы переписать этот стиль для макета state-b:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<table class="table"> <!-- table content --> </table> <style> .table { /* state-a layout style */ @media (min-width: 600px) { /* state-b layout style */ } } </style> |
Это решение может быть не идеальным, поскольку выбранная вами контрольная точка является компромиссом: в результате вы можете получить несколько таблиц, которые выглядят слишком переполненными, а другие — слишком разреженными. Даже если вы найдете решение, которое, кажется, подходит для текущих таблиц, оно может легко сломаться с будущими.
Модификаторы класса
Возможной альтернативой будет определение модификаторов адаптивных классов (классов, которые имеют один и тот же стиль, но нацелены на разные контрольные точки), чтобы иметь возможность инициировать изменение макета в разных контрольных точках.
Если мы рассмотрим пример с двумя контрольными точками (малая и средняя), вы получите:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.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 на основе их содержимого:
1 2 3 4 5 |
<!-- 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:
1 2 3 4 5 6 7 |
.table { /* state-a layout style */ } .table--state-b { /* state-b layout style */ } |
Затем мы определили пользовательское свойство CSS —table-layout внутри класса .table и изменили его значение с помощью модификаторов класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.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. В результате будет применен нужный стиль макета!
1 2 |
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 и изменить его содержимое с помощью модификаторов класса:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.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
Источник: //codyhouse.co
Редакция: Команда webformyself.