em和rem
1em 等于当前元素的字号,其准确值取决于作用的元素。谈到 font-size 属性时, em 表现得不太一样。如果声明 font-size: 1.2em,会发生什么呢?一个字号当然不能等于自己的 1.2 倍。实际上,这个 font-size 是根据继承的字号来计算的。
rem 是 root em 的缩写。 rem 不是相对于当前元素,而是相对于根元素的单位。不管在文档的什么位置使用 rem, 1.2rem 都会有相同的计算值: 1.2 乘以根元素的字号。
经验
用 rem 设置字号,用 px 设置边框,用 em 设置其他大部分属性,尤其是内边距、外边距和圆角,(有时用百分比设置容器宽度)。
响应式面板
小屏幕用较小的默认字号,在 800px、 1200px 以及更大的屏幕上逐渐增大字号。
css
:root {
font-size: 0.75em;
}
@media (min-width: 800px) {
:root {
font-size: 0.875em;
}
}
@media (min-width: 1200px) {
:root {
font-size: 1em;
}
}
缩放单个组件
有时,需要让同一个组件在页面的某些部分显示不同的大小,你可以用 em 来单独缩放一个组件。
首先,给每个面板添加父元素声明 font-size: 1rem,这样无论面板位于页面何处,都有一个可预测的字号。
其次,改用 em 而不是用 rem,重新定义标题的字号,使其相对于刚刚在 1rem 时创建的父元素的字号
css
:root {
font-size: 0.75em;
}
@media (min-width: 800px) {
:root {
font-size: 0.875em;
}
}
@media (min-width: 1200px) {
:root {
font-size: 1em;
}
}
body {
font-family: Helvetica, Arial, sans-serif;
}
.panel {
font-size: 1rem;
padding: 1em;
border: 1px solid #999;
border-radius: 0.5em;
}
.panel > h2 {
margin-top: 0;
font-size: 0.8em;
font-weight: bold;
text-transform: uppercase;
}
.panel.large {
font-size: 1.2em;
}
视口相对单位
视口------浏览器窗口里网页可见部分的边框区域。它不包括浏览器的地址栏、工具栏、状态栏。
vh:视口高度的 1/100。
vw:视口宽度的 1/100。
vmin:视口宽、高中较小的一方的 1/100
vmax:视口宽、高中较大的一方的 1/100
提示
相对视口的单位对大部分浏览器而言是较新的特性,因此当你将它跟其他样式结合使用时,会有一些奇怪的 bug。
用 calc()结合 em 和 vh 两种单位定义 font-size
css
:root {
font-size: calc(0.5em + 1vw);
}
现在打开网页,慢慢缩放浏览器,字体会平滑地缩放。 0.5em 保证了最小字号, 1vw 则确保了字体会随着视口缩放。这段代码保证基础字号从 iPhone 6 里的 11.75px 一直过渡到 1200px 的浏览器窗口里的 20px。可以按照自己的喜好调整这个值。
无单位的数值和行高
有些属性允许无单位的值(即一个不指定单位的数)。支持这种值的属性包括 line-height、z-index、 font-weight( 700 等于 bold, 400 等于 normal,等等)。任何长度单位(如 px、 em、rem)都可以用无单位的值 0,因为这些情况下单位不影响计算值,即 0px、 0%、 0em 均相等。警告 一个无单位的 0 只能用于长度值和百分比,比如内边距、边框和宽度等,而不能用于角度值,比如度,或者时间相关的值,比如秒。
line-height 属性比较特殊,它的值既可以有单位也可以无单位。通常我们应该使用无单位的数值,因为它们继承的方式不一样。
当一个元素的值定义为长度( px、 em、 rem,等等)时,子元素会继承它的计算值。当使用 em 等单位定义行高时,它们的值是计算值,传递到了任何继承子元素上。如果子元素有不同的字号,并且继承了 line-height 属性,就会造成意想不到的结果,比如文字重叠。
使用无单位的数值时,继承的是声明值,即在每个继承子元素上会重新算它的计算值。这样得到的结果几乎总是我们想要的。我们可以用一个无单位的数值给 body 设置行高,之后就不用修改了,除非有些地方想要不一样的行高。
自定义属性(即 CSS 变量)
要定义一个自定义属性,只需要像其他 CSS 属性那样声明即可
css
:root {
--main-font: Helvetica, Arial, sans-serif;
}
这个代码清单定义了一个名叫--main-font 的变量。将其值设置为一些常见的 sans-serif 字体。变量名前面必须有两个连字符( --),用来跟 CSS 属性区分,剩下的部分可以随意命名。
调用函数 var()就能使用该变量。利用该函数引用前面定义的变量--main-font。
css
:root {
--main-font: Helvetica, Arial, sans-serif;
}
p {
font-family: var(--main-font);
}
动态改变自定义属性
css
<!doctype html>
<head>
<style>
:root {
font-size: calc(0.5em + 1vw);
--main-bg: #fff;
--main-color: #000;
}
body {
font-family: Helvetica, Arial, sans-serif;
}
.dark {
margin-top: 2em;
padding: 1em;
background-color: #999;
--main-bg: #333;
--main-color: #fff;
}
.panel {
font-size: 1rem;
padding: 1em;
border: 1px solid #999;
border-radius: 0.5em;
background-color: var(--main-bg);
color: var(--main-color);
}
.panel > h2 {
margin-top: 0;
font-size: 0.8em;
font-weight: bold;
text-transform: uppercase;
}
.panel.large {
font-size: 1.2em;
}
</style>
</head>
<body>
<div class="panel">
<h2>Single-origin</h2>
<div class="body">
We have built partnerships with small farms
around the world to hand-select beans at the
peak of season. We then carefully roast in
small batches to maximize their potential.
</div>
</div>
<aside class="dark">
<div class="panel">
<h2>Single-origin</h2>
<div class="body">
We have built partnerships with small farms
around the world to hand-select beans at the
peak of season. We then carefully roast in
small batches to maximize their potential.
</div>
</div>
</aside>
</body>
在本例中,总共定义了自定义属性两次:第一次在根元素上( --main-color 为黑色),第二次在深色容器上( --main-color 为白色)。自定义属性就像作用域变量一样,因为它的值会被后代元素继承。在深色容器中, --main-color 为白色,在页面其他地方,则是黑色。
可以使用 JavaScript 改变自定义属性
javascript
<script type="text/javascript">
let rootElement = document.documentElement;
let styles = getComputedStyle(rootElement);
let mainColor = styles.getPropertyValue('--main-bg');
console.log(String(mainColor).trim());
rootElement = document.documentElement;
rootElement.style.setProperty('--main-bg', '#cdf');
</script>
总结
拥抱相对单位,让网页的结构决定样式的含义。
建议用 rem 设置字号,但是有选择地用 em 实现网页组件的简单缩放。
不用媒体查询也能让整个网页响应式缩放。
使用无单位的值设置行高。
请开始熟悉 CSS 的一个新特性:自定义属性