深入理解css 笔记(2)
还有一种给元素添加样式的方式:继承。经常有人会把层叠跟继承混淆。虽然两者相关,但是应该分别理解它们。如果一个元素的某个属性没有层叠值,则可能会继承某个祖先元素的值。比如给 body 元素添加上 font-family,里面所有的祖先元素都会继承这个字体,不必给页面的每个元素明确指定字体了。但不是所有的属性都能被继承。默认情况下,只有特定的一些属性能被继承,通常是我们希望被继承的那些。它们主要是跟文本相关的属性:color,font,line-height,text-align,word-spacing.还有一些其他属性也可以被继承。比如列表属性:list-style,我们可以在适当的场景使用继承。比如给 body 元素应用字体,让后代元素继承该字体。
有两个特殊值可以赋给人以属性,inherit 和 initial.有时,我们想用继承代替一个层叠值。这时候可以用 inherit 关键字。可以用它来覆盖另一个值,这样该元素就会继承其父元素的值。
我们给网页添加一个浅灰色的页脚,在页脚有一些链接,但是我们不希望这些链接显眼,因此将页脚的链接变为深灰色。
<footer class="footer">
@copy;2022 for css .<a href="/terms-of-use"> Terms of use </a>
</footer>
<style>
a:link {
color: blue;
}
.footer {
color: #666;
background-color: #ccc;
padding: 15px 0;
text-align: center;
font-size: 14px;
}
.footer a {
color: inherit;
text-decoration: underline;
}
</style>
这样做的好处是,如果页脚发生任何样式改变的话,页脚链接的颜色就会跟着页脚其他内容一起改变。比如,当页脚文本变为更深的灰色时,其中的链接也会跟着改变。
有时,你需要撤销作用于某个元素的样式。这可以用 initial 关键字来实现。每一个 CSS 属性都有初始值。如果将 initial 值赋给某个属性,那么就会有效的将其重置为默认值,这个操作相当于硬复位了该值。我们将 footer a 中 color 的值改为 initial。他就会变为黑色。这么做的好处是不需要思考太多。如果想删除一个元素的边框,设置 border:initial 即可。可以习惯了使用 auto 来实现这种重置效果。实际上,用 width:auto 和 initial。原因是 width 的默认值是 auto.但是要注意的是,auto 不是所有属性的默认值,对很多属性甚至来说是非法的。比如 border-width.padding。不会生效。不如使用 initial。
相对单位。说起给属性指定值,CSS 提供了很多选项。人们最熟悉同时也最简单的应该是像素单位 px.它是绝对单位,意思 5px 放在哪里都一样大。而其他单位,如 em 和 rem 就不是绝对单位,而是相对单位。相对单位的值会根据外部因素发生变化。比如 2em 的具体值会根据它作用到的元素而变化。
我们来搞清它的工作原理,然后展示如何控制其看似不可预测的性质。相对单位可以为我们所用,用得恰当的话,它们会让代码更简洁,更灵活也更简单。
CSS 为网页带来了后期绑定的样式:直到内容和样式都完成了,二者才会结合起来。这会给设计流程增加复杂性,而这在其他类型的图形设计中是不存在的。不过这也带来了好处,即一个样式表可以作用于成千上百个网页。此外,用户还能直接改变最终的渲染效果。比如用户可以改变默认字号。
在 web 环境下,用户可以设置浏览器窗口的大小,而 css 必须适应这种窗口大小。这给 css 增加了一个抽象层。我们无法根据理想的条件给元素添加样式,而是要设置无论元素处于任意条件,都能够生效的规则。现在的 web 环境下,网页即需要在手机上渲染也可以在大屏幕上渲染。在很长时间里。我们通过像素级完美的设计来降低这种复杂性。他们会创建一个紧凑的容器,通常是居中的一栏。一般 1024 宽,然后在像之前的本地应用和印刷出版物一样,在这个限制里进行设计。
随着技术的发展,加上制造商推出高清显示器,像素级完美的方式逐渐走向了终点。智能手机出现后,我们都得抛弃以前固定宽度的栏目设计,开始考虑响应式设计。css 带来的抽象性也带来了额外的复杂性。我们在 css 的时候,既要考虑整体性,也要考虑差异性。相对单位就算 css 用来解决这种抽象的一种工具。我们可以基于窗口大小来等比例的缩放字号,而不是固定为 14px。或者将网页上的任何元素大小都相对于基础字号来设置,然后只用改一行代码就能缩放整个网页。这个怎么实现的呢?
em 是最常见的相对长度单位,适合基于特定的字号进行排版。在 css 中,1em 等于当前元素的字号,其准确值取决于作用的元素。
<content>
<div class="padded cover">Here lies one whose name was written in water</div>
</content>
<style>
.padded {
font-size: 16px;
padding: 1em;
border: 1px solid greenyellow;
}
.cover {
font-size: 12px;
}
</style>
这里设置内边距的值为 1em。浏览器将其乘以字号,最终渲染为 16px。这一点很重要:浏览器会根据相对单位的值计算出绝对值,称作计算值(computed value)。设置为 2em,会产生一个 32px 的计算值。如果另一个选择器也命中了相同的元素,并修改了字号,那么就会改变 em 的局部含义,计算出来的内边距也会随之变化。
当设置 padding,height,width,border-radius 等属性时,使用 em 会很方便。这是因为当元素继承了不同的字号,或者用户改变了字体设置时,这些属性会跟着元素均匀的缩放。
<style>
.box {
padding: 1em;
border-radius: 1em;
background-color: lightblue;
}
.box-small {
font-size: 12px;
}
.box-large {
font-size: 18px;
}
</style>
<div>
<span class="box box-small">Small</span>
<span class="box box-large">Large</span>
</div>
我们在设置盒子的样式时,可以用 em 指定内边距和圆角。给每个元素设置 1em 的内边距和圆角,再分别指定不同的字号,那么这些属性会随着字体一起缩放。这就是 em 的好处。可以定义一个元素的大小,然后只需要改变字号就能整体缩放元素。
谈到 font-size 属性时,em 表现得不太一样。之前提到过,当前元素字号决定了 em。但是,如果声明 font-size:1.2em,会发生什么呢?一个字号当然不能等于自己的 1.2 倍。实际上,这个 font-size 是根据继承的字号来计算的。16*1.2
<p class="slogan">we love coffee</p>
<style>
body {
font-size: 16px;
}
.slogan {
font-size: 1.2em;
padding: 1.2em;
background-color: #ccc;
}
</style>
所以,如果知道字号的像素值,但是想用 em 声明,可以用一个简单的公式换算:用想要的像素大小除以继承的像素字号。所以字号的计算值为19.2。(bb时刻)em的复杂之处在于同时用它指定一个元素的字号和其他属性。这时,浏览器必须先计算字号,然后使用这个计算值区算出其余的属性值。这两类属性可以拥有一样的生命值,但是计算值不一样。
当用em来指定多重嵌套的元素的字号时,就会产生意外的结果。当列表多级嵌套并且给每一级使用em定义字号时,就会发生文字缩小的现象。比如有个多层级的div结构,每一层font-size:.8em。这样会导致字体越来越小,或者字体越来越大。不小心应用em会变得很难驾驭。
那怎么办呢,我们还有rem.当浏览器解析HTML文档时,会在内存里将页面的所有元素表示为DOM。在文档中,根节点是所有其他元素的祖先节点。根节点有一个伪类选择器(:root),可以用来选中它自己。rem是root em的缩写。rem不是相对于当前元素,而是相对于根元素的单位。不管在文档的什么位置使用rem,1.2rem都会有相同的计算值:1.2乘以根元素的字号。
与em相比,rem降低了复杂性。实际上,rem结合了px和em的优点,既保留了相对单位的优势,又简单易用。只是不应该全用rem。rem只是你工具包中的一种工具。掌握css很重要的一点是学会在适当的场景下使用适当的工具。比如你可以用rem设置字号,用px设置边框。用em设置内边距,外边距,圆角这种情况。这样字号是可预测的,同时还能在其他因素改变元素字号时,借助em缩放内外边距。