23

我正在努力重新设计一个遗留工具集,并且我正在研究如何更好地在外观和语义上显示一些信息。

数据本质上是分层的,但具有需要用户随时可见的属性。所需的布局类似于下面。

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列表 - 序列号是可选的,并不总是一个数字。如果它是一组列表,那将正确缩进子列表,但是呈现短属性的最佳方式是什么?

如果是表,那么在表中呈现层次结构的语义存在的最佳方式是什么?

4

7 回答 7

23

这里的挑战是,您要表示的信息一方面是表格的(它是一组具有相同标签属性的项目),另一方面是分层的(项目有父项)。

不幸的是,HTML 中没有用于表格行的嵌套分组机制:tbody可用于对行进行分组,但嵌套它是非法的(除了 a 中的中间体tabletd这非常可怕)。

这让你有两个选择:

  1. 用某种嵌套列表表示信息,并依靠 CSS 使结果看起来像一个表格。

  2. 将信息表示为表格,并依靠某种属性来表示其层次关系。

以下是您如何实施这些选择的一些示例:

使用嵌套列表(天真的方法):

<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>

在这里,我们使用描述列表来描述两件事:

  1. 例如“项目名称”和“标识符”等之间的标题/详细信息关系。

  2. 例如,“姓名”单元和“名字”单元之间的父/子关系。

它当然更紧凑,但不幸的是,每个标题与其细节元素之间的特定关系充其量是隐含的,并且如果没有额外的样式以表格方式直观地组织信息,则在渲染实际表示的内容时就更不明显了。

使用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 看起来是否合理?” 经验法则比上面的任何一种嵌套列表方法都要好得多。

于 2013-07-20T03:30:00.503 回答
8

我将通过使用表格并向标签添加自定义数据属性来呈现它: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上工作。

于 2013-07-17T06:40:47.337 回答
3

I think there are two sensible ways how to represent this in HTML:

  • use a table and make the relation/hierarchy explicit with natural language
  • use sectioning elements (resp. headings if you use HTML 4.01)

table with a column explaining the hierarchy

If there is no markup for defining this relationship, you should use text. If the visual representation is unambiguous, you could visually hide this text so that it is only accessible for screenreader/text browser users.

In your case, you could add a column that explains the relationship of rows that are "sub items":

<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>

Each row could get an id (with value of Seq or Item Name), so that this row can be linked {note that id values starting with a digit are not allowed in HTML 4.01; you could use something like id="seq-2.1" there}. If an item is a child of another item, you could link to the row of the parent item.

This way you make it clear for humans, and machines still see that these rows are connected, although the specific semantics of this relation is not machine-readable. You could use a link type (rel value) here if to make the meaning of the relation explicitly clear. In HTML 4.01 you could create a value yourself, in HTML5 it would need to be registered first.

sectioning elements / headings

Instead of using a table, you could make use of HTML’s outlining. {The following example uses HTML5’s sectioning elements. If you use HTML 4.01, simply replace the sectioning elements with div (or no element at all) and use headings only.}

Each section (introduced by a heading) represents an item. The outline of the headings (resp. nesting of the sectioning elements) represents the hierarchy of your items.

Here is an example to see the whole structure:

 <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>

Each section could contain a dl for the properties:

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

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

</section>

Depending of the actual meaning of your content, you could use the code element for the item names (e.g. if it describes elements of a markup language, for example), and/or the dfn element, if the following content is a definition of that item.

于 2013-07-21T10:50:38.200 回答
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 链接

于 2013-07-20T01:21:50.467 回答
2

更新:我添加了 ID 和“标题”属性的使用,以某种方式在语义上标记层次结构。

这绝对是表格数据(您应该真正推动“列表”的定义,以证明在这里使用 UL 或 DL 是合理的!)。

我认为一个好的方法是使用不同的 tbody 将这些相关的行组合在一起(它在这里使用的类似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>
于 2013-07-26T05:19:12.530 回答
2

我认为你应该使用一张桌子。确实,层次更重要,但也可以通过手动写下第一列来显示。但是属性 min、max 和 item name 不能像在表中那样容易地显示在列表中。我的意见:使用表格并手动提供 seq 列!

于 2013-07-17T06:26:59.543 回答
0

为什么不兼得?树形网格是表示也符合层次结构的表格数据的好方法。

这是一个这样的例子

但是,在两个非常大的项目中使用过 Extjs,我个人的建议是,如果您要生成一个大型应用程序,请远离它。虽然对于一次性网格来说可能很好,但我个人发现它的实施很差,并且随着项目规模的增加会变得更加麻烦。但是,它的功能非常丰富,因此示例面板可能会为您提供更多关于网格(表格)的想法,这可能会对您有所帮助。

请记住,您应该始终问自己,“我的用户试图回答什么问题?” 然后,问问自己,“哪些图形设备可以最清晰、最简单地回答这个问题?”

真正帮助我解决这些问题的一本书是仪表板设计书。尽管您可能没有构建仪表板,但它具有许多 UX 技术和理论,使我在选择适当的 UI 元素(关于数据)时更容易。

希望有帮助...

于 2013-07-20T03:38:33.973 回答