CSS文本样式

最近偶然发现,定宽容器中的的文字,如果中文会自动换行,英文不会自动换行。原本只是为了解决这个问题,后逐渐深入css文字处理,发现这里面另有乾坤。

<!--more-->

为了便于理解,我将文字处理,分为了字体与文本这两块:

  • 字体包括字体,颜色,大小,字样,加粗等
  • 文本内容杂而多,大致分为如下部分:
    • 文本区域尺寸,包括行高
    • 文本排版,包括大小写,对齐,间距,缩进
    • 文本换行,包括溢出,换行
    • 文本装饰,包括下划线,阴影

1. 字体

关于字体样式,整理了下面几点:

  • font-family可以设置多个字体,使用逗号分隔,浏览器按顺序查找对应字体,如果系统存在对应字体则使用,如果不存在则查询下一个字体,依次类推;
  • 关于字体颜色,常见的一个BUG是突然发现页面上字体不显示,这种情况下可以检测字体颜色是否与背景色一致;
  • font-style设置字体倾斜,如果对应字体的font-family没有设计斜体,指定italic也会应用oblique;
  • font-weight可以设置数值,范围为100-900的整百位数(实际上100到300可能映射到同样的字体粗细上面);
  • 字体大小除了应用在常规的文章排版上,现在正逐渐流行基于rem的移动端自适应布局。
  • 提到字体,就不能不提到字体图标,常见的如fontawesome,iconfont等,可以通过设置字体样式达到之前必须使用精灵图才能实现的效果,十分方便。

2. 文本

2.1. 行高

行高是刚接触CSS就学习的一个属性,然而对它的了解却仅限于设置文字居中,这实在是惭愧得很,这里有一篇关于行高的详解博客

首先需要明白的是文字的顶线中线基线底线:指文本行从上到下的四条基准线,跟vertical-align的属性值相对应,(大概可以想象成写英文单词时的四线本)。

然后需要明白的是文字的行高字体大小行距这三个概念:

  • 行高指上下文本行之间基线的竖直距离;
  • 字体大小指该行文本行顶线到底线的竖直距离;
  • 行距指上一行文本行的底线到下一行文本行的顶线之间的距离,即(行高-字体大小);

最后是内容区行内框行框这三个概念:

  • 内容区指文本行顶线和底线所撑开的范围,即由字体大小决定;
  • 行内框是一个浏览器渲染模型(类似于BFC,这里应该叫IFC)。在没有设定行高的时候,行内框与内容与大小相同;设定行高时,行内框大小也不会发生变化,而是在其上下增加半行距;
  • 行框也是一个浏览器渲染模型,每行文本行都有自己的行框,其高度等于该行所有内联元素行内框的最大值;

搞定上面的几个概念,终于能够明白行高了。前面提到行高指的是两行文本行之间基线的竖直距离,两行文本行之间的行距是行高与文本字体大小之差。

可以使用比例指定行高大小为字体的倍数,关于行高的继承性,有一个小小的坑,在子元素并未继承父元素字体大小的情况下:

  • 如果行高使用的是百分数,则会先将父容器的行高计算出来在继承给子元素(即百分数*父容器字体大小);
  • 如果行高使用的小数,则会直接将该乘积因子继承给子元素,再计算子元素的行高(即小数*子容器字体大小);

2.2. 排版

关于排版这几个属性,日常用的也不是很多,简单了解一下:

  • 使用text-transform进行文本大小写转换;
  • 使用text-align设置文本内中对齐方式,需要注意的是这条属性对于图片等内联-块状元素也是同样生效的;
  • 关于文本间距,又分为字间距(letter-spacing)和词间距(word-spacing),区分这两种间距十分容易,字间距在一组连续的字中生效,词间距在两个以空格分隔的词组间生效:
  • 使用text-indent设置文本缩进大小,一般使用em表示相对缩进几个字符,手册上说text-indent是一个复合属性,一个很少用的到属性值each-line表示对每行强制换行的文本都执行对应大小的缩进,但是很多浏览器都不支持(所以并没有什么用处);

2.3. 换行

文本换行是之前很少注意到的一个地方,最近的项目中却频繁出现了类似的要求:处理定宽标题中多余的文字,处理某个网站英文版本导航栏由于单词过长导致的排版问题。突然又会想起之前遇到的“包含块内的p内的字是中文会自动换行,是英文不会自动换行”的问题。基于上述原因,因此开始学习相关内容,这篇文章的初衷也源于此。 接下来讨论的换行主要是针对西文字符的,因为亚洲文字文本拥有默认的white-space:normal,当遇到文本框边界时自动换行,而默认的非亚洲文本并不会自动换行,直接溢出整个文本框。 换行有两个属性(word-wrap和word-break),这两者都指定了文本换行的规则,但是又有不同:

2.3.1. word-break

word-break的换行属性值有normal,break-allkeep-all三个:

  • break-all表示允许非亚洲语言文本行可以在任意字符间换行,即当该文本行放不下最后一个单词时会打断该单词
  • keep-all会检测该行文本是否有足够的空间容纳最后的那个单词,如果不能,则该单词会换行显示,如果第二行整行都不能放下这个单词,那也不会再换行,而是直接溢出
  • normal表示依照空格换行,与keep-all类似,具体的区别我还真没弄明白

2.3.2. word-warp

word-warp的换行属性值有normal和break-word两个:

  • normal与上面的keep-all类似,如果第二行整行不能放下这个单词就会溢出,
  • break-word表示文本会在边界换行,与keep-all类似,但是如果第二行整行都不能放下这个单词,则会打断该单词并实现换行效果。

2.3.3. 处理文本溢出

设置word-break:break-all之后单词会非常生硬地换行,而平常书本上的换行单词都有短横线连接符,可以使用hyphens属性实现,但是目前的谷歌浏览器不支持。

    .elp {
        -moz-hyphens: auto;
        -ms-hyphens: auto;
        -webkit-hyphens: auto;
        hyphens: auto;
    }

然后就是解决文本溢出的问题,常用的方法是:

    .elp {
        white-space: nowrap; 
        overflow: hidden; 
        text-overflow: ellipsis;
    }

其中white-space属性是用来设置文本内的空格处理方式,下面是几个常用的属性值(详情参加手册):

  • pre 不合并文字间的空白距离,当文字超出边界时不换行,也就是说会解析HTML代码中的所有空白(包括为了清晰代码格式而使用的缩进);
  • nowrap 强制在同一行内显示所有文本,合并文本间的多余空白(即存在空格则会保留一个空格),直到文本结束或者遭遇br对象;
  • pre-wrap 用等宽字体显示预先格式化的文本,不合并文字间的空白距离,当文字碰到边界时发生换行,但是长单词在换行之后仍然可能溢出文本框
  • pre-line 保持文本的换行,不保留文字间的空白距离,当文字碰到边界时发生换行。 而上面处理文本溢出的方法采用的就是忽略全部空格,因此这样只能实现处理一行文本溢出的情况,关于多行文本溢出,可以使用下面这段CSS样式,需要注意的是该方法只能在webkit内核的浏览器下才能生效,希望以后标准能够加入到所有浏览器中。如果考虑兼容性的化可以使用JS实现该效果。
      .elp {
          width: 100px;
          overflow: hidden;
          text-overflow: ellipsis;
          display: -webkit-box;
          -webkit-line-clamp:3;
          -webkit-box-orient: vertical;
      }

2.4. 文本装饰和阴影

这个就很熟悉了吧,最常见的文本装饰就是a标签的默认下划线,而关于字体阴影是CSS3新增的属性,这个在另外的文章里面再谈吧。

3. 最后

关于文本样式最后需要注意一点:貌似所有的文本样式都是可以继承的,因此为父容器指定公共的字体样式是很明智的做法。但是,并不能完全依赖于继承样式,否则就会困惑于为什么“a标签的字体样式为什么与父容器的字体样式不一致,我明明设置了呀”这样的问题,而关于这个问题,只需要明白继承样式的优先级非常低就很清晰了。