Адаптивный веб-дизайн и таблицы не обязательно являются лучшими друзьями. Многие люди исследовали ситуацию, и было разработано много подходов (некоторые из них были даже собраны в недавней статье здесь на SitePoint ). Однако мы все еще далеки от идеального решения, и поиск продолжается.
Хотя в общем случае все еще сложно, к некоторым конкретным случаям можно относиться с гораздо большим вниманием. Я говорю здесь о таблице сравнения функций. Мы сталкиваемся с этим во многих местах — при выборе автомобиля и попытке решить, какие дополнительные опции выбрать; на веб-хостингах при сравнении планов и функций; на любом членском портале, который позволяет вам решить, какие функции вы должны получить в обмен на ваши деньги.
Поскольку таблица такого типа имеет относительно стабильную и последовательную структуру, можно добиться лучшего поведения при отображении на небольших экранах.
Анатомия сравнительной таблицы характеристик
Классическая таблица сравнения объединяет как минимум три продукта (отображаются в столбцах), а функции отображаются в строках ниже. В традиционной структуре первая ячейка каждой строки имеет название функции, а ячейки под каждым продуктом имеют галочку или какой-либо другой символ, показывающий, принадлежит ли эта функция продукту или нет. Мы можем найти отличные примеры этой классической структуры: здесь , здесь и здесь
На основании этих примеров мы можем обобщить структуру таблицы сравнения с помощью следующего кода:
<table> <thead> <tr> <th> </th> <th>Product 1</th> <th>Product 2</th> <th>Product 3</th> </tr> </thead> <tbody> <tr> <td>Feature 1</td> <td>✔</td> <td>✔</td> <td>✔</td> </tr> <tr> <td>Feature 2</td> <td>—</td> <td>✔</td> <td>✔</td> </tr> <tr> <td>Feature 3</td> <td>—</td> <td>—</td> <td>✔</td> </tr> <tr> <td>Feature 4</td> <td>—</td> <td>—</td> <td>✔</td> </tr> </tbody> </table>
Легко определить элементы, упомянутые ранее: названия продуктов, названия функций и метки, которые показывают, присутствует ли функция или нет. Обратите внимание, что ✔
Код представляет символ галочки ().
Теперь мы подошли к корню проблемы. Чтобы таблица сохраняла оптимальную эффективность при низкой ширине экрана, необходимо выполнить несколько условий:
- Пользователь должен иметь возможность легко дифференцировать продукты;
- Функции должны быть легко идентифицируемыми; и
- Должно быть ясно, присутствует ли функция для продукта или нет.
Лучший способ достичь этого результата — переместить ячейку, содержащую имя объекта, поверх трех других ячеек, которые отмечают наличие или отсутствие объекта.
Первое решение: Flexbox
Как мы можем добиться этого? Один ответ — flexbox. Если вы не знаете, что такое flexbox, или вам нужен освежитель, вы можете проверить недавнюю статью Ника Саллума на эту тему . Остальные из нас могут погрузиться в решение.
Сначала мы должны убедиться, что наши изменения происходят только на маленьких экранах. Чтобы это произошло, мы нацеливаем наш код, используя медиа-запрос, используя классическую ширину 768px
в качестве точки останова:
@media screen and (max-width: 768px) { tr { display: flex; flex-flow: row wrap; justify-content: space-around; } td, th { display: block; width: 33%; } th:first-child, td:first-child { text-align: center; background: #efefef; width: 100%; } th:first-child { display: none; } }
В этом наборе правил есть несколько важных вещей:
- Мы изменяем отображаемое значение для строки таблицы, чтобы
flex
и мы говорим ее дочерним элементам течь в строке, равномерно распределенной. - Затем мы указываем ячейкам принять
display:block
чтобы нормализовать их как обычные контейнеры (оставив значение по умолчанию, вы получите помехи от правил таблицы, особенно в отношении размера). - Следующий шаг нацеливается на первую ячейку в каждой строке, делая ее полной ширины и изменяя цвет фона, для дополнительного контраста. Правила потока позволяют ему оставаться на вершине трех других ячеек — именно то, что нам нужно.
- Мы заканчиваем изменение, скрывая первое, чтобы над названиями продуктов ничего не отображалось.
Очевидно, что решение действительно только до тех пор, пока оно имеет достаточную поддержку. Согласно caniuse.com , поддержка flexbox составляет более 80% для самых современных вариантов и более 93%, если мы включаем версии браузера, которые требуют префиксов, или используют предыдущие версии правил. Поддержка IE начинается с IE10 (только синтаксис 2012 года), в то время как IE11 имеет полную поддержку. Поскольку мы в основном заинтересованы в поддержке на небольших экранах, мы можем игнорировать отсутствие поддержки предыдущих версий IE. На мобильном фронте поддержка начинается с Android 4.4 и iOS 7.1. Предыдущие версии требуют префиксов поставщиков и не поддерживают функцию переноса.
Вы также должны предоставить запасные варианты, такие как прокрутка div, используемая в Bootstrap . Таким образом, посетители, которые выходят за пределы опорного кронштейна будет еще есть другая альтернатива для их отображения.
Второе решение: дополнительная разметка + роли ARIA
Если большая часть браузеров, которые вы собираетесь поддерживать, не поддерживает flexbox, есть альтернатива. Фактически это решение, которое я использовал в реальном проекте в 2013 году. Нам понадобится дополнительная разметка: нам нужно будет добавить одну дополнительную строку, дублирующую имя функции. Хотя это может показаться утомительным, чтобы делать вручную, это может быть автоматизировано, если информация считывается из источника данных. В конце код из нашего исходного примера должен выглядеть так:
<table> <thead> <tr> <th> </th> <th>Product 1</th> <th>Product 2</th> <th>Product 3</th> </tr> </thead> <tbody> <tr class="visible-xs" aria-hidden="true"> <td> </td> <td colspan="3">Feature 1</td> </tr> <tr> <td>Feature 1</td> <td>✔</td> <td>✔</td> <td>✔</td> </tr> <tr class="visible-xs" aria-hidden="true"> <td> </td> <td colspan="3">Feature 2</td> </tr> <tr> <td>Feature 2</td> <td>—</td> <td>✔</td> <td>✔</td> </tr> <tr class="visible-xs" aria-hidden="true"> <td> </td> <td colspan="3">Feature 3</td> </tr> <tr> <td>Feature 3</td> <td>—</td> <td>—</td> <td>✔</td> </tr> <tr class="visible-xs" aria-hidden="true"> <td> </td> <td colspan="3">Feature 4</td> </tr> <tr> <td>Feature 4</td> <td>—</td> <td>—</td> <td>✔</td> </tr> </tbody> </table>
CSS также довольно прост:
.visible-xs { display: none; } @media screen and (max-width: 768px) { .visible-xs { display: table-row; } td:first-child, th:first-child { display: none; } }
Мы можем сделать еще один шаг ради доступности и скрыть дополнительную разметку от программ чтения с экрана с помощью aria-hidden="true"
. Таким образом, те приложения для чтения с экрана, которые соответствуют спецификации aria-hidden , не будут читать дублированный контент дважды.
Вот демонстрация этого второго решения .
Вывод
Мы нашли здесь два способа сделать таблицу сравнения действительно отзывчивой. У обоих есть свои плюсы и минусы. В конце концов, выбранный выбор должен зависеть от специфики вашей аудитории. Для большинства случаев первого варианта (с запасным вариантом) должно быть достаточно. Если вам действительно нужно обслуживать старые версии Android и iOS , вы можете развернуть второй вариант. В любом случае, теперь ваши таблицы сравнения функций будут выглядеть намного лучше, независимо от размера экрана.