Вопрос по html, wcag, wcag2.0, css, html-table – Объединение таблицы и иерархического списка в HTML

19

Я работаю над редизайном устаревшего набора инструментов и смотрю, как лучше отобразить некоторую информацию как в презентационном, так и в семантическом виде.

Данные иерархически по своей природе, но имеют свойства, которые должны быть легко видны пользователям. Желаемый макет похож на ниже.

Seq     Item Name         Min  Max  - Anything under here isn't shown
 1      Identifier         1    1     (Required)
 2      Name               1    1
  2.1    First Name        1    1
  2.2    Middle Name       -    -     (Optional but unlimted)
  2.3    Last Name         1    1
 3      Age                -    1     (Optional)

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

Задача, которую я имею, - выяснить, как эффективно отображать эту информацию.

Прежде всего это табличные данные? Я бы сказал нет, так как иерархия важна, а «столбцы» - это просто атрибуты элемента в каждой «строке».

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

Если это таблица, как лучше представить семантическое существование иерархии в таблице?

Ограничена ли иерархия вашей реальной информации двумя уровнями (как в вашем примере)? Zero Piraeus
@ ZeroPiraeus Нет, это произвольная глубина, но на практике, вероятно, не более 5-8. user764357
Я не знаю, что случилось со столом. Я думаю, что этоЯВЛЯЕТСЯ табличные данные, потому что они поступают в строках и столбцах. Это не меняется по иерархии yunzen

Ваш Ответ

7   ответов
2

что вы должны использовать стол. Правда, иерархия важнее, но ее также можно отобразить, записав вручную первый столбец. Но атрибуты min, max и имя элемента не могли быть отображены в списке так же легко, как в таблице. Мое мнение: используйте таблицу и предоставьте колонку seq вручную!

3

использоватьtable и сделать связь / иерархию явными с естественным языкомиспользуйте элементы секционирования (соответственно заголовки, если вы используете HTML 4.01)table с колонкой, объясняющей иерархию

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

В вашем случае вы можете добавить столбец, который объясняет отношения строк, которые являются «подпунктами»:

<table>

  <tr>
    <th>Seq</th> 
    <th>Relation</th> <!-- or some clever better label -->
    <th>Item Name</th>
    <th>Min</th>
    <th>Max</th>
  </tr>

  <!-- … -->

  <tr id="2">
    <td>2</td>
    <td></td> <!-- "parent", "root", "container", empty -- whatever makes sense for your case -->
    <td>Name</td>
    <td>1</td>
    <td>1</td>
  </tr>

  <tr id="2.1">
    <td>2.1</td>
    <td>child of <a href="#2">Name</a></td>
    <td>First Name</td>
    <td>1</td>
    <td>1</td>
  </tr>

</table>

Каждый ряд может получитьid (со значением Seq или Item Name), так что эта строка может быть связанаid значения, начинающиеся с цифры, не допускаются в HTML 4.01; Вы могли бы использовать что-то вродеid="seq-2.1" там}. Если элемент является дочерним по отношению к другому элементу, вы можете указать ссылку на строку родительского элемента.

Таким образом, вы проясните для людей, и машины все еще видят, что эти строки связаны, хотя конкретная семантика этого отношения не читается машиной. Вы можете использовать тип ссылки (rel значение) здесь, если сделать смысл отношения явно понятным. В HTML 4.01 вы можете создать значение самостоятельно, в HTML5 это должно бытьзарегистрированный первый.

элементы секционирования / заголовки

Вместо использованияtableВы могли бы использовать контуры HTML. {В следующем примере используетсяHTML5-элементы секционирования, Если вы используете HTML 4.01, просто замените элементы секционирования наdiv (или вообще без элемента) и используйте только заголовки.}

Каждый раздел (введенный заголовком) представляет элемент. Схема заголовков (соответственно вложенность элементов секционирования) представляет иерархию ваших элементов.

Вот пример, чтобы увидеть всю структуру:

 <article>

   <h1><!-- heading for the whole data --></h1>

   <section class="item" id="1">
     <h2>Identifier</h2>
   </section>

   <section class="item" id="2">
     <h2>Name</h2>

     <section class="item" id="2.1">
       <h3>First Name</h3>
     </section>

     <section class="item" id="2.2">
       <h3>Middle Name</h3>
     </section>

     <section class="item" id="2.3">
       <h3>Last Name</h3>
     </section>

   </section>

   <section class="item" id="3">
     <h2>Age</h2>
   </section>

 </article>

каждыйsection может содержатьdl для свойств:

<section class="item" id="3">
  <h2>Age</h2>

  <dl>
    <dt>Min</dt>
    <dd>1</dd>
    <dt>Max</dt>
    <dd>1</dd>
  </dl>

</section>

В зависимости от реального значения вашего контента, вы можете использоватьcode элемент для названий элементов (например, если он описывает элементы языка разметки) и / илиdfn элемент, если следующее содержание является определением этого элемента.

20

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

К сожалению, в HTML нет вложенного механизма группировки строк таблицы:tbody может использоваться для группировки строк, но вложение это недопустимо (за исключением промежуточногоtable внутриtdчто довольно ужасно).

Это оставляет вам два варианта:

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

Представлять информацию в виде таблицы и полагаться на какие-либо атрибуты для представления ее иерархических отношений.

Вот несколько примеров того, как вы могли бы реализовать этот выбор:

Использование вложенных списков (наивный подход):

<ul>
  <li>
    <dl>
      <dt>Seq</dt> <dd>1</dd>
      <dt>Item Name</dt> <dd>Identifier</dd>
      <dt>Min</dt> <dd>1</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
  </li>
  <li>
    <dl>
      <dt>Seq</dt> <dd>2</dd>
      <dt>Item Name</dt> <dd>Name</dd>
      <dt>Min</dt> <dd>1</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
    <ul>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.1</dd>
          <dt>Item Name</dt> <dd>First Name</dd>
          <dt>Min</dt> <dd>1</dd>
          <dt>Max</dt> <dd>1</dd>
        </dl>
      </li>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.2</dd>
          <dt>Item Name</dt> <dd>Middle Name</dd>
          <dt>Min</dt> <dd>-</dd>
          <dt>Max</dt> <dd>-</dd>
        </dl>
      </li>
      <li>
        <dl>
          <dt>Seq</dt> <dd>2.3</dd>
          <dt>Item Name</dt> <dd>Last Name</dd>
          <dt>Min</dt> <dd>1</dd>
          <dt>Max</dt> <dd>1</dd>
        </dl>
      </li>
    </ul>
  </li>
  <li>
    <dl>
      <dt>Seq</dt> <dd>3</dd>
      <dt>Item Name</dt> <dd>Age</dd>
      <dt>Min</dt> <dd>-</dd>
      <dt>Max</dt> <dd>1</dd>
    </dl>
  </li>
<ul>

Это обрабатывает иерархический аспект информации, но в конечном итоге вы многократно повторяете себя, и вам придется перепрыгивать через некоторые циклы в CSS, чтобы отобразить результат в табличной форме. Это вероятно выполнимо при разумном использовании:first-child, но конечный результат состоит в том, что вы старались изо всех сил пометить что-то, что вы хотите представить в виде таблицы не в табличной форме, и в результате вы дали себе больше работы по приведению его в форму.

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

Использование вложенных списков («умный» подход):

<dl>
  <dt>
    <ul> <li>Seq</li> <li>Item Name</li> <li>Min</li> <li>Max</li> </ul>
  </dt>
  <dd>
    <ul> <li>1</li> <li>Identifier</li> <li>1</li> <li>1</li> </ul>
  </dd>
  <dd>
    <dl>,;
      <dt>
        <ul> <li>2</li> <li>Name</li> <li>1</li> <li>1</li> </ul>
      </dt>
      <dd>
        <ul> <li>2.1</li> <li>First Name</li> <li>1</li> <li>1</li> </ul>
      </dd>
      <dd>
        <ul> <li>2.2</li> <li>Middle Name</li> <li>-</li> <li>-</li> </ul>
      </dd>
      <dd>
        <ul> <li>2.3</li> <li>Last Name</li> <li>1</li> <li>1</li> </ul>
      </dd>
    </dl>
  </dd>
  <dd>
    <ul> <li>3</li> <li>Age</li> <li>-</li> <li>1</li> </ul>
  </dd>
</dl>

Здесь мы используемсписки описания описать две вещи:

Отношение заголовок / подробность, например, между «Имя элемента» и «Идентификатор» и т. Д.

Родительско-дочерние отношения, например, между блок «Имя» и блок «Имя».

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

С помощьюtable:

<table>
  <thead>
    <tr>
      <th>Seq</th> <th>Item Name</th> <th>Min</th> <th>Max</th>
    </tr>
  </thead>
  <tbody>
    <tr id=100>
      <td>1</th> <th>Identifier</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=200>
      <th>2</th> <th>Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=210 data-parent=200 class=level-1>
      <th>2.1</th> <th>First Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=220 data-parent=200 class=level-1>
      <th>2.2</th> <th>Middle Name</th> <td>-</td> <td>-</td>
    </tr>
    <tr id=230 data-parent=200 class=level-1>
      <th>2.3</th> <th>Last Name</th> <td>1</td> <td>1</td>
    </tr>
    <tr id=300>
      <th>3</th> <th>Age</th> <td>-</td> <td>1</td>
    </tr>
  </tbody>
</table>

Здесь родительские / дочерние отношения явно описываютсяdata-parent атрибут (который может быть доступен через JavaScript при необходимости), иclass=level-{n} Атрибут предоставляет хук, который может использоваться CSS:

.level-1 > th {
  padding-left: 1em;
}

В конечном счете, это вопрос личных предпочтений и удобства, но я думаю, что<table> подход лучше просто потому, что он удовлетворяет "выглядит ли это разумно без CSS?" Эмпирическое правило намного лучше, чем любой из вышеперечисленных подходов.

Осторожно, атрибуты id не могут начинаться с цифры. Matt Sach
Хороший ответ. Дляtable решение, не было бы лучше использоватьатрибут заголовков вместо того чтобы придумыватьdata-parent)?headers атрибут также читается программами чтения с экрана, но AFAIK он может применяться только к отдельным ячейкам (например,seq или жеitem name клетки), а не целые ряды. JohnCand
Ну, взорви меня пером, я понятия не имел, что изменилось. Спасибо! Matt Sach
@MattSach Этобольше не правда в HTML5. Zero Piraeus
2

ОБНОВЛЕНИЕ: я добавил использование идентификаторов и атрибута «заголовки», чтобы как-то семантически разметить иерархию.

Это определенно табличные данные (вы должны действительно толкнуть определение «список», чтобы оправдать использование здесь UL или DL!).

Я думаю, что хороший подход будет использовать разные tbodys для группировки этих связанных строк (что-то вроде этого, он использовал здесьhttp://www.w3.org/TR/2012/WD-html5-20120329/the-table-element.html#the-table-element см. «таблица, используемая для разметки головоломки Судоку»)

<table>
  <thead>
    <tr>
      <th id="seq">Seq</th>
      <th>Item Name</th>
      <th>Min</th>
      <th>Max</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="s1" headers="seq">1</th>
      <td>Identifier</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th id="s2" headers="seq">2</th>
      <td>Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub">
      <th id="s2_1" headers="seq s2">2.1</th>
      <td>First Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub">
      <th id="s2_2" headers="seq s2">2.2</th>
      <td>Middle Name</td>
      <td>-</td>
      <td>-</td>
    </tr>
    <tr class="sub">
      <th id="s2_3" headers="seq s2">2.3</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub sub">
      <th id="s2_3_1" headers="seq s2 s2_3">2.3.1</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr class="sub sub">
      <th id="s2_3_2" headers="seq s2 s2_3">2.3.2</th>
      <td>Last Name</td>
      <td>1</td>
      <td>1</td>
    </tr>
  </tbody>
  <tbody>
    <tr>
      <th id="s3" headers="seq">3</th>
      <td>Age</td>
      <td>-</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

Тогда вы можете использовать что-то вроде этого:

table { border-collapse: collapse; }
tbody { border-bottom:1px solid #000; }
tbody .sub td { padding-left: 10px; }

На самом деле, я думаю, что вы можете использовать только tbody, чтобы сгруппировать строки и оставить отдельные строки в покое.

<tr>
  <td>1</td>
  <td>Identifier</td>
  <td>1</td>
  <td>1</td>
</tr>
<tbody>
  <tr>
    <td>2</td>
    <td>Name</td>
    <td>1</td>
    <td>1</td>
  </tr>
  <tr class="sub">
    <td>2.1</td>
    <td>First Name</td>
    <td>1</td>
    <td>1</td>
  </tr>
  ...
</tbody>
<tr>
  <td>3</td>
  <td>Age</td>
  <td>-</td>
  <td>1</td>
</tr>
Для визуального представления вы можете использовать разные имена классов на каждом уровне (я использовал опцию в примере, но вы также можете использовать что-то вроде «level_0», «level_1», «level_2» и т. Д.). Coluccini
Есть атрибут «заголовки», который вы можете использовать для обозначения иерархии. Я сделаю пример и отредактирую сообщение через минуту. Coluccini
С помощьюtbody группировка элементов не будет работать, когда существует несколько уровней иерархии, как указано в комментариях OP. Zero Piraeus
Интересно; Я не знал оheadersи это хороший вариант использования. Но как вы собираетесь использовать его в качестве ловушки CSS для визуального представления глубины иерархии, минуя два уровня, которые вы используете?tbody дает тебе? Zero Piraeus
2

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

Например, список описания для первой строки может выглядеть примерно так:

<dl>
  <dt>Item Name</dt>
  <dd>Identifier</dd>
  <dt>Min</dt>
  <dd>1</dd>
  <dt>Max</dt>
  <dd>1</dd>
  <dt>Notes</dt>
  <dd>(Required)</dd>
</dl>

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

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

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

CodePen Link

0

ых данных, которые также соответствуют иерархии.

Этоодин такой пример.

Однако, используя Extjs в двух очень больших проектах, я лично рекомендую держаться от него подальше, если вы собираетесь создавать большое приложение. Хотя это может быть хорошо для одноразовой сетки, я лично считаю, что она плохо реализована и может стать более громоздкой по мере увеличения размера проекта. Тем не менее, это очень многофункциональный, поэтомупанель примеров может дать вам больше идей по сеткам (таблицам), которые могут вам помочь.

Имейте в виду, что вы всегда должны задавать себе вопрос: «На какие вопросы пытаются ответить мои пользователи?» Затем спросите себя: «Какие графические устройства дают самый ясный и простой способ ответить на этот вопрос?»

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

Надеюсь, это поможет...

@ Homer6 Часть проблемы, я ищу решение "только для HTML". Программы чтения с экрана и другие специальные браузеры могут ограничивать использование CSS и JS, поэтому предпочтительным является решение только на HTML. user764357
Никаких обид не было задумано ... по моему опытуявляется Обычно в комментариях указываются потенциальные недостатки ответа, независимо от того, дал ли комментатор ответ (это наверняка случилось со мной). По второму пункту: яваскрипт или отсутствие яваскрипта, я думаю, что законно критиковать «вообще не представлять данные» как способ представления данных. OP явно заботится о семантической разметке, и пример, на который вы ссылаетесь, совсем не похож на. Zero Piraeus
Я не уверен, что я бы описал<div id="tree-example"></div> (из вашего связанного примера) как семантическое представление данных ... этоявляется очень Extjs подход, хотя ;-) Zero Piraeus
Я не уверен, что стоит критиковать ответы других, когда вы публикуете свой собственный. Он спросил о представлении данных в веб-интерфейсе пользователя. Означает ли это «только HTML»? Потому что я, конечно, не считаю, что текущее состояние сети. Javascript - это бесценный инструмент пользовательского интерфейса. Homer6
... если это поможет, я просто проголосовал за один из ваших ответов в другом месте :-) Zero Piraeus
7

Я хотел бы представить его с помощью таблицы и добавивпользовательские атрибуты данных кtd теги:

<table id="myTable" class="table">
    <tr>
        <td data-indent="0">1</td>
        <td data-indent="0">Test</td>
        <td data-indent="0">Test 1</td>
    </tr>
    <tr>
        <td data-indent="1">1.1</td>
        <td data-indent="1">Another</td>
        <td data-indent="0">Test 1.1</td>
    </tr>
    <tr>
        <td data-indent="2">1.1.1</td>
        <td data-indent="3">Another</td>
        <td data-indent="0">Test 1.1.1</td>
    </tr>
        <tr>
        <td data-indent="2">1.1.2</td>
        <td data-indent="3">Another one</td>
        <td data-indent="0">Another test 1.1.2</td>
    </tr>
    <tr>
        <td data-indent="0">2</td>
        <td data-indent="0">Test</td>
        <td data-indent="0">Test 2</td>
    </tr>
</table>

Затем с помощью jQuery установите заполнение каждого значения ячейки в вашей таблице:

$("td")
    .css("padding-left", function (index) {
    return 10 * parseInt($(this).data("indent")) + "px";
});

Видите это работает наjsFiddle.

Однако, как я вижу, проблема в том, что вы теряете семантику иерархии. user764357
Почему бы не сделать заполнение через CSS? Вы можете сопоставить ячейки с падением через td: first-child [data-indent = "1"] или td: first-child [data-indent = "2"] и применить необходимые отступы. Lars Ebert

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