名称-值对的语义和结构


76

这是我一段时间以来一直在苦苦挣扎的问题。标记名称/值对的正确方法是什么?

我喜欢<dl>元素,但这带来了一个问题:无法将一对对分开-它们没有唯一的容器。在视觉上,代码缺乏定义。不过从语义上来说,我认为这是正确的标记。

<dl>
    <dt>Name</dt>
    <dd>Value</dd>
    <dt>Name</dt>
    <dd>Value</dd>
</dl>

在上面的代码中,很难在代码和渲染上都在视觉上正确地偏移对。例如,如果我想在每对之间都设置边框,那将是一个问题。

我们可以指向表格。可以说名称-值对是表格数据。这对我来说似乎是不正确的,但我明白了。但是,HTML不会将名称与值区别开来,除非在位置或添加了类名。

<table>
    <tr>
        <td>Name</td>
        <td>Value</td>
    </tr>
    <tr>
        <td>Name</td>
        <td>Value</td>
    </tr>
</table>

从代码和CSS的视觉角度来看,这更有意义。设置上述边框的样式很简单。但是,如上所述,语义充其量是模糊的。

有想法,评论,问题吗?

编辑/更新 也许这是我应该在结构上明确提及的内容,但是定义列表也存在不对语义进行分组的问题。add和a之间的有序和隐式边界dt很容易理解,但对我来说它们仍然有些许不适。


回复:您的编辑/更新-如果您想绝对确保节点之间的语义关系没有歧义,您总是会很冗长,并做<dt id =“ key1”>名称</ dt> <dd about =“# key1“>值1 </ dd> <dd about =”#key1“>值2 </ dd>,但有些人会称其为过大杀伤力。;)
lucideer 2010年

您还应该询问CSS。例如,效果<dl>还不错,但是很难设置样式
以内

有很多好的答案,尤其是在代码方面,但是我几乎对所有的答案都有些犹豫。这仅仅是因为每个解决方案都是让步。我将很快将当前答案之一标记为对此线程最好的选择,但要知道这是一个艰难的决定。
瑞安·金纳尔

@Danny Lin就是那个!改进的规格使语义和样式轻松自如!stackoverflow.com/a/50313363/792888
EvilDr,

Answers:


57

感谢您提出这个有趣的问题。这里还有几件事要考虑。

什么是一对?两个元素在一起。因此,我们需要一个标签。假设它是pair标签。

 <pair></pair>

该对包含密钥和相应的值:

 <pair><key>keyname</key><value>value</value></pair>

然后,我们需要列出对:

<pairlist>
     <pair><key>keyname</key><value>value</value></pair>
     <pair><key>keyname</key><value>value</value></pair>
</pairlist>

接下来要考虑的是对的显示。通常的布局是表格形式:

key value
key value

和可选的分隔符,通常是冒号:

key : value
key : value

冒号可以通过CSS轻松添加,但这在IE中当然无法使用。

上述情况是理想的情况。但是没有有效的HTML标记可以轻松地实现此目的。


总结一下:

dl在键和值的简单情况下,在语义上最接近,但是很难应用视觉样式(例如,以内联方式显示对或在刚刚悬停的对上添加红色边框)。最适合的情况dl是词汇表。但这不是我们讨论的情况。

在这种情况下,我可以看到的唯一替代方法是使用table,如下所示:

<table summary="This are the key and value pairs">
    <caption>Some notes about semantics</caption>
    <thead class="aural if not needed">
        <tr><th scope="col">keys</th><th scope="col">values</th></tr>
    </thead>
    <tbody class="group1">  
        <tr><th scope="row">key1</th><td>value1</td></tr>
        <tr><th scope="row">key2</th><td>value2</td></tr>
    </tbody>
    <tbody class="group2">
        <tr><th scope="row">key3</th><td>value3</td></tr>
        <tr><th scope="row">key4</th><td>value4</td></tr>
    </tbody>
</table>

多一个:

<ul>
  <li><strong>key</strong> value</li>
  <li><strong>key</strong> value</li>
</ul>

要么:

<ul>
  <li><b>key</b> value</li>
  <li><b>key</b> value</li>
</ul>

或者,当按键可能被链接时:

<ul>
  <li><a href="/key1">key1</a> value</li>
  <li><a href="/key2">key1</a> value</li>
</ul>

键和值对通常存储在数据库中,而键和值对通常存储表格数据,因此该表最适合恕我直言。

你怎么看?


4
非常彻底的答案。我喜欢你如何表达自己的想法。+1
Ryan Kinal

以及诸如此类的事情:<ul> <li><div class="key">key</div><div class="value">value</div></li> </ul>我们可以拥有任意键和值(一个值可以是另一个列表,图像等)
Enrique

此外,对于表格解决方案,您可以使用<col class="key"/>标记。无论如何,我认为表解决方案不是很好,如果我们可以在不同的行中显示键和值怎么办?
Enrique

2
我相信(嗯,几乎知道<strong>应该<b>根据HTML5语义替换。
Andreas Rejbrand

1
这个问题在Google中名列前茅。您能否考虑更新您的答案以反映@Danny Lin关于在内使用divs的输入dl?这解决了语义和样式问题,从而避免了<b>and的干扰<strong>stackoverflow.com/a/50313363/792888
EvilDr

20

规范(和进一步的细节由亚历山大安东诺夫提供):使用dldtdd,和任选的div

的组合dldtdd在语义罚款键-值对:

<dl>
    <dt>Key1</dt>
    <dd>Value1</dd>
    <dt>Key2</dt>
    <dd>Value2</dd>
</dl>

为了使样式或解析更加容易,div可以将s用作dl组合键值对的子项(以及dtdd成为的子项dl):

dl { display: table; }
dl > div { display: table-row; }
dl > div > dt, dl > div > dd { display: table-cell; border: 1px solid black; padding: 0.25em; }
dl > div > dt { font-weight: bold; }
<dl>
  <div>
    <dt>Key1</dt>
    <dd>Value1</dd>
  </div>
  <div>
    <dt>Key2</dt>
    <dd>Value2</dd>
  </div>
</dl>


出色的答案,应该接受恕我直言,尤其是考虑到规范中包含的示例非常适合该问题。CSS Grid也是一种简单有效的格式化方法。
EvilDr '19

12

XHTML 2引入了使用di元素对术语和定义进行分组的功能

<!-- Do not us this code! -->
<dl>
    <di>
        <dt>Name</dt>
        <dd>John</dd>
    </di>
    <di>
        <dt>Age</dt>
        <dd>25</dd>
    </di>
</dl>

X / HTML 5 vs XHTML 2>增强定义列表

但是不幸的是,XHTML 2已经死了,HTML5没有 di元素

因此,您可以结合ul > li使用dl > dt + dd

<ul>    
    <li>
        <dl>
            <dt>Name</dt>
            <dd>John</dd>
        </dl>
    </li>
    <li>
        <dl>
            <dt>Age</dt>
            <dd>25</dd>
        </dl>
    </li>
</ul>

7
天啊。哇。我想要<di>元素。我现在就想要。太糟糕了,我不能拥有它。谢谢你的信息!
Ryan Kinal

2
根据规范,div充当的角色di。详见我的答案。
林丹妮

6

我认为定义列表可能不是一个好主意。在语义上,它们用于定义。其他键值列表通常会与定义标题和描述不同。

Atable是一种解决方法,但是无序列表又如何呢?

<ul>
    <li class="key-value-pair">
        <span class="key">foo</span>
        <span class="value">bar</span>
    </li>
</ul>

2
在这方面,定义列表的命名可能略有欠佳,但它们并非纯粹用于定义(如果使用的话,它们的使用情况将非常有限)-W3C规范。定义它们的示例实际上就是使用它们标记对话的示例。
lucideer

从面向对象的角度考虑它,我想我正在寻找的是“名称-值对的无序列表”,但是我不确定这是最好的答案(目前)。+1
Ryan Kinal

1
这是一种微格式方法,但是在默认的浏览器渲染或屏幕阅读器中,您将获得foo bar,就像foo bar根本没有任何标签一样。跨度之一需要大于一个跨度。也许<strong>吧?然后,不需要第二个。
Takehin 2010年

3
在当前的HTML5规范中,dl已重命名为描述列表,这使得在这里看起来更正确。
埃里克·博克

3

这不是我的首选解决方案,但这是对语义元素的巧妙滥用:

使用新的<dl><dt>/<dd>对:

<div class="terms">
    <dl><dt>Name 1</dt><dd>Value 1</dd></dl>
    <dl><dt>Name 2</dt><dd>Value 2</dd></dl>
</div>

带有css浮动和悬停时带有红色边框的示例:

dt:after { content:":"; }
dt, dd { float: left; }
dd { margin-left: 5px }
dl { float: left; margin-left: 20px; border: 1px dashed transparent; }
dl:hover { border-color: red; }
<div class="terms">
    <dl>
        <dt>Name 1</dt>
        <dd>Value 1</dd>
    </dl><!-- etc -->
    <dl><dt>Name 2</dt><dd>Value 2</dd></dl>
    <dl><dt>Name 3</dt><dd>Value 3</dd></dl>
    <dl><dt>Name 4</dt><dd>Value 4</dd></dl>
    <dl><dt>Name 5</dt><dd>Value 5</dd></dl>
    <dl><dt>Name 6</dt><dd>Value 6</dd></dl>
</div>


有趣。如果不需要将其作为相关项目的列表,这将可以工作……尽管我认为可以将每个项目封装<dl><li>
Armstrongest

3

dl {
  display: grid;
  grid-template-columns: auto auto;
}

dd {
  margin: 0
}
<dl>
  <dt>key</dt>
  <dd>value</dd>
  <dt>key</dt>
  <dd>value</dd>
</dl>

我用<dl> <dt> <dd>网格对它们进行样式设置


2

无论是在代码还是在渲染上,都很难在视觉上正确地抵消对。例如,如果我想在每对之间都设置边框,那将是一个问题。

我之前的其他人已经(在我看来很好)处理了在代码中提供可视化定义的问题。剩下的问题是渲染和​​CSS。在大多数情况下,这可以非常有效地完成。最大的例外是在每组dt / dds周围设置边框,这被认为非常棘手-可能无法可靠地设置样式。

您可以这样做:

dt,dd{ border:solid; }
dt{ margin:10px 0 0 0; border-width:1px 1px 0 1px; }
dd{ margin:0 0 10px 0; border-width:0 1px 1px 1px; padding:0 0 0 10px; }
dd::before{ content:'→ '; }

它适用于键值对,但是如果您在一个“集合”中有多个dd,则会出现问题,例如:

<dt>Key1</dt>
  <dd>Val1.1</dd>
  <dd>Val1.2</dd>
<dt>Key2</dt>
  <dd>Val2.1</dd>
  <dd>Val2.2</dd>

但是,除了边框样式限制之外,使用CSS进行关联集(背景,编号等)的任何其他操作都是很有可能的。这里有一个很好的概述:http : //www.maxdesign.com.au/articles/definition/


我想指出的另一点是,如果您正在寻找最佳样式定义列表以提供视觉分隔,则CSS的自动编号功能(counter-incrementcounter-reset)会派上用场:http : //www.w3.org/TR/ CSS2 / generate.html#counters


2

当然,您可以只使用HTML Custom Elements。(spec)它们是完全有效的HTML5。

不幸的是,浏览器支持不是很好,但是在处理语义时,我们很少关心诸如浏览器支持之类的行事。:-)

您可以用一种这样的方式表示它:

在注册您的全新花式元素后,如下所示:

var XKey = document.registerElement('x-key');
document.body.appendChild(new XKey());

您可以这样编写标记:

<ul>
  <li>
    <x-key>Name</x-key>
    Value
  </li>
</ul>

HTML Custom元素具有的唯一条件是它们中需要一个破折号。当然,您现在可以变得超级有创意……如果您要建立一个带有零件清单和序列号的汽车零件仓库,请执行以下操作:

<ul>
  <li>
    <auto-part>
      <serial-number>AQ12345</serial-number>
      <short-description>lorem ipsum dolor...</short-description>
      <list-price>14</list-price>
    </auto-part>
  </li>
</ul>

您无法获得比这更多的语义!

但是,有可能我走得太远了semantic-shangri-la-la(一个真实的地方),可能会想将其扩展到更通用的东西:

<ul>
  <li class='auto-part' data-serial-number="AQ12345">
      <p class='short-description'>lorem ipsum dolor...</p>
      <p class='list-price'>14</p>
  </li>
</ul>

或者也许是这样(如果我需要样式化并以视觉方式显示键)

<ul>
  <li class='auto-part'>
      <x-key>AQ12345<//x-key>
      <p class='short-description'>lorem ipsum dolor...</p>
      <p class='list-price'>14</p>
  </li>
</ul>

很有意思。下次需要配对时,我可能会调查一下。
Ryan Kinal

1

dt/dd声音最适合这一点,它能够在视觉上抵消他们,虽然我不同意它比对表更加困难。

至于源代码的可读性,如何将它们放在一行中呢?

<dl>
    <dt>Name</dt> <dd>Value</dd>
    <dt>Name</dt> <dd>Value</dd>
</dl>

我同意它不是100%完美的,但是请注意,您可以使用空格字符进行缩进:

<dl>
    <dt>Property with a looooooooooong name</dt>   <dd>Value</dd>
    <dt>Property with a shrt name</dt>             <dd>Value</dd>
</dl>

这可能是最好的方法。


问题在于,在规范中,一个dt可以有多个dd,可能是或可能不是期望的。
阿姆斯特朗

1

除了<dl>元素之外,您几乎总结了HTML的所有选项:有限的选项。

但是,您不会迷失方向,剩下一个选择:使用可以翻译为HTML的标记语言。Markdown是一个很好的选择。

使用某些markdown引擎提供的表扩展名,您可以具有如下代码:

| Table header 1 | Table header 2 |
-----------------------------------
| some key       | some value     |
| another key    | another value  |

这意味着您当然需要一个构建步骤才能将Markdown转换为HTML。

这样,您就可以获得有意义的标记(表格数据表)和可维护的代码。


1
因此,您再次得到一张桌子,但是要到达那里要做更多的工作。这似乎根本解决不了任何问题。
pydsigner '16

0

仅在每对之间放置一条空白行怎么样?

对于长值,这不需要特殊处理。

<dl> 
    <dt>Name</dt> 
    <dd>Value</dd> 

    <dt>Name</dt> 
    <dd>Value</dd> 

    <dt>Name</dt> 
    <dd>Value</dd> 
</dl> 

空格字符在HTML中没有任何语义含义。1个空格或多个空格,回车CRtab和换行符LF基本上全部转化为一个空间。对于阅读代码的人来说,它可能在视觉上更具吸引力,但它并没有赋予任何语义含义。
阿姆斯特朗(Armstrongest)

0

那使用列表呢?

订购:

<ol>
  <li title="key" value="index">value</li></ol>

<ul>用于无序列表,然后跳过该value="index"位。


0

spec中的行:

名称值组可以是术语和定义,元数据主题和值,问题和答案,或任何其他名称值数据组

我想使用的元素<dl><dt><dd>


2
感谢您链接到规范。是的,规范中确实允许使用名称/值对,但是由于dl每个key/value对都没有容器,因此该元素难以直观显示。它的最初用途可能是列出具有1个术语和多个定义的词汇表项或词典条目。
阿姆斯特朗

-1

我喜欢Unicron将它们全部放在一行上的想法,但是另一种选择是缩进定义名称下的值:

<dl>
    <dt>Name</dt>
       <dd>Value</dd>
    <dt>Name</dt>
       <dd>Value</dd>
</dl>

在可笑的长定义中,这种方式可能会更容易一些(尽管如果您使用的是错误的定义,那么定义列表毕竟不是您真正想要的)。

至于屏幕上的渲染,应用于dd的粗大底边留有足够的视觉分隔。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.