转载

CSS秘密花园: 插入换行符

《 CSS Secrets 》是 @Lea Verou 最新著作,这本书讲解了有关于CSS中一些小秘密。是一本CSSer值得一读的一本书,经过一段时间的阅读,我、@南北和@彦子一起将在W3cplus发布一系列相关的读后感,与大家一起分享。

CSS秘密花园: 插入换行符

需要通过CSS插入换行符的情况,通常出现在list列表定义中,如下图所,

CSS秘密花园: 插入换行符

在其它的情况中也有。很多时候我们使用定义列表,是因为我们想要使用恰当的、语义标记,甚至当我们视觉上想要的只是几行 name/value 对,例如,看看下边的HTML:

<dl>     <dt>Name:</dt>     <dd>Lea Verou</dd>     <dt>Email:</dt>     <dd>lea@verou.me</dd>     <dt>Location:</dt>     <dd>Earth</dd> </dl> 

我们想要的视觉效果是类似上图这样的简单的样式。第一步通常是应用一些基础的CSS,如下:

dd {     margin: 0;     font-weight: bold; } 

但是,因为 <dt><dd> 是块元素,我们最终得到的是类似下图这样的效果:

CSS秘密花园: 插入换行符

namevalue 各占一行。下一步尝试通常是将 <dt><dd> 或两个一起的 display 属性的值改变,排版经常变得随意混乱,所以我们也变得有些绝望。但是,这样我们经常会得到这样的效果。

CSS秘密花园: 插入换行符

在我们开始发狂、埋怨CSS、或者是放弃转移注意力或者去修改我们的HTML,有什么办法能让我们保持理智并维持我们的代码整洁吗?

解决方案

基本上,我们要做的就是在每一个 <dd> 结束的地方添加换行符。如果我们不介意这些太表象的标签,我们可以直接用 <br> 元素来完成,如下:

<!-- If you do this, kittens die --> <dt>Name:</dt> <dd>Lea Verou<br /></dd> ... 

然后,我们分别为 <dt><dd> 应用 display:inline; ,这样就可以完成了。当然,这对于可维护性并不是一个好的习惯,而且还让我们的HTML标签变得臃肿。如果我们可以使用生成内容来添加换行,并且能够有像 <br> 元素这样的效果的,那么我们的问题就可以解决了!但是我们不能这样做,对吗?或许可以试试~?

事实上在Unicode中有一个转义字符是等同于换行的: 0x000A 。在CSS中,可以写成 "/000A" ,或更简单的 "/A" 。我们可以使用它作为我们的 ::after 伪元素的内容,这样在每个 <dd> 元素后边加上它,如下:

dd::after {     content: "/A"; } 

从技术上说, 0x000A 对应于“Line Feed”字符,也就是我们在JavaScript中使用的 /n 。还有一个“Carriage Return”字符(在js中是" /r ",在CSS中是" /D "),但是这在现代浏览器中并不需要。

这看起来似乎是可行的,但是如果我们尝试了,结果却是令人失望的:和上图显示的结果并没有什么区别。但是这并不意味着我们的方向错了;我们只是忘了一些东西。我们可以在CSS中完成的,和在HTML标签中添加换行符是一样的,就是在结束标签 </dd> 之前添加。还记得如果在HTML代码中添加换行符会发生什么吗?默认情况下,它们会随着我们空白的多余部分塌下去。这通常是一个很棒的事情,否则我们就需要把我们的整个HTML页面设置格式为一行了!但是,有时候我们想要保留空格和换行,如在代码块中。记得在这种情况下我们通常是怎么做的吗?应用 white-space: pre; 。这里同样适用,仅应用它来产生换行符。

我们现在只有一个换行符,所以我们不需要关心空格是否会被保留(因为没有空格),所以任何的 pre 值都会生效( pre , pre-line , pre-wrap )。我推荐 pre ,因为它有广泛的浏览器支持。我们来把它们放到一起:

dt, dd { display: inline; } dd {     margin: 0;     font-weight: bold; } dd::after {     content: "/A";     white-space: pre; } 

如果你测试过了,你会看到它是可行的,而且和下图的结果完全一样!

CSS秘密花园: 插入换行符

但是,这个东西灵活吗?假设我们想要为我们定义列表中的用户添加第二个电子邮件,如下所示:

... <dt>Email:</dt> <dd>lea@verou.me</dd> <dd>leaverou@mit.edu</dd> ... 

现在结果如下所示,并不太美观。

CSS秘密花园: 插入换行符

因为我们在每一个 <dd> 后边都添加了换行符,每个值都是在单行上显示的,即使有些内容并不需要换行。多个值的话用逗号分隔会比较好,并且放在同一行上(只要有足够的空间)。

理想情况下,我们希望针对最后一个 <dd> ,在 <dt> 之前的,只针对它添加换行,而不是所有的 <dd> 后边都添加换行。但是,就CSS选择器当前的状态来看,这是不可能的,因为它们不可以在DOM树中直接找到那个元素。我们需要想另一个方法。一个想法是尝试在 <dt> 之前添加换行,而不是在 <dd> 之后。

dt::before {     content: '/A';     white-space: pre; } 

但是,这会导致第一行是空白的,因为选择器也会应用在第一个 <dt> 上。为了解决这种情况,我们可以尝试使用任何如下的选择器,而不仅是 dt

  • dt:not(:first-child)
  • dt ~ dt
  • dd + dt

我们使用最后一个选择器,因为它在多个 <dt> 有相同的值时也可以,不像前面两个选择器在这种情况下会出错。我们还要想办法把多个 <dd> 分开,除非这多个值已经使用空格分隔了(这在某些情况下是没有问题的,但不是所有情况都是这样)。理想情况下,我们希望能够告诉浏览器“在前边还有 <dd> 标签的每个 <dd> 标签之前添加一个逗号(也就是说除了第一个 <dd> 标签,其它的 <dd> 标签都在前面添加一个逗号)”,但是同样,对于今天的CSS选择器是不可能的。所以,我们必须在每个 <dd> 前添加逗号。这是我们最终的CSS:

dd + dt::before {     content: '/A';     white-space: pre; } dd + dd::before {     content: ', ';     font-weight: normal; } 

效果如下:

CSS秘密花园: 插入换行符

记住,如果你的HTML标签中,多个连续的 <dd> 之间包含(未注释掉的)空格,逗号之前都会有空格。有很多方法可以解决这个问题,但是都不是完美的。例如,负外边距:

dd + dd::before {     content: ', ';     margin-left: -.25em;     font-weight: normal; } 

这是可行的,但是相当站不住脚。如果你的内容显示的是不同的字体,带有不同的度量,空格可能会比 0.25em 大一些或小一点,这样结果看起来可能就有点过。但是,对于大多数的字体,它们的差异是可以忽略不计的。

原文  http://www.w3cplus.com/css3/css-secrets/inserting-line-breaks.html
正文到此结束
Loading...