Стиль таблицы с двумя заголовками свернут для мобильного - PullRequest
2 голосов
/ 21 марта 2020

Взять пример таблицы с двумя заголовками из учебников w3 c wcag

table {
  border-collapse: collapse;
  border-spacing: 0
}

table th {
  text-align: left;
  background-color: #ccc
}

table th,
table td {
  padding: .5em;
  border: 1px solid #999
}
<table>
  <tr>
    <td></td>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
  </tr>
  <tr>
    <th>09:00 - 11:00</th>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>11:00 - 13:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>13:00 - 15:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>15:00 - 17:00</th>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
  </tr>
</table>

Можно ли это стилизовать без изменения разметки (она должна оставаться доступной), чтобы в отзывчивом мобильном представлении она сворачивалась в вертикальную таблицу примерно так:

Понедельник

09: 00–11:00 Закрыто

11: 00–13:00 Открыто

13: 00–15 : 00 открыто

15: 00 - 17:00 закрыто

вторник

09: 00 - 11:00 открыто

11:00 - 13:00 Открыто

13: 00 - 15:00 Открыто

15: 00 - 17:00 Закрыто

et c

Ответы [ 2 ]

2 голосов
/ 21 марта 2020

Не законченный ответ, так как я буду делать скрипки для каждого сценария, просто хотел бы обдумать процесс для вас, чтобы играть с - ОБНОВЛЕНИЕ: 3/4 скрипты сделано

I играл с большим количеством вариантов здесь, веселый вызов!

Краткий ответ

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

Я был бы настолько смелым, чтобы сказать, что невозможно сделать то, что вы просите, поскольку это будет связано с использованием каких-либо свойств отображения, которые нарушат дерево доступности (т. Е. Если бы мы использовали display: block, который немедленно нарушает дерево доступности).

Я даже подумывал об использовании position: absolute (ужасная идея, но хотел посмотреть, можно ли это сделать), но это также сразу нарушает дерево доступности.

Из-за В структуре данных единственный способ, которым я мог бы подумать, чтобы сделать это только с CSS, - это задействовать сотни свойств / селекторов :before, :after и content: CSS, которые были бы просто беспорядком. Поэтому я не изучал этот вариант, но это могло бы быть возможно для кого-то, решившего достаточно сделать эту работу.

Почему это было бы невозможно?

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

Какие есть варианты?

У меня есть несколько разных способов достижения конечного результата. Я попытаюсь взвесить все «за» и «против» для каждого, но каждый из них нарушает хотя бы одно из ваших требований.

Вариант 1. Создайте вторую таблицу для мобильного просмотра и отключите их с помощью медиа-запросов.

Создав вторую таблицу, вы можете по-разному представить информацию для мобильных и планшетных ПК и настольных компьютеров.

Я очень удивлен тем, сколько положительных результатов я нашел для этого метода.

  • Он позволяет вам сохранить исходную разметку (хотя вы должны добавить разметку для второй таблицы)
  • Переключение таблиц - это буквально один селектор CSS (display: none или display: table) в медиа-запросе.
  • Доступность будет поддерживаться (если вы правильно построите вторую таблицу)
  • Производительность - на самом деле я думал, что добавление второй таблицы будет плохим для времени загрузки, но после некоторого времени я понял, что это, скорее всего, не будет иметь большого значения, так как уменьшенное требование CSS будет противодействовать увеличению HTML, плюс таблицы хорошо сжимаются с помощью GZIP et c.
  • Не требует JavaScript (но для этого потребуется создать таблицу дважды либо программно, либо вручную в бэкэнде)

Пример варианта 1

(просмотр в полноэкранном режиме для рабочего стола / исходный вид)

Мнение, которое я имел при создании этого примера - Я являюсь на самом деле не уверены, является ли следующая таблица семантически правильной. Немного необычно добавление <th> в любом месте, кроме верхних и нижних колонтитулов / первых столбцов таблицы. Он проходит проверку и выглядит нормально для программы чтения с экрана, но все же вы можете проверить это самостоятельно.

table {
  border-collapse: collapse;
  border-spacing: 0
}

table th {
  text-align: left;
  background-color: #ccc
}

table th,
table td {
  padding: .5em;
  border: 1px solid #999
}


/*start with mobile view hidden*/
table:nth-child(2){
  display:none;
}

@media only screen and (max-width: 720px) {
/*toggle second table in for mobile view*/
    table:nth-child(1){
  display:none;
}
table:nth-child(2){
  display:table;
}
}
<table>
  <tr>
    <td></td>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
  </tr>
  <tr>
    <th>09:00 - 11:00</th>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>11:00 - 13:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>13:00 - 15:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>15:00 - 17:00</th>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
  </tr>
</table>

<table>
<tr>
  <th colspan="2">Monday</th>
</tr>
<tr>
  <td>09:00 - 11:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>11:00 - 13:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>13:00 - 15:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>15:00 - 17:00</td>
  <td>Closed</td>
</tr>
<tr>
  <th colspan="2">Tuesday</th>
</tr>
<tr>
  <td>09:00 - 11:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>11:00 - 13:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>13:00 - 15:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>15:00 - 17:00</td>
  <td>Closed</td>
</tr>
<tr>
  <th colspan="2">Wednesday</th>
</tr>
<tr>
  <td>09:00 - 11:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>11:00 - 13:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>13:00 - 15:00</td>
  <td>Open</td>
</tr>
<tr>
  <td>15:00 - 17:00</td>
  <td>Closed</td>
</tr>
<tr>
  <th colspan="2">Thursday</th>
</tr>
<tr>
  <td>09:00 - 11:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>11:00 - 13:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>13:00 - 15:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>15:00 - 17:00</td>
  <td>Open</td>
</tr>
<tr>
  <th colspan="2">Friday</th>
</tr>
<tr>
  <td>09:00 - 11:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>11:00 - 13:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>13:00 - 15:00</td>
  <td>Closed</td>
</tr>
<tr>
  <td>15:00 - 17:00</td>
  <td>Open</td>
</tr>
</table>

Вариант 2. Просто сделайте таблицу прокручиваемой на мобильном телефоне.

Еще один вариант, где на бумаге это выглядит как хороший вариант, но я просто не надеваю это не нравится Наличие прокручиваемой таблицы - одно из худших мобильных приложений, которое я могу себе представить (исключение составляют массивные наборы данных).

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

Вариант 2 Пример

Просто сделайте экран меньше 720px, чтобы увидеть полосы прокрутки для горизонтальной прокрутки.

table {
  border-collapse: collapse;
  border-spacing: 0;
  min-width: 720px;
}

table th {
  text-align: left;
  background-color: #ccc
}

table th,
table td {
  padding: .5em;
  border: 1px solid #999
}

DIV{
  overflow-x:auto;
}
<div>
<table>
  <tr>
    <td></td>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
  </tr>
  <tr>
    <th>09:00 - 11:00</th>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>11:00 - 13:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>13:00 - 15:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th>15:00 - 17:00</th>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
  </tr>
</table>
</div>

Вариант 3. Не используйте таблицу вообще, а используйте другую разметку и сделайте ее похожей на таблицу.

Это может кажется глупой идеей, и во многих отношениях это так! CSS будет тяжелой работой, и она не будет семантически правильной.

Хотя разметка окажется семантически правильной (с точки зрения структуры документа), поскольку у вас есть «заголовок» (<h2>Monday</h2>) и затем «подзаголовок» (<h3>09:00 - 11:00</h3>), за которым следует соответствующая информация <p>Closed</p>. Это просто означает, что визуальный стиль не совсем совпадает с информацией HTML.

Единственное преимущество этого метода в том, что нам не нужно полагаться на WAI-ARIA, чтобы заставить его работать, и мы может позиционировать вещи так, как мы хотим визуально, не влияя на программы чтения с экрана. WAI-ARIA не является идеальной поддержкой на 100%, поэтому это может быть наиболее доступным решением из всех. С другой стороны, это полное изменение данных по сравнению с тем, с чего вы начали.

Вариант 3 Пример

Пожалуйста, сделайте лучше, чем я, 1156, но принцип здравый.

Обратите внимание на то, как у меня есть раздел aria-hidden в начале для представления «рабочего стола» (чтобы скрыть его от программ чтения с экрана, но не визуально) и как я использую визуально скрытую технику на селектор .col h3. Таким образом, что касается программы чтения с экрана, HTML одинаково для обоих.

.container{
  width: 60%;
}


@media only screen and (min-width: 1024px) {
h2, .desktop h3, p{
  outline: 1px solid #333;
  outline-offset: -1px;
  padding: 0px 10px;
  margin: 0;
}


div{
  float: left;
  width: 15%;
  line-height: 2rem;
}
h2{
  line-height: 3rem;

}
.col h3{
  position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
    white-space: nowrap; /* added line */
}
.desktop{
  width: 25%;
  margin-top: 3rem;
  float:left;
  display: block;
}
.desktop h3{
  display: block;
  line-height: 2rem;
}

}

@media only screen and (max-width: 1023px) {
  .desktop{
    display: none;
  }
  h2{
    width: 100%;
    display: block;
    float: left;
    padding: 10px 0px 10px 0px;
    margin: 5px 0;
    border-top: 1px solid #666;
    border-bottom: 1px solid #666;
  }
  h3{
    width: 50%;
    display: block;
    float:left;
    line-height: 2rem;
     padding: 0px;
    margin: 0;
  }
  .col p{
    width: 50%;
    display: block;
    float:left;
    line-height: 2rem;
     padding: 0px;
    margin: 0;
  }
  
  
  
}
<div class=container>
<div class="desktop" aria-hidden="true">
  <h3>09:00 - 11:00</h3>
  <h3>11:00 - 13:00</h3>
  <h3>13:00 - 15:00</h3>
  <h3>15:00 - 17:00</h3>
</div>
<div class="col">
<h2>Monday</h2>
<h3>09:00 - 11:00</h3>
<p>Closed</p>
<h3>11:00 - 13:00</h3>
<p>Open</p>
<h3>13:00 - 15:00</h3>
<p>Open</p>
<h3>15:00 - 17:00</h3>
<p>Closed</p>
</div>
<div class="col">
<h2>Tuesday</h2>
<h3>09:00 - 11:00</h3>
<p>Open</p>
<h3>11:00 - 13:00</h3>
<p>Open</p>
<h3>13:00 - 15:00</h3>
<p>Open</p>
<h3>15:00 - 17:00</h3>
<p>Closed</p>
</div>
<div class="col">
<h2>Wednesday</h2>
<h3>09:00 - 11:00</h3>
<p>Open</p>
<h3>11:00 - 13:00</h3>
<p>Closed</p>
<h3>13:00 - 15:00</h3>
<p>Open</p>
<h3>15:00 - 17:00</h3>
<p>Closed</p>
</div>
<div class="col">
<h2>Thursday</h2>
<h3>09:00 - 11:00</h3>
<p>Closed</p>
<h3>11:00 - 13:00</h3>
<p>Closed</p>
<h3>13:00 - 15:00</h3>
<p>Closed</p>
<h3>15:00 - 17:00</h3>
<p>Open</p>
</div>
<div class="col">
<h2>Friday</h2>
<h3>09:00 - 11:00</h3>
<p>Closed</p>
<h3>11:00 - 13:00</h3>
<p>Closed</p>
<h3>13:00 - 15:00</h3>
<p>Closed</p>
<h3>15:00 - 17:00</h3>
<p>Open</p>
</div>
</div>

Вариант 4. Используйте другой метод (например, предложение G-Cyrillus) и используйте WAI-ARIA для поддержания доступности.

I Мне очень понравилось, насколько чистый метод, предложенный пользователем G-Cyrillus , с точки зрения разделения интересов. CSS для визуалов, HTML для семантики, это то, к чему я стремлюсь каждый день.

Если бы не эта ошибка браузера (которая теперь, когда я думаю об этом, может не быть ошибкой из-за того, что я сказал ранее о том, почему вы не можете использовать свойства отображения в таблицах), это решение было бы идеально (хорошо также 90% покрытия на дисплее: содержание немного низкое, на мой взгляд, но это из-за места, в котором я работаю, и я уверен, что будет подходящая поли-заливка для рубина sh браузеры!)

Для этого метода решение будет использовать WAI-ARIA .

Это позволяет добавлять атрибуты к элементам для добавления дополнительной информации. или опишите семантику элемента для программы чтения с экрана. Это поможет нам заменить семантическую информацию, которая уничтожается при применении к таблице стиля position или display.

Для таблиц у нас есть несколько элементов арии, которые мы можем использовать для создания таблицы из элементы, не относящиеся к таблице .

Единственный реальный недостаток этого метода заключается в том, что вам придется либо использовать JavaScript для добавления атрибутов aria (менее предпочтительно), либо добавить их в HTML разметка (лучше, чем тогда, даже если JavaScript терпит неудачу, она все еще идеально доступна).

Так какой метод я бы выбрал?

Я очень удивлен, что говорю это, но вариант 1. «Создайте вторую таблицу для мобильного представления и отключите их с помощью медиазапросов».

В отношении удобства сопровождения, я бы предположил, что вы создадите это программно, связанное с CMS или подобным, поэтому я не думаю, что это проблема. Он доступен (при условии, что таблица 2 правильно структурирована) и требует минимального CSS.

Кроме моей инстинктивной реакции на то, что это хак, я на самом деле думаю, что это отличный вариант, и это было бы наиболее доступный способ сделать это.

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

1 голос
/ 21 марта 2020

Я делаю ответ из комментария муравья, чтобы дать кому-то что-то, что можно использовать для лучшего или эффективного ответа:

, включенный во фрагмент ниже,

  • Запрос @support перед запуском: содержание

  • al oop для генерации атрибута данных, который может быть использован.

  • a matchmedia ( Медиа-запрос через javascript), чтобы обновить атрибуты роли tds, становясь рядом с их псевдо. https://w3c.github.io/aria-practices/examples/table/table.html

Это не все гладко работает вместе, это только мысли, незавершенные. Не стесняйтесь, чтобы улучшить его.

// data attribute generated from the th content of each tr
for (let tr of document.querySelectorAll("tr")) {
  var myDataAttr = tr.querySelector("th").textContent;
  for (let td of tr.querySelectorAll("td")) {
    td.setAttribute("data-time", myDataAttr);
  }
}

// check if display:contents is avalaible
var supported = false;
if (window.CSS) {
    supported = window.CSS.supports('display', 'contents');
} else {
    //nothing needed for now
}


// check screen size for the role attributes on td's 
window.onload = mymq;
window.onresize = mymq;

function mymq() {
  const mq = window.matchMedia("(max-width: 768px)");
  if (mq.matches  &&  supported !=false) {// also checking on display:contents supports
    for (let td of document.querySelectorAll("td")) {
      td.setAttribute("role", "row");
    }
  } else {
    for (let td of document.querySelectorAll("td")) {
      td.setAttribute("role", "cell");
    }
  }
}
table {
  width: 100%;
  border-collapse: collapse;
  background: rgb(196, 215, 70)
}

tr:nth-child(2n) {
  background: lightblue;
}

th,
:before {
  background: tomato;
  box-shadow: inset 0 0 0 2px;
}

th,
td {
  box-shadow: inset 0 0 0 2px;
  text-align: center;
  vertical-align: middle;
  padding: 0.5em;
  vertical-align: middle;
}

@supports (display: contents) {
  /* trick works if data-time attributes stands in html and if display:contents is supported */
  @media screen and (max-width: 768px) {
    table {
      display: flex;
      flex-flow: column;
    }
    thead,
    tr,
    tbody {
      display: contents;
    }
    tr th:first-child {
      display: none;
    }
    th {
      background: red;
    }
    td {
      display: table;
      table-layout: fixed;
      border-collapse: collapse;
      width: 100%;
    }
    td:before {
      content: attr(data-time);
      border-right: solid 1px;
      display: table-cell;
      vertical-align: middle;
      white-space: pre;
      /* only if you care */
      padding: 0.25em;
    }
    tr :nth-child(2) {
      order: 0;
    }
    tr :nth-child(3) {
      order: 1;
    }
    tr :nth-child(4) {
      order: 2;
    }
    tr :nth-child(5) {
      order: 3;
    }
    tr :nth-child(6) {
      order: 4;
    }
    tr :nth-child(7) {
      order: 5;
    }
  }
}

/* let's see if role attribute value is being updated  */
td::after {
  content:'role='attr(role);
  display:block;
  font-family:courier;
  font-size:0.7em;
}
<table role="table">
  <caption>Delivery slots:</caption>
  <tr>
    <td></td>
    <th scope="col">Monday</th>
    <th scope="col">Tuesday</th>
    <th scope="col">Wednesday</th>
    <th scope="col">Thursday</th>
    <th scope="col">Friday</th>
  </tr>
  <tr>
    <th scope="row">09:00 - 11:00</th>
    <td>Closed</td>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
  <tr>
    <th scope="row">11:00 - 13:00</th>
    <td>Open</td>
    <td>Open</td>
    <td>Closed</td>
    <td>Closed</td>
    <td>Closed</td>
  </tr>
</table>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...