CSS 中的 行高 属性控制文本行之间的间距。它通常设置为无单位值(例如 line-height: 1.4;
),使其与字体大小成比例。它对于排版控制至关重要。太低会导致行之间挤在一起;太高会导致行之间过分分开。两者都会影响可读性。但您可能已经知道这一点。
在这篇文章中,我们将重点关注一些技巧。如果您知道(或能够计算出)line-height
的精确值,您可以做一些很棒的事情!
为每行文本设置不同的颜色
没有 ::nth-line()
,不幸的是。我们甚至不能可靠地使用 <span>
,因为有许多不同的因素会导致文本在不同的位置断开。
有一种方法,虽然是非标准的,但可以使用元素的背景作为文本的背景。
.text {
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
还有一个技巧,您可以使用 linear-gradient()
和颜色停止点,这样颜色不会渐变到另一种颜色,而是突然结束,另一种颜色开始。假设我们知道行高是 22px,我们可以使渐变断点正好位于该位置。
.text {
background-image: linear-gradient(
to bottom,
#9588DD,
#9588DD 22px,
#DD88C8 22px,
#DD88C8 44px,
#D3DD88 44px,
#D3DD88 66px,
#88B0DD 66px,
#88B0DD);
}

组合这两个技巧

在不支持文本背景剪裁的浏览器(如 Firefox)中,您将在文本后面看到实心的彩色条。也许这很酷,您喜欢它。也许您更愿意只回退到实心颜色文本。在这种情况下,您可以使用 @supports
仅在支持的情况下应用它。
此外,由于您会反复使用行高值,因此将其变量化可能很有用。我将在本文中使用 SCSS,但这将来使用真正的 CSS 变量会很酷,这样您甚至可以在渲染后更改它并观察它继续工作。
$lh: 1.4em;
body {
font-size: 1em;
line-height: $lh;
}
@supports (-webkit-background-clip: text) {
p {
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
to bottom,
#9588DD,
#9588DD $lh,
#DD88C8 $lh,
#DD88C8 $lh*2,
#D3DD88 $lh*2,
#D3DD88 $lh*3,
#88B0DD $lh*3,
#88B0DD);
}
}
在元素的顶部使用此行为最容易。下面是一个示例,其中前几行被修改以强调。
.text {
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
to bottom,
rgba(white, 0.8),
rgba(white, 0.8) $lh,
rgba(white, 0.6) $lh,
rgba(white, 0.6) $lh*2,
rgba(white, 0.4) $lh*2,
rgba(white, 0.4) $lh*3,
rgba(white, 0.2) $lh*3,
rgba(white, 0.2));
}

如果我们试图定位任意数量文本的最后几行,则会变得更加困难。在这种情况下,我们需要第一个彩色条从顶部延伸到一直到底部减去几行。幸运的是,我们可以使用 calc()
来做到这一点!
.text {
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
to bottom,
rgba(white, 0.8),
rgba(white, 0.8) calc(100% - 66px),
rgba(white, 0.6) calc(100% - 66px),
rgba(white, 0.6) calc(100% - 44px),
rgba(white, 0.4) calc(100% - 44px),
rgba(white, 0.4) calc(100% - 22px),
rgba(white, 0.2) calc(100% - 22px),
rgba(white, 0.2));
background-position: bottom center;
}

还有其他方法可以实现这种效果,例如叠加伪元素渐变(使用 pointer-events: none;
以免造成干扰)。
文本之间的线条
使用与上述实心颜色停止点技术类似的技术,我们可以创建一个 1px 线性渐变,该渐变以已知的 line-height
精确重复。最简单的方法是使用 repeating-linear-gradient()
,并确保所有其他元素都能很好地协同工作(例如基于行高的填充)。
.parent {
padding: $lh*2;
background: #082838;
background-image: repeating-linear-gradient(
to bottom,
rgba(white, 0) 0,
rgba(white, 0) $lh/1em*16px-1,
rgba(white, 0.1) $lh/1em*16px-1,
rgba(white, 0.1) $lh/1em*16px
);
}
为了获得 1px 线,我们需要知道 line-height
是多少像素,然后减去 1。目标是渐变以已知的行高精确重复,因此该空间中的最后一个像素可以是线。由于我们将正文字体大小保留为 1em,因此它为 16px。由于 line-height
以 ems 设置,我们可以除以 1em 删除单位,然后乘以 16px,并在需要时减去 1。

每行放置一张图片
如果您知道确切的 line-height
,还可以做的一件事是使 background-size
与其匹配,至少在垂直轴上。然后,您可以将其垂直重复,它将以每行一张图片的方式对齐。
.text
background-image: url(image.svg);
background-size: $lh $lh;
background-repeat: repeat-y;
padding-left: $lh*2;
}

演示
查看 CodePen 上 Chris Coyier (@chriscoyier) 的 一行文本不同的颜色。
我在构建代码块样式时使用了类似的技术。很棒的东西。
关于定位最后几行:为什么使用
calc()
而不是简单地将渐变方向更改为“从上到下”而不是“从下到上”?关于线条示例:这真的很乱,而没有必要如此。您可以只使用普通的线性渐变,颜色停止点设置为 1px,然后使用以 ems 为单位的
background-size
。永远不要以绝对长度指定行高。当某些粗心的开发人员更改字体大小而不更改行高时,它一定会出现严重问题。是的,Charlotte 指出这一点,从底部开始渐变要容易得多。
感谢您的文章,Chris!
-> 我可以获得任何解决此问题的变通方法示例吗?我知道行高与字体大小的关系。但是,我需要对第一句话进行一些澄清。
如果有人想知道为什么示例 1(多色)在 Safari 中不起作用,而示例 2(渐变到灰色)有效,那是因为示例 1 的 CSS 依赖于
@supports
(Safari 不支持)。我喜欢这种强调效果,我从未想到过它。我一定会在我接下来的几个项目中使用它 :)
底部的渐变不仅仅是反转渐变,它是在解决一个不同的问题,即文章中所述的:“试图定位任意数量文本的最后几行”。
很棒的技巧,而且感觉“好”——也就是说,没有滥用 CSS(虽然拥有
::nth-line()
来更明确地表达我们的意图会很棒)。但是,我应该指出,对于“带线条的纸张”效果,Blink 存在一个严重的错误,导致渐变以错误的比例呈现。关于此错误,有 多个错误报告,但据我所知,并没有得到重视。如果人们可以对其中几个进行投票,这可能会推动一些行动。Vox 真的很喜欢在所有东西上使用渐变,但最近我注意到他们的一些拉取引用在一些故事中使用了这种效果
http://charleston.eater.com/2015/1/27/7921157/after-28-years-in-business-crowds-still-line-up-for-hymans-seafood
如果浏览器以任何原因更改了缩放级别(我知道很多人都会这样做,因为在浏览器上设置缩放级别比在高分辨率屏幕上全局修复字体大小更容易),其中一些会以非常奇怪的方式失败。
整洁有趣的效果。淡出底部效果很棒,我之前认为无法通过 CSS 实现。在此之前,我们必须使用半透明 PNG 图像以及绝对位置和 Z-Index 来在文本框上创建这种效果。上面的示例很好地实践了如何创建这种效果。感谢您的分享。
这些真是很酷的技巧,但在我的 Nexus 5 上浏览这些时,其中几个会失效,尤其是在纵向模式下。
您不知道在各种媒体查询中线条将如何换行,这会非常显著地改变效果。因此,不要忘记在较小的设备上测试这些效果。