《CSS揭秘》第5章-字体排印

连字符断行

hyphens

难题

设计师迷恋文本的两端对齐效果。不过在网页中,两端对齐却极少使用。因为在对文本进行两端
对齐处理时,需要调整单词的间距,此时会出现“单词孤岛”现象。这个结果不仅看起来很糟糕,而且损伤了可读性。

以前,有一些在网页上实现连字符断行的方法,但这类方法完全是“伤敌八百,自损一千” 。常见的方法包括服务器端预处理、JavaScript后期处理、用在线生成器单独处理,甚至还有开发者耐着性子在单词中纯手工插入软连字符(­)。

解决方案

CSS 文本(第三版)引入了一个新的属性hyphens。它接受三个值:none、manual 和 auto。
manual 是它的初始值,需要人工插入软连字符(­);
none 会禁用这种行为;
auto会自动断行

1
huphens: auto;


如果需要更细粒度地控制连字符的行为(比如在简短的引文中),你仍然可以通过一些软连字符(­)来辅助浏览器进行断词。hyphens属性会优先处理它们,然后再去计算其他可以断词的地方。

插入换行

伪元素、white-space

难题

通过CSS来插入换行的需求通常与定义列表有关,但有时也涉及其他场景。在通常情况下,采用定义列表是标签语义化。
举例来说,考虑下面这段结构代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//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>都是块级元素,我们最终得到的往往是下图,所有的名和值均独占一行

解决方案

基本上,我们需要做的只是在每个<dd>后面添加一个换行。如果不在乎使用表现型的结构标记,可以请出老套的<br>元素,比如这样:

1
2
3
4
5
<!-- 如果你这样写,天崩地裂万劫不复 --> 
<dt>Name:</dt>
<dd>Lea Verou<br /></dd>
...
dt,dd{display:inline;}

这种方法不仅在可维护性方面是一种糟糕的实践,而且污染了结构层的代码。
只要能使用生成性内容来添加换行,并以此取代<br>元素,那么问题就可以解决了!
实际上,有一个Unicode字符是专门代表换行符的:0x000A。在CSS中,这个字符可以写作”\000A”,或简化为”\A”。我们可以用它来作为::after伪元素的内容,并将其添加到每个<dd>元素的尾部

1
2
3
dd::after { 
content: "\A";
}

这样做还是不行,默认情况下(块级元素前后自带换行符),这些换行符会与相邻的其他空白符进行合并。
我们希望保留源代码中的这些空白符和换行,会用到white-space: pre

1
2
3
4
5
6
7
8
9
10
11
dt, dd { display: inline; } 

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

dd::after {
content: "\A";
white-space: pre;
}

文本行的斑马条纹

CSS 渐变,background-size,“条纹背景”,“灵活的背景定位”

难题

我们最常用:nth-child()/:nth-of-type()来解决的一个需求就是表格的“斑马条纹”。
当我们想把表格行的这种效果应用到文本行时,仍然有些力不从心。

解决方案

我们可以在CSS 中用渐变直接生成背景图像,而且可以用em单位来设定背景尺寸,这样背景就可以自动适应font-size 的变化了。

1
2
3
4
5
padding:.5em;
line-height:1.5em;
background:beige;
background-image:linear-gradient(rgba(0,0,0,.2) 50%,transparent 0);
background-size:auto 3em;


这里有一个严肃的小问题不可忽视:代码行和条纹是错位的,破坏了整体效果。这是怎么回事?
第一条条纹是从容器的最顶部开始的,这是背景图像最平常的表现。不过,我们的代码并不是
从那里开始的,因为那样排版会显得很局促。如你所见,我们对容器应用了.5em 的内边距,这个距离正是这些条纹与理想位置之间的偏差。

background-origin这个属性正是我们所需要的:它可以告诉浏览器在解析background-position时以content box的外沿作为基准,而不是默认的padding box外沿。

1
2
3
4
5
6
7
padding: .5em; 
line-height: 1.5;
background: beige;
background-size: auto 3em;
background-origin: content-box;
background-image: linear-gradient(rgba(0,0,0,.2) 50%,
transparent 0);

调整Tab的宽度

tab-size

难题

包含大量代码的网页(比如文档或教程)在样式上面对着无法回避的挑战。我们通常使用<pre><code>元素来显示代码,人们在网页中却常常有意避开tab。这是因为浏览器会把其宽度显示为 8 个字符!

解决方案

在CSS3中,一个新的CSS属性tab-size可以控制这个情况。这个属性接受一个数字(表示字符数)或者一个长度值(这个不那么实用)。我们通常希望把它设置为4(表示 4 个字符的宽度)或
2。

1
2
3
pre{
tab-size:2;
}

连字

暂时看不出对中文语境的影响

华丽的&符号

麻烦而用处不大

自定义下划线

CSS渐变、background-sizetext-shadow、“条纹背景”

难题

尽管默认样式text-decoration很实用,但往往太过扎眼,更不要提在不同浏览器下的渲染效果大相径庭。
尽管用border-bottom模拟出来的文本下划线给予了我们对颜色、线宽、线型的控制能力,但它并不完美,这些“下划线”跟文本之间的空隙很大,位置甚至比字形的降部(descender)还
要低,并且也会阻止正常的文本换行行为。box-shadow和其有一样的缺点。

解决方案

最佳方案来自于background-image及其相关属性。

1
2
3
background:linear-gradient(gray,gray) no-repeat;
background-size:100% 1px;
background-position:0 1.02em;

请注意下划线会穿过某些字母(比如p和y)的降部。如果下划线在遇到字母时会自动断开避让,那效果看起来岂不是更好?
假如背景是一片实色,就可以设置两层与背景色相同的text-shadow来模拟这种效果。

1
2
3
4
background:linear-gradient(gray,gray) no-repeat;
background-size:100% 1px;
background-position:0 1.02em;
text-shadow:.05em 0 white,-.05em 0 white;

使用渐变来实现下划线的高明之处在于,这些线条极为灵活。举例来说,如果要生成一条虚线下划线

1
2
3
4
background:linear-gradient(90deg,gray 66%,transparent 0) repeat-x;
background-size:.2em 2px;
background-position:0 1em;
text-shadow:.05em 0 white,-.05em 0 white;

下面是我自己的曲线版

1
2
3
4
5
background:linear-gradient(45deg,transparent 45%,gray 0,gray 55%,transparent 0) repeat-x,
linear-gradient(-45deg,transparent 45%,gray 0,gray 55%,transparent 0) repeat-x;
background-size: 8px 6px;
background-position: 0 .95em,4px .95em;
text-shadow: .05em 0 white, -.05em 0 white;

下面的官方版:

1
2
3
4
5
background: linear-gradient(-45deg, transparent 40%, red 0, red 60%, transparent 0) 0 1em,
linear-gradient(45deg, transparent 40%, red 0, red 60%, transparent 0) .1em 1em;
background-repeat: repeat-x;
background-size: .2em .1em;
text-shadow: .05em 0 white, -.05em 0 white;

现实中的文字效果

基本的text-shadow

难题

在网页中,对文字进行艺术加工已经变得非常普遍了,比如凸版印刷效果,当鼠标悬停时的模糊效果,浮雕(伪3D)效果

凸版印刷效果

这种效果尤其适用于中等亮度背景配上深色文字的场景;但它也可用于深色底、浅色字的场景,只要文字不是黑色并且背景不是纯黑或纯白就行。

浅底深字

当我们在浅色背景上使用深色文字时,在底部加上浅色投影通常效果最佳。到底要多浅,取决于你用的是什么颜色,以及你期望最终效果有多明显,因此需要反复尝试其透明度以达到满意效果。我们最终敲定为 80% 不透明度的白色

1
2
3
background: hsl(210, 13%, 60%); 
color: hsl(210, 13%, 30%);
text-shadow: 0 1px 1px hsla(0,0%,100%,.8);

深底浅字

给文字顶部加深色投影是最佳方案

1
2
3
background: hsl(210, 13%, 40%);  
color: hsl(210, 13%, 75%);
text-shadow: 0 -1px 1px black;

空心字效果

流传最广的方法就是使用多个text-shadow,分别为这些投影加上不同方向的少量偏移,就像这样

1
2
3
background:deepink;
color:white;
text-shadow:1px 1px black,-1px -1px black,1px -1px black,-1px 1px black;

文字外发光效果

在某些类型的网站中,文字外发光效果常用于凸显标题,或给链接添加鼠标悬停效果。
这种方法有一个最简单的版本:
你只需要准备几层重叠的text-shadow即可,不需要考虑偏移量,颜色也只需跟文字保持一致。

1
2
3
4
5
6
7
8
9
a{
background:#203;
color:white;
transition:1s;
}

a:hover{
text-shadow:0 0 .1em,0 0 .3em;
}

这个效果还可以做得更炫。如果你在:hover状态下把文字本身隐藏掉,那它看起来真的就像在慢慢变模糊。

1
2
3
4
5
6
7
8
9
10
a{
background:#203;
color:white;
transition:1s;
}

a:hover{
color:transparent;
text-shadow:0 0 .1em white,0 0 .3em white;
}

不过你要牢记一点,依赖text-shadow来实现文字显示的做法无法实现平稳退化:如果浏览器不支持text-shadow,那就什么字也看不见了。

1
2
3
4
5
6
7
8
a{
background:#203;
color:white;
transition:1s;
}
a:hover{
filter:blur(.1em);
}

文字凸起效果

text-shadow

难题

另一种在拟物化风格的网站中流行的效果是文字凸起(伪3D)效果。
这其中的主要思路就是:
使用一长串累加的投影,不设模糊并以1px 的跨度逐渐错开,使颜色逐渐变暗,然后在底部加一层强
烈模糊的暗投影,从而模拟完整的立体效果。

1
2
3
4
5
6
7
8
background: #58a; 
color: white;
text-shadow: 0 1px hsl(0,0%,85%),
0 2px hsl(0,0%,80%),
0 3px hsl(0,0%,75%),
0 4px hsl(0,0%,70%),
0 5px hsl(0,0%,65%);
0 5px 10px black;

这种繁琐冗长的代码正是 CSS 预处理器的 mixin 功能所要解决的问题。我们在SCSS 中可以这样来做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@mixin text-3d($color: white, $depth: 5) { 
$shadows: ();
$shadow-color: $color;

@for $i from 1 through $depth {
$shadow-color: darken($shadow-color, 10%);
$shadows: append($shadows,
0 ($i * 1px) $shadow-color, comma);
}

color: $color;
text-shadow: append($shadows,
0 ($depth * 1px) 10px black, comma);
}

h1 { @include text-3d(#eee, 4); }

这种效果还有很多变种。比如把所有的投影都设成黑色,并且去掉最底层的投影,就可以模拟出一种在复古标志牌中常见的文字效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
color: white; 
background: hsl(0,50%,45%);
text-shadow: 1px 1px black, 2px 2px black,
3px 3px black, 4px 4px black,
5px 5px black, 6px 6px black,
7px 7px black, 8px 8px black;

//转化成SCSS更合适
@function text-retro($color: black, $depth: 8) {
$shadows: (1px 1px $color,);

@for $i from 2 through $depth {
$shadows: append($shadows,
($i*1px) ($i*1px) $color, comma);
}

@return $shadows;
}

h1 {
color: white;
background: hsl(0,50%,45%);
text-shadow: text-retro();
}

环形文字

基本的SVG

liborn wechat
欢迎您扫一扫上面的微信二维码,订阅我的公众号!