深度剖析Baseline设计原理

6,051 阅读7分钟

前言:Baseline是很多前端人都用过的最基本的CSS属性之一,乍一看来,似乎很简单,但真的深究起来,Baseline可以算得上CSS最有深度的属性之一了。不信,那就继续往下看。

目录

  • 字体大小

    • 字体大小相同,高度不同
    • 字体是如何制造出来的
  • Baseline的位置

    • 不同display值的Baseline的位置
    • 从vertical-align的值来了解Baseline的兄弟属性的值的含义。

一、字体大小

(1)字体大小相同,高度不同

先来看一个简单的例子:

<p>
    <span style="font-family:Catamaran;font-size:100px;">MO</span>
    //Catamaran就是Google字体库中的原生
    <br>
    <span style="font-family:Catamaran-special;font-size:100px;">MO</span>
    //Catamaran是在原生的基础上做了尺寸改动(只改动了布局,没改动字体设计风格,你就权当是一种新的字体),文章会有说明。
</p>

这一段代码中两个span唯一的不同就是font-family不同,来看一下他们表现的结果:

此处,选中文本,你会发现设置了同样大小的font-size为什么会出现高度不同这样的差异呢?

接下来就要去了解vertical-align中的各个参数的值了:(top,text-top,middle,baseline,text-bottom,bottom等)文字太抽象,直接看(参数图):

这张图的信息量比较大,我们一个一个的理解:

首先,当务之急是要理解,为什么font-size都为100的情况下会出现高度不同的现象:(如图中:第一个span的文字高度为164,而第二个高度则为100呢?)想要搞清楚这个问题,你必须要搞清楚字体是怎么造出来的。因为字体的设计工作不是我们今天的主要工作,我们就直接用别人设计好的字体直接导入字体设计工具。(这里导入的就是我们现在用的Catamaran字体。你可以在google的字体库中找到这个字体https://github.com/qrpike/Web-Font-Load)

(2)字体是如何制造出来的

接下来就看一下字体是如何制造出来的,这你要去了解一个工具Fontforge,如何你有兴趣研究,可以参考参考资料(1)快速入门。我们在这款字体工具中打开M这个字体(O是一样的)。

字体设计时,不出意外都是在上下1000units(font-size)这个单元格之间的范围内设计。我们把上面的MO从新放回Fontforge工具中测试一下就这道。

相信看完这张图,你一定了解了font-size的真正含义了. 但是到目前为止,你可能还有一个疑问就是:那为什么用了Catamaran字体100px就是164像素高呢? 到了这,有人可能就想研究一下fontforge了,所以这边也贴出详细的fontforge的使用说明参考:designwithfontforge.com/zh-CN/index…

@font-face {
       		 font-family: 'hhabnormal';
       		 src: url('./fontfamily/Catamaran.ttf') format('truetype');
   		 }

我们还是接着解决100px边164像素的问题。接下来我们把原生的Catamaran也与fontforge工具中的字体对比一下(你可以用以下代码在网页中尝试自己设计的字体)

对比上下两张图你会发现164px比100px,其实就是多出了font-size上下两个问号的地方。那么这两个问号有指代什么呢?对比上面提到的参数图,你会发现有这样的一块区域,HHead/Win Ascent.这样的两个参数同样是在设计字体的时候就定义好了的。你想通过CSS来修改是不可能的。这里我们同样用图片进行对比,因为用图片进行对比能让你一目了然。我们来看一下,到底对原生的Catamaran字体做了什么,让它与原生的Catamaran字体高度上产生如此大的差异。

可能单看参数,很难理解其真实的含义,所以我们还是结合实例进行分析。我们把这些参数挨个的标注到字体中去。

对比着参数图再看一下上面这张图是不是很快就明白了为什么设置了相同的font-size,却表现出不同的高度。高出的部分其实是:

?(图中上部)=Win/HHead Ascent - Type Ascent.

?(图中下部)=Win/HHead Descent - Type Descent.

这里有必要做一个解释:Win Ascent使用在windows系统中的。HHead Ascent是用在Mac系统中的。基本上设计师在设计的时候两者的值都时一样的。之所以有两个,是因为有两个主流系统,并且他们又不按照同一个标准走,为了兼容才这样。

所以,我们现在算一下font-size:100px;一个高度表现为164px,一个高度表现为100px原因:

164px=Win/HHead Ascent(11px) +Win/HHead Descent(54px);

100px=Win/HHead Ascent(77px) +Win/HHead Descent(23px);

二、Baseline的位置

(1)不同display值的Baseline的位置

解决了上述font-size的疑问之后,一个新的疑问又诞生了:是所有的display类型的元素都有Baseline吗?像inline-block这样的元素如果有好几行文字,是按第一行文字的baseline,还是按第二行文字的基线呢?比如如下图:

像这样的一个div盒模型中有两行文字,那么它的基线应该是按哪一条呢?为什么要搞清楚这个问题?因为display:inline;display:inline-block;的元素都是按baseline来对齐的。不知道你写的元素的baseline在哪,也就等于你写的下一个元素出现在哪个位置,你根本不知道。来看一张图你就明白了。

你会发现,但没有一种对齐标准的时候,物品的摆放将显得异常的混乱。所以这个时候,理解display:inline:display:inline-block;display:block;的基线在什么位置就显得格外的重要了。接下来分情况考虑:

(一)display:inline的基线

通过上面对字体的学习可以知道:inline的元素(如:span,label,i,等元素)的基线就是其中的元素的字体的基线。就是在第一节中的各种baseline.几个不同的inline元素放在同一行的时候,就是把几个的baseline对齐就可以了,就像上面的不同字号的“MO”按基线对齐后的排列是一样的。

(二)display:inline-block的基线

我们用一个实例来看一下:

<div style="display:inline-block;width:100px;height:100px;word-wrap:break-word;
background-color: hsl(2, 86%, 58%);color:#fff;">
    <span>
        MOMOMOMOMOMOMOOMOM
    </span>
</div>
<span style="color:#fff">MOMO</span>

再来看一下运行的结果:

从图中可以看出div元素的baseline是以其包含的inline元素的最后一行作为自己的baseline。下一个同一行中的元素将会把baseline与div的这条基线对齐。那么所有的display:inline-block;都这样吗?像img这种的里面没有inline元素的怎么办呢?我们再通过一个实例来看一下。

<img src="http://chuantu.biz/t6/62/1506246890x3752257483.png" alt="" style="background-color:hsl(2, 86%, 58%);
height:100px;width:100px;">
<span style="color:#fff">MOMO</span>

看一下运行结果:

可以看出img的baseline是它的最底边。其实看到这,我们大概也能得出一些结论了,就是display:inline-block;的元素的baseline。当其中有inline元素是按inline的baseline,当没inline元素是,按最低边。这样总结对吗?告诉你:基本是对的。不信,我们来看一下W3C对于inline-block的基线的定义:

The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge.

(三)display:block的基线

因为block元素是自己霸占一行,所以它根本不需要基线,以为它不需要在前面或者后面与任何元素对齐。

(2)从vertical-align的值来了解Baseline的兄弟属性的值的含义。

上面的那副参数图,已经足以说明一切,除了没有覆盖到sub,super这种不太常用的属性外,其他几乎全覆盖。每一个值都与上面的参数图中一一对应,所以这一点就不再多说。

参考资料:

1.FontForge简单使用教程:www.youtube.com/watch?v=ljR…

2.Deep dive CSS: font metrics, line-height and vertical-align iamvdo.me/en/blog/css…