CSS:相对单位

304 阅读3分钟

相对单位也是CSS里容易混淆的概念,这篇文章主要是两点,em和rem,视口的相对单位。

em和rem:

em是最常见的相对长度单位,1em等于当前元素的font-size:

.padded {
  font-size: 16px;
  padding: 1em;
}

padding为1em,当前元素的fontsize是16px,所以浏览器计算后得出padding为16px,所以font-size的变化会导致所有使用em作为单位的属性发生变化:

.box {
  padding: 1em;
  border-radius: 1em;
  background-color: lightgray;
}

.box-small {
  font-size: 12px;
}

.box-large {
  font-size: 18px;
}

<span class="box box-small">Small</span>
<span class="box box-large">Large</span>

image.png

在定义盒子的样式时,可以用 em 指定内边距和圆角。给每个元素设置 1em 的内边距和圆角,再分别指定不同的字号,那么这些属性会随着字体一起缩放。

但是关键的问题来了,如果给font-size设置em会怎样?

答案是会根据继承的字号来计算

body {
  font-size: 16px;
}
//计算结果为元素继承字号的1.2.slogan {
  font-size: 1.2em;
  padding: 1.2em;
}

<body>
  We love coffee
  <p class="slogan">We love coffee</p>
</body>

所以浏览器计算得到slogan的font-size为16×1.2=19.2px, 然后sologan的属性再根据19.2px计算padding值,也就是19.2×1.2=23.04px

所以这会导致一个奇怪的现象,如果文档出现多级嵌套,那么每一级的字体都会继承父级字体大小来计算,如果后代元素的em值大于1,那么字体会逐渐增大,em小于1会逐渐减小:

image.png

逐级缩小

使用rem指定字号

我们知道:root是选中根节点的伪类选择器,所以可以给根节点设定font-size,然后让其余元素的font-size都相对于根节点的font-size来计算,也就是rem:

:root {
  font-size: 1em;
}
ul {
  font-size: .8rem;
}

根元素的em是根据浏览器的默认字号来计算,一般来说是16px,所以使用rem来计算元素本身的字号就解决了上边字号继承带来的问题,而且这么一来还可以很容易改变网页的字号,只需要改变根元素的字号就好。比如使用媒体查询来根据屏幕大小设置响应式面板:

//默认字号
:root {
  font-size: 0.75em;
}
//800px宽屏
@media (min-width: 800px) {
 :root {
   font-size: 0.875em;
 }
}
//1200px宽屏
@media (min-width: 1200px) {
 :root {
   font-size: 1em;
 }
}

视口的相对单位:

前面介绍的 em 和 rem 都是相对于 font-size 定义的,但 CSS 里不止有这一种相对单位。还有相对于浏览器视口定义长度的视口的相对单位

视口——浏览器窗口里网页可见部分的边框区域,不包括浏览器地址栏,工具栏和状态栏
  • vh:视口高度的 1/100。
  • vw:视口宽度的 1/100。
  • vmin:视口宽、高中较小的一方的 1/100
  • vmax:视口宽、高中较大的一方的 1/100 可以通过设置100vw或vh来让一张图铺满视口高度或者宽度

也可以用相对视口的单位来设置字号,而且当视口大小平滑变化时,文字大小也会平滑变化,但是如果屏幕太窄会导致字体极端的小

使用calc()定义字号

calc()函数内可以对两个及其以上的值进行基本运算。它支持的运算包括:加(+)、减(−)、乘(×)、除(÷)。加号和减号两边必须有空格:

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

其中0.5em保证了最小字号,1vm会根据视口缩放,这样在即使屏幕很窄也能有不错的体验。