TanXinNiao / blog

贪心鸟的博客
0 stars 0 forks source link

CSS权威指南(第4版)第六章 文本属性 #16

Open TanXinNiao opened 3 years ago

TanXinNiao commented 3 years ago

是的,很多Web设计都要选择适当的颜色,让页面具有最酷的外观,不过在设计的过程中, 可能更多的时间是花在思考文本的位置和外观上的。针对这一需求,早期的HTML出现 了 <FONT>和<CENTER>等标签,对文本的外观和位置提供一定程度的控制。

文本是网页的重要元素,因此CSS提供了很多相关的属性,以不同的方式控制文本。那么, 文本和字体之间有什么区别呢?简单而言,文本是内容,而字体是用于显示内容的。借 助文本属性,可以影响文本相对一行中其他内容的位置,可以把文本设为上标,可以为 文本添加下划线,可以改变文本的大小写,甚至还能在一定程度上模拟打字机的Tab键。

TanXinNiao commented 3 years ago

缩进和行内对齐

缩进文本

text-indent属性把元素的第一行文本缩进指定的长度,缩进的长度可以是负值。这个 属性通常用于缩进段落的第一行: p {text-indent: 3em;} 这个规则把段落的第一行缩进3 em

text-indent属性可以用在任何块级元素上,缩进将沿着行内方向展开。text-indent属 性不能用于行内元素或置换元素(如图像)。然而,如果图像在块级元素的第一行里, 它将随行中的其他文本一起后移。

TanXinNiao commented 3 years ago

文本对齐

text-align比text-indent还基础,它控制元素中各文本行的对齐方式。 text-align 取值 start | end | left | right | center | justify | match-parent | start end text-align只能用于块级元素(如 段落),因此,无法让锚记独立于行中的其他内容而居中显示

对齐最后一行

有时,你可能想使用不同于其他内容的方式对齐元素的最后一行。例如,在两端对齐 的文本块中,可能想左对齐最后一行,或者把左对齐换成居中对齐。此时,可以使用 text-align-last 属性。 text-align-last 取值 auto | start | end | left | right | center | justify

元素的最后一行与其他内容的对齐方式不同,具体如何对齐由text - align-last属性决定。

你会发现,除了块级元素的最后一行之外,还有其他行也受这个属性影响。 其实,只要一行后面有强制换行,不管是不是在元素的末尾,都受text-align-last属 性的控制。因此,如果换行是由
标签导致的,那么前面那一行的对齐方式将使用 text-align-last的值。当然,块级元素的最后一行也受这个属性控制,因为此处的换 行是由元素的结尾导致的。

text-align-last有个有趣的现象:如果元素的第一行也是最后一行,text-align-last 的优先级比text-align高。因此,下述样式将把段落居中对齐,而不是靠起边对齐:

p (text-align: start; text-align-last: center;)
<p>A paragraph.</p>
TanXinNiao commented 3 years ago

块级对齐

行的高度

line-height属性指行的基线之间的距离,与字号无关,决定着元素所在方框的高度是 增还是减。很多时候,我们都以为通过line・height能增加(或减少)行之间的纵向空间。 这其实是一种误解,没有完全理解line-height的工作方式。line-height控制的是行 距(leading),是除字体高度之外在文本行上方的额外空间。也就是说,line-height 的值与字体高度之差就是行距。

对块级元素而言,line-height定义元素中文本行基线之间的最小距离。注意,定义的 是最小距离,不是定死的值,基线之间的距离可能比1 ine-height的值大。line-height 不影响置换元素的布局,但是依然应用到置换元素上。

行的构成 文本行中的每个元素构成一个内容区(content area),其高度由字体的高度决定。随内 容区出现的是一个行内框(inline box),如果不考虑其他因素,其高度与内容区完全相等。 line-height导致的行距是影响行内框高度的因素之一。

元素的行距等于font-size的计算结果减去line-height的计算结果。这个值是行距的 总值。注意,行距可能为负数。行距分为两半,分别放到内容区的上部和下部。算上行距, 得到的就是元素的行内框。

举个例子。假设font-size是14像素(因此内容区也是这么高),line-height的计算 结果为18像素。二者之差(4像素)分成两半,分别放到内容区的上部和下部。因此, 行内框的高度为18像素,内容区上部和下部分别多出2像素。看起来用这种方法描述 line-height的工作方式好像绕了弯子,不过是有充分理由的。

确定一行内容的全部行内框之后,行框也就确定了。行框恰好包围最高那个行内框的顶 端和最低那个行内框的底端。

行高的继承 块级元素之间继承的行高有点复杂。从父元素继承line-height值时,根据父元素的字 号计算,而不根据子元素计算。

body (font-size: 10px;}
div (line-height: lem;) /♦计算结果为 10px */
p (font-size: 18px;}
<div>
<p>This paragraph's 'font-size' is 18px> but the inherited 'line-height'
value is only lOpx. This may cause the lines of text to overlap each other by a small amount.</p>
</div>

行高太小的问题,一种解决方法是为每个元素设定line.height, 但是这样做不太灵活。更好的方法是使用纯数字,即设定一个换算系数:

body (font-size: 10px;) div {line-height: 1;} p (font-size: 18px;}

使用纯数字时,继承的将是设定的换算系数,而不是计算得到的值。纯数字将应用到当 前元素及其所有子元素上,因此各元素的行高将根据自身的字号计算

TanXinNiao commented 3 years ago

纵向对齐文本

如果用过sup和sub (上标和下标)元素,或者用过<img src=Hfoo.gifn align="middlen> 这样的标记,那么你就用过一些基本的纵向对齐方式。CSS中的vertical-align属性 只能用于行内元素和置换元素(例如图像和表单输入框)。vertical-align属性不继承。

取值 baseline | sub | super | top | text-top | middle | bottom | text-bottom | 初始值 baseline

注意,vertical-align不影响块级元素中文本的对齐方式。不过,vertical-align 可以控制单元格中元素的纵向对齐方式。

基线对齐 vertical-align: baseline强制元素的基线与父元素的基线对齐。多数时候,浏览器都 是这么做的,因为正常情况下一行中所有文本元素的底端应该对齐。 如果目标元素没有基线,例如图像、表单输入框或其他置换元素,元素的底端与父元素 的基线对齐

img {vertical-align: baseline;}
<p>The image found in this paragraph <img src="dot.gif" alt="A dot" /> has its
bottom edge aligned with the baseline of the text in the paragraph,</p>

这个规则很重要,一些Web浏览器始终把置换元素的底边放在基线上,即便行中没有其 他文本也是如此。举个例子。假如一个单元格中只有一个图像,那个图像会放在基线上3 然而在某些浏览器中,基线下方有一点空间,从而导致图像下方出现间隙;其他浏览器 把图像紧贴着单元格的边界放置,因此没有间隙。有间隙是对的,不过多数创作人员不 在乎。 上标和下标 vertical-align: sub把元素放在下标处,即元素的基线(对置换元素来说是底边线) 低于父元素的基线。规范没有定义下沉的距离,因此在不同用户代理中可能不同。

super的作用与sub相反,让元素的基线(或置换元素的底边线)高于父元素的基线。同样, 高出多少距离由用户代理决定。 注意,sub和super不改变元素的字号,因此下标和上标中的文本不会变小(或变大)。 下标和上标中的文本默认情况下与父元素的字号相等

span.raise {vertical-align: super;}
span.lower {vertical-align: sub;}
<p>This paragraph contains <span class="raise">superscripted</span>
and <span class="lower">subscripted</span> text.</P>

底端对齐 vertical-align: bottom把元素所在行内框的底边与行框的底边对齐。

中线对齐 middle这个值通常(不是始终)用在图像上。它的作用与字面意思不完全一样。middle 把行内元素所在方框的中线与父元素基线向上偏移0.5ex处的线对齐(lex等于父元素 的font-size)

多数用户代理把lex视作半个em,因此middle通常把元素的纵向中点与父元素基线向 上偏移1/4 em处的点对齐。但这不是规范定义的距离,所以在不同的浏览器中向上偏移 的量可能不同

百分数 百分数不能像align="middle“那样对齐图像。把vertical-align的值设为百分数,效 果是把元素的基线(或置换元素的底边)相对父元素的基线抬升或下沉指定的量(指定 的百分数相对元素自身而非父元素的1 ine-height计算)。正百分数抬升元素,负百 分数下沉元素。如果抬升或下沉的量足够大,目标元素可能会出现在相邻的行上,因此使用百分数时要小心。

<div style="font-size: 14px; line-height: 18px;">
I felt that, if nothing else, I deserved a
<span style="vertical-align: 50%;">raise</span> for my efforts.
</div>

span元素的vertical-align值为50%,即抬升9像素,这是span元素继承的行高(18px) 的一半。注意,抬升的值不是font-size的一半,即不是7像素。

长度值 最后,分析设为长度值时的纵向对齐方式。此时,vertical-align的效果很简单:把元 素抬升或下沉声明的距离。因此,vertical-align: 5px;把元素从原位置向上抬升5像 素。长度值为负时,下沉元素。这种简单的对齐方式在CSS1中没有,是在CSS2中增加的。

注意,纵向抬升或下沉的文本不会变成其他行的一部分,也不会与其他行中的文本重叠。

可以看出,纵向对齐的元素可能影响行的高度。还记得吗,行框恰好包围最高那个行内 框的顶端和最低那个行内框的底端。这包括因纵向对齐而抬升或下沉的行内框。

TanXinNiao commented 3 years ago

单词间距和字符间距

讲完行内元素的纵向对齐方式之后,回到行内方向,说明单词间距和字符间距。与之前 一样,这些属性也有一些异于直觉的行为。

单词间距

word-spacing属性的值为长度,可正可负。指定的长度值追加到单词的标准间距上。其 实,word-spacing属性用于修改单词之间的距离。因此,默认值normal等同于把值设 为零(0)。

字符间距

word-spacing属性的很多问题在letter-spacing属性上也有体现。这两个属性之间唯 一的区别是,letter-spacing属性修改的是字符或字母之间的距离。

对齐方式对间距的影响

word-spacing的值可能会受text-align的值影响。如果元素是两端对齐的,为了让 文本占满整行的宽度,可能要调整字符和单词之间的距离。鉴于此,创作人员声明的 word-spacing值可能也要被调整。如果letter-spacing的值是长度,不受text-align 的影响;但是,如果letter-spacing的值是normal,为了使文本两端对齐,可能要修 改字符之间的距离。CSS未指明如何调整距离,因此用户代理可以采用自认为恰当的算 法。

TanXinNiao commented 3 years ago

文本转换

text-transform 取值 uppercase | lowercase | capitalize | none

默认值none不对文本做任何修改,大小写形式与源文档一样。uppercase和lowercase 的作用与字面意思一样,分别把文本转换成大写和小写字母。最后一个值capitalize 只把各单词的首字母变成大写

TanXinNiao commented 3 years ago

文本装饰

text-decoration 取值 none | [underline || overline || line-through || blink ]

你可能猜到了,underline为元素添加下划线,就像旧时HTML中的U元素一样。 overline的作用相反,在文本的上方绘制一条线。line-through绘制一条贯穿文本中部的线,这也叫删除线,等价于HTML中的S和strike元素。blink让文本一闪一闪, 类似于Netscape中备受非议的blink标签。

怪异的装饰

下面来看text-decoration不寻常的一面。第一个奇怪的行为是,text-decoration不 被继承。这表明,任何装饰线(下划线、上划线或贯穿线)的颜色都与父元素的文本颜 色一样。即便后代元素的颜色变了,也是如此。

p {text-decoration: underline; color: black;}
strong (color: gray;}
<p>This paragraph^ which is black and has a black underline, also contains <strong>strongly emphasized text</strong> which has the black underline beneath it as well.</p>

那么为什么会这样呢?因为text-decoration的值不被继承,strong元素假定使用默认 值none。因此,strong元素没有下划线。可是,strong元素下面明显有一条线,说没 有下划线不是信口开河吗?真的,确实没有。strong元素下面那条线其实是段落的下划 线,只是恰好“跨过” T strong元素。像下面这样调整加粗元素的样式看得更清楚:

p (text-decoration: underline; color: black;}
strong {color: gray; text-decoration: none;}
<p>This paragraph, which is black and has a black underline, also contains
<strong>strongly emphasized text</strong> which has the black underline beneath it as well.</p>

这样修改之后,得到的结果与图6-30是完全一样的,因为现在你是显式声明strong元 素没有装饰线。这表明,应用到父元素上的下划线(抑或上划线或贯穿线)在子元素上 是无法取消的。

text-decoration和vertical-align同时使用时还会发生更奇怪的事情。图6-31是其 中一种怪异行为。尽管sup元素自身没有装饰线,但是它身在一个有上划线的元素中, 导致那条线穿过sup元素

p (text-decoration: overline; font-size: 12pt;}
sup (vertical-align: 50%; font-size: 12pt;}

看到这些问题,你可能会发誓再也不用文本装饰线了。实际上,我只是指出了最为简单 的一些情况,这里只是根据规范说明可能出现的结果。现实中,有些Web浏览器会去掉 子元素的下划线,尽管这样做是不对的。

TanXinNiao commented 3 years ago

文本渲染效果

text-rendering是CSS最近新增的属性,它其实是一个SVG属性,支持它的用户代理 不会把它视作CSS属性。这个属性的作用是让创作人员指定用户代理在显示文本时应该 优先考虑什么方面。 取值 auto | optimizeSpeed | optimizeLegibility | geometricPrecision

optimizeSpeed和optimizeLegibility的作用基本无需过多解释,它们指明首先考 虑绘制速度,而不是清晰性特性,如紧排和连字(optimizeSpeed),或者反过来 (optimizeLegibility)。 optimizeLegibility针对的清晰性特性没有明确定义,而且文本渲染效果通常取决于运 行用户代理的操作系统,因此具体结果视情况而定。

geometricPrecision的作用不太明显,它其实是让用户代理尽量精准地绘制文本,确保 能无损缩放。别以为情况始终是这样,现实并非如此。比如说,有些字体会随着字号的 变化而改变紧排或连字效果,在字号小时提供较大的字距,字号变大之后又紧缩字距。 使用geometricPrecision可以让用户代理忽略随字号增减而出现的这些变化。如果不理 解的话,可以这样想:geometricPrecision的作用相当于让用户代理把文本绘制成一系 列SVG路径,而不是字形。

TanXinNiao commented 3 years ago

处理空白

我们介绍了装饰文本的不同方式,下面讨论white-space属性,它影响用户代理对文档 源码中空格、换行符和制表符的处理方式。 white-space 取值 normal | nowrap | pre | pre-wrap | pre-line

这个属性影响浏览器对待单词之间及文本行之间空白的方式。XHTML在某种程度上已 经做了处理,即把空白压缩成一个空格。因此,对下述标记来说,经Web浏览器渲染后, 各单词之间只有一个空格,而且会忽略元素中的换行。 <p>This paragraph has many spaces in it.</p> 这种默认的行为可以使用下述声明显式设定: p (white-space: normal;} 这个规则让浏览器采用当前的方式处理空白,即丢掉多余的空白。这种情况下,换行符(回 车)变成空白,而且连续的多个空格变成一个空格。 然而,我们可以把white-space设为pre,这样目标元素中的空白将像XHTML pre元 素那样处理,空白不会被忽略

p (white-space: pre;}
<p>This paragraph has many spaces in it.</p>

设为pre时,浏览器会小心处理额外的空格以及回车。任何元素在这一面,而且仅在这 一方面,可以变得像pre元素那样。

与之相反的值nowrap,禁止元素中的文本换行,除非使用的是br元素。CSS中的 nowrap,与HTML 4中使用设定单元格内容不换行差不多,只不过nowrap 值可以用在任何元素上。

           空白 | 换行符 | 自动换行

pre-line | 折叠 | 保留 | 允许 normal | 折叠 | 忽略 | 允许 nowrap | 折叠 | 忽略 | 禁止

设定制表符的宽度 既然white-space取某些值时空白会保留下来,那么制表符(即Unicode码位0009)也 就将显示成制表符了。但是一个制表符等于多少个空格呢?这就要问tab-size属性了

默认情况下,一个制表符相当于八个连续的空格。不过,可以使用tab-size属性设为 其他整数值。例如,tab-size: 4将把一个制表符渲染成四个连续空格。 如果提供的是长度值,那么制表符将渲染成指定的长度。例如,tab-size: 10px将把三 个连续的制表符渲染成30像素宽的空白。

注意,如果white-space的值导致空白被折叠了(见表6-1),那么tab-size就不再起 作用。此时,tab-size的值还要计算,但是不管源码中有多少制表符,在视觉上都没有 体现。

TanXinNiao commented 3 years ago

换行和断字

遇到单词较长,而行的长度较短时,最好加上连字符,例如移动设备中的博客文章和《经 济学人》的一栏。创作人员可以自己动手插入断字提示(使用Unicode字符U+00AD SOFT HYPHEN,或者HTML中的­),但是借助CSS,无需改动文档就能自动断字。

hyphens 取值 manual | auto | none 初始值 manual

使用默认值manual时,只在文档中手动插入的连字符(例如U+OOAD或­)处断字; 否则,不断字。而使用none值时,即使有手动插入的连字符,也不断字,即,U+00AD 和­将被忽略。

auto值有趣多了(行为也不太一致),即使没有手动插入连字符,浏览器也会在单词中 “合适的”位置断字,把单词分开。这就带来了一些有趣的问题,比如怎样定义“单词”, 以及何为断字的“合适”位置。其实,这两个问题完全由所用的语言决定。用户代理应 该优先在手动插入的连字符处断字,但情况并非总是如此。

此外,如果选择断字,要谨慎选择在什么元素上断字。hyphens属性能被继承

body {hyphens: auto;}声明将在文档中的所有元素上应用断字,包括多行文本输入框、 代码示例、引用块等。这些元素最好通过类似下面的规则禁止自动断字:

body {hyphens: auto;}
code, var, kbd, samp, tt, dir, listing, plaintext, xmp, abbr, acronym, blockquote, q, textarea, input, option {hyphens: manual;}

代码示例和代码块禁止断字的原因应该很明显,尤其是那些使用连字符表示属性和值名 称的语言。通过键盘输入的文本也是如此,你肯定不希望UNIX命令行示例中出现误导 人的连字符。类似的情况还有很多。如果确实想在某些元素中断字,从选择符中把它们 删掉即可(在多行文本输入框中输入的过程中自动断字看起来还是不错的)

断字还受其他属性的影响,例如word-break这个属性的作用是控制不同语言处理文本 软换行的方式。 取值 normal | break-all | keep-all

如果一串文本太长,一行里放不下,就会软换行。这个概念与换行符和<br>元素导致 的硬换行是相对的。文本在何处软换行由用户代理(或操作系统)决定,但是创作人员 可以使用word-break属性影响这一决定。

默认值normal的意思是,按正常方式换行。通俗易懂地说,就是文本在单词之间换行, 不过不同语言中“单词”的定义有所不同。

再次说明,这是浏览器处理文本的默认方式,已经沿用了数年。如果使用break-all, 软换行可能(也会)出现在任何字符之间,即使是在一个词的内部。使用这个值时,连 字符不显示,即使换行出现在断字的位置(参见前文对hyphens属性的说明)。注意, line-break属性(参见下文)可能会影响CJK文本应用break-all的行为。

keep-all禁止在字符之间软换行,即便对一个符号一个词的CJK语言来说也是如此。 因此,在日语中,没有空白的字符序列不会出现软换行,即便这样可能导致文本行超出 所在元素的长度(这个行为类似于white-space: pre) 值 | 非CJK | CJK | 是否断字’ normal | 照常 | 照常 | 是 break-all | 任何字符之后 | 任何字符之后 | 否 keep-all | 照常 | 序列两侧 | 是

TanXinNiao commented 3 years ago

如果你关注的是CJK文本,除了 word-break属性之外,可能还想了解line-break属性。 line-break 取值 auto | loose | normal | strict 我们知道,word-break属性可以影响CJK文本行的软换行方式。line-break属性也能 影响这种软换行,尤其是如何处理CJK符号两侧的换行,以及CJK文本中非CJK标点 符号(例如感叹号、连字符和省略号)两侧的换行方式。

默认值auto指示用户代理按正常行为软换行,而更为重要的是,让用户代理根据情况 变更换行方式。例如,用户代理在处理较短的行时采用宽松的换行规则,在处理较长的 行时采用严格的规则。其实,auto的作用是让用户代理根据需求在loose、normal和 strict之间切换,甚至可以在一个元素的不同行之间切换。

loose 采用“最宽松的”换行规则,主要用于文本行较短的情况,例如报纸。 normal 采用“最常规的”换行规则。什么是“最常规的”规则,没有准确定义,不过前面说过, 规范中有建议的行为。 strict 采用“最严格的”换行规则。同样,何为“最严格的”,也没有准确定义。

TanXinNiao commented 3 years ago

文本换行

了解断字和软换行之后,我们不禁会想,如果文本超出了所在容器怎么办?这正是 overflow-wrap属性要解决的问题。

取值 normal | break-word

这个属性的作用再简单不过了。使用默认值normal时,按正常方式换行,即在单词之间 换行,或者由所用的语言决定。使用break-word时,可以在单词的内部换行。

溢出换行 注意,只有white-space属性的值允许换行时,overflow-wrap才会起作用。如果 white-space禁止换行(例如设为pre),那么overflow-wrap没有任何效果。

TanXinNiao commented 3 years ago

书写模式

如果你阅读的是本书英文版,或者其他主流西方语言的版本,那么文本是从左至右、从 上到下排列的,这正是英语的流动方向。然而,不是每种语言都是如此。有些语言是从 右至左、从上到下排列的,例如希伯来语和阿拉伯语,还有些语言主要采用从上到下的 方式书写,此外还可以从左至右书写,例如汉语和日语,也可以从右至左书写,例如蒙 古语。

设定书写模式

用于指定采用这三种书写模式中的哪一种的属性是writing-mode。 取值 horizontal-tb | vertical-rl | vertical-lr

改变文本方向

选定书写模式之后,可能还想改变文本行中字符的方向。这么做的原因有很多,尤 其是多种书写系统混杂时,例如日语中掺杂着英语单词或数字。此时,要使用text-orientation 属性。 取值 mixed | upright | sideways text-orientation属性的作用是控制字符的方向。

部是日语和英语文本混合的一个段落,基本没什么样式。下面三个副本使用书 写模式vertical-lro第一个副本使用text-orientation: mixed,横向书写的字符(英 语)侧排,纵向书写的字符(日语)直排。第二个副本中所有字符都是直排的(upright), 包括英语字符。第三个副本中所有字符都是侧排的(sideways),包括日语字符。

TanXinNiao commented 3 years ago

声明方向

回到CSS2。这一版提供了两个用于控制文本方向的属性,它们会改变行内基线的方向。 这两个属性是 direction 和 unicode-bidio direction 取值 ltr|rtl direction属性影响块级元素中文本的书写方向,表格列布局的方向,内容在横向上 溢出元素框的方向,以及两端对齐的元素中最后一行的位置。对行内元素来说,仅当 unicode-bidi 属性设为 embed 或bidi-override 时(见下文),direction 才起作用。

默认值为Mr,但是如果浏览器显示的是从右至左的文本,应该变成rtl因此,浏览 器的内部样式中可能有类似下面的规则: *:lang(ar), *:lang(he) (direction: rtl;} unicode-bidi 取值 normal | embed | bidi-override normal 根据双向算法(bidirectional algorithm),目标元素不打开新的嵌套层级。对于行内 元素,跨元素边界隐式重排。 embed 对于行内元素,根据双向算法,打开新的嵌套层级。这一级嵌套的方向由direction 属性指定。元素内部隐式重排,在元素开头添加一个LRE字符(U+202A,针对 direction: Itr)或一个 RLE 字符(U+202B,针对 direction: rtl),在元素末 尾添加一个PDF字符(U+202C) o bidi-override 覆盖行内元素的书写方向。对于块级元素,覆盖行内后代的书写方向。这意味着, 元素中的文本严格按照direction属性依序重排,而双向算法所做的隐式重排将被忽 略。此时,在元素的开头添加一个LRO字符(U+202D;针对direction: Itr)或一个 RLO字符(U+202E,针对direction: rtl),在元素的末尾添加一个PDF (U+202C) 字符。