CSS 像素和单位计算

像素思维

这一小节,我们将介绍 px(Pixel)

逻辑像素而不是物理像素

px 从字面上来看是像素的意思,很多新手一上来可能会认为它的物理像素

这里必须要澄清,px一般是指逻辑像素,它会根据浏览器、操作系统、硬件设备做适当的缩放。

但是,通常96px对应了一个物理英寸

像素级的完美与响应式布局

最开始,px 被设计出来的时候所奉行的哲学就是提供像素级别的完美

早期的网页设计者会在一个固定大小的页面中设计网页,一般是 800px,你的浏览器如果超过来这个尺寸,必须用水平或者上下滚轮来浏览。每一个元素都是以像素为单位,被精确和巧妙地安排在这个页面中。

随着高清显示屏的出现,人们开始考虑把网页调大到 1024px,甚至是 1280px,

设备的种类越来越多,尺寸、像素等等都难以兼容。

响应式布局是一种能根据屏幕的大小动态调整的布局方式,如今大部分网页都是响应式的,你几乎看不到非响应式的网页了,记得我小时候冲浪就经常遇到那种网页大小不兼容的。

相对字号的大小单位

em 是一个非常有意思的属性。它是一个相对长度单位,相对于当前元素的字号,也就是相对于 font-size 的大小。

计算方法

例如,假设已定义当前的 font-size 的大小为 16pxpadding 的大小为 1.2em ,则 padding 的实际大小是多少 px?

1
2
3
4
.default {
  font-size: 16px;
  padding: 1.2em;
}

这是一道简单的计算题,padding 的实际大小应该是 $16\times1.2=19.2(px)$。

字体大小相对于字体的大小

这是一个有趣的问题,既然 em 是相对于字体的大小单位,那么如果 字体font-size 的大小单位也是 em 会发生什么?

这种情况下,参照对象不再是元素自身,而是父元素

1
2
3
<div class="container">
  <div class="subcontainer"></div>
</div>
1
2
3
4
5
6
7
.container {
  font-size: 16px;
}

.subcontainer {
  font-size: 2em;
}

假如父元素的 font-size16px,子元素的 font-size2em,则子元素的实际 font-size 应该为 32px

如果父元素没有特别说明,则会一直沿着 DOM树 向上,直到找到一个定义的字体大小为止,你始终可以找到一个定义的字体大小,因为浏览器会给根元素设置一个默认的固定的字体大小。

浏览器默认字号

对每一个网页的根节点,我们一般使用 伪类选择器:root 来表示,也可以使用 html 来表示。

大多数浏览器都定义了这个根元素的默认 font-size16px

1
2
3
:root {
  font-size: 16px;
}

字体缩小问题

关于 font-size 使用 em ,你应当尽量避免使用,这会造成一个问题,这里有一个比较有趣的例子。

先做一个无序列表出来:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<ul>
  <li> Top level
    <ul>
      <li> Second level
        <ul>
          <li> Third level
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

设置无序列表的字体为 0.8em,根据计算,无序列表里面的字体大小应该是 12.8px

1
2
3
ul {
  font-size: .8em;
}

效果:

font-size demo

为什么字体越来越小了?

我们可以想象,根元素的字体大小是 16px,所以第一级无序列表是 12.8px 没问题,但是第二级无序列表的父元素是第一级无序列表,所以它的字体大小变成了 $12.8\times0.8=10.24(px)$ 。第三极无序列表的字体大小: $10.24\times0.8=8.192(px)$。

字体随着层级越来越多,变得越来越失控。

正式因为如此,我们一般不推荐使用 em 来定义字体大小,如果你一不小心,就可能造成这种悲剧。

相对根元素字号的大小单位

根元素伪类选择器

伪类选择器:root,在 HTML 中对应的是 html 标签。

设置默认字号

以前,网页设计者们为了方便计算,很喜欢利用这个伪类选择器这样写:

1
2
3
:root {
  font-size: .875em;
}

这是因为 $16\times0.875=10(px)$,通过这种方式把根元素字号定义为 10px 后,接下来,基于根元素的字号计算可以变得简单一些。

自定义属性

这是 CSS3 非常重要的一个特性,不过大多数人都会忽略,事实上,我们习惯了使用 SASS/Scss、Less 等等CSS预处理器之后,这个特性已经比较鸡肋了。

1
2
3
4
5
6
7
8
9
:root {
  --main-font: Helvetica, Arial, sans-serif;
  --brand-color: #369;
}

p {
  font-family: var(--main-font);
  color: var(--brand-color)
}

如果 var() 函数计算出来的是一个非法值,会设置成对应属性的初始值。

rem-低复杂度的em

rem 是 root rm 的缩写,前面已经介绍过 ,rem 是相对于根元素的字号大小,根元素也就是 :root,或者说是 html

1
2
3
4
5
6
7
:root {
  font-size: 16px;
}

ul {
  font-size: .8rem;
}

ul 的 font-size 大小经过计算是 12.8px。

这个 css 代码可以解决上面我们的字体缩小问题。

因为 rem 是相对于根元素字体的大小,就不会引起因为父子元素嵌套而造成的递推缩小现象。

故此,rem 可以被认为是一种低复杂度的 em 。

相对视图窗口的大小单位

视图窗口指的是浏览器视图的大小,在桌面端的浏览器中,你可以随意拖动鼠标来调节这个窗口的大小。

主要涉及的元素是 vhvw,很显然,他们分别是 visual hightvisual width 的缩写。

单位作用备注
vh视图窗口高度的$\frac{1}{100}$
vw视图窗口宽度的$\frac{1}{100}$
vmin视图窗口高度、宽度中较小一方的$\frac{1}{100}$部分浏览器不支持
vmax视图窗口高度、宽度中较大一方的$\frac{1}{100}$部分浏览器不支持

你可以认为这些是百分比单位,他们的原子单位都是 1%

使用 vh 和 vw 定义字号

1
2
3
:root {
  font-size: 2vw;
}

假设这是在一个 1200px 的显示屏上,字体的大小经过计算是 24px。

而在一个 768px 的显示屏上,计算值是 15px。

这实在是太棒了,这是动态可调节的字号。

但是,如果你把浏览器的宽度放到很小,这太糟糕了,有没有可能设置一个最小值和最大值来限制这种现象?

使用 calc() 函数

1
2
3
:root {
  font-size: calc(0.5em + 1vw);
}

这个设计的巧妙之处在于,当你缩小到一定程度,1vw 的计算值几乎不可见的时候,0.5em 依然可以保证它至少有 8px 的大小,不至于小到看不见。

响应式布局入门

响应式布局的精髓是对不同屏幕的适配,我们可以通过媒体查询来定义不同屏幕下的差异。

媒体查询应当规定一些固定的值,作为后面所有元素的参照,后面所有的元素都应该使用相对单位,除了一些线条可以使用 px,其他一律不建议使用。

这里只简单谈一些博主的经验,具体还要靠你们实践。

媒体查询

在 CSS 中,也叫 @meida 规则,它可以指定某种屏幕尺寸或者媒体类型下的样式。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
:root {
  font-size: 0.75em;
}

@media (min-width: 800px) {
  :root {
    font-size: 0.875em;
  }
}

@media (min-width: 1200px) {
  :root {
    font-size: 1em;
  }
}

在宽度小于 800px 屏幕下,根元素 font-size 的计算值是 12px;

在宽度大于 800px,但是小于 1200px 的屏幕下,根元素 font-size 的计算值是 14px;

在宽度大于 1200px 屏幕下,根元素 font-size 的计算值是 16px;

通过媒体查询,做到了不同屏幕的适配。

使用大小单位的建议

为了防止布局的不可调整,我们有一些一般性的结论,来使用 CSS 提供的各种单位。

使用 px 定义线

1
2
3
.default {
  border: 1px soild #999;
}

使用 em 定义间距

1
2
3
.default {
  padding: 1em;
}

使用 rem 定义字号

1
2
3
.default {
  font-size: 1rem;
}

使用 vh 和 vw 定义容器

1
2
3
4
.default {
  height: 50vh;
  weight: 50vw;
}
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计