通过 CSS 来插入换行的需求在越来越多的场景中运用到,例如我们使用定义列表来呈现一行行的名值对,例如下面一段代码:
<dl> <dt>Name:</dt> <dd>John</dd> <dt>Email:</dt> <dd>John@qq.com</dd> <dt>Sex:</dt> <dd>male</dd> </dl>
我期望达到下面的效果:
我依次做了下面的尝试:
1. 在每一个 <dd> 后面添加了一个 <br> ,让他们换行,可效果却是这样的:
查找资料我明白了,<dd> 本来是块级元素,并且占有一定的外边距,它们默认情况下不能同占一行。
2. 我添加了一些样式:
dd { margin: 0; font-weight: bold; } dt, dd { display: inline; }
嗯,还不错,才进行两步就满足了我的要求,我效率也太高了吧。
——扯淡,写成这样还好意思说。(不仅仅污染了结构层的代码,而且在可维护方面也是一种糟糕的实践)
于是我想尝试一种不加入 <br> 这种额外的标签就能达到我想要的效果的方法。
一、添加生成内容
有一个 Unicode 字符是专门代表换行符的:0x000A。在 CSS 中可以使用 " 00A", 或者简化成 "A"。可以使用它来作为伪元素 ::after 的生成内容,把它添加到 <dd> 元素的后面:
dd::after { content: "A" ; }
不过,这段 CSS 代码想当于在 HTML 结构中的所有关闭标签 </dd> 之前添加换行符。添加的空白符会和其他相邻的空白符进行合并(我们输入很多空白符,只相当于输入了一个空白符!)。当然我们这里需要保留这些空白符和换行,可以用 white-space: pre; 。不过这里只针对伪元素生成的换行符设置这个样式。
二、对生成内容设置样式,保留源代码中的这些换行和空白符
dt, dd { display: inline; } dd { margin: 0; font-weight: bold; } dd::after { content: "A"; white-space: pre; }
至此我们完成了我们的需求,而不加任何 <br />。
可是这样的代码有这样的问题,如果我们某一个定义项有多个内容,即一个 <dl> 中有多个 <dd> ,具体到该项目中,该用户有两个邮箱:John@qq.com 和 John@126.com,那么我们得到的效果会是:
看起来 John@126.com 又是一个定义列表,且没有标题。
更改一、既然如此,我们可以将换行符加载 <dt> 前面,并且 <dt> 前面要有 <dd>:
dd + dt::before { content: "A"; white-space: pre; }
更改二、多个 <dd> 之间用 ", " 分割:
dd + dd::before { content: ", "; font-weight: normal; }
全部的代码:
dt, dd { display: inline; } dd { margin: 0; font-weight: bold; } dd + dt::before { content: "A"; white-space: pre; } dd + dd::before { content: ", "; font-weight: normal; }
扩展:以后 <hgroup> 里面有 <h2> , <h3> 等,并且 <h2> 和 <h3> 的宽度需要根据文本的长度进行调整,而不是 100%,那么就需要将其设置为 display: inline-block; 这样的情况下, <h2> 和 <h3> 之间需要插入换行符,便可以通过这种方式实现了。