深入理解css 笔记(3)
过去经常将网页的根元素字号设置为 0.625em 或者 62.5%。这样是为了将全局的 font-size 改成 10px。这样设计师希望字号 14px 时,只需要写成 1.4rem 就好了。还使用了相对单位。一开始,这会很方便,但是这样有两个缺点。第一,我们被迫写很多重复的代码。10px 对大部分都太小了。所以得覆盖它,给文本,边距都设置为 1.4rem.等等。要修改的时候,修改的地方很多。样式表也会更大。第二,这种做法的本质还是像素思维。虽然在代码里写的是 1.4rem。但是心中仍然想着 14 像素。在响应式网页中,需要习惯模糊值。1.2em 到底是多少像素并不重要,重点是它比继承的字号要稍微大一些。
我们可以通过@media 规则,指定某种尺寸或媒体类型下的样式。这是响应式设计的关键部分。
<style>
:root {
font-size: 0.75em;
}
@media (min-width: 800px) {
:root {
font-size: 0.875em;
}
}
@media (min-width: 1200px) {
:root {
font-size: 1em;
}
}
</style>
第一个规则指定里一个较小的默认字号,这是希望在小屏幕上显示的字号。然后使用媒体查询覆盖该值,在 800px,1200px 以及更大的屏幕上逐渐增大字号。所以,如果你足够严格,整个网页的样式都像这样使用相对单位定义,那么网页就会根据窗口大小整体缩放。这是响应式策略中很重要的一部分。这两个媒体查询可以极大减少后续 css 代码中的媒体查询的数量。如果用像素的话,就没有那么容易。如果老板或客户觉得网页的字体太大或者太小,只需要改一行代码就能改变整体的字号,进而不费吹灰之力影响整个网页。
有时,需要让同一个组件在某些部分显示不同的大小,你可以用 em 来单独缩放一个组件。这个我们一般会在当前的 class 后新增一个 large。代码的写法会改变我们 large 类的代码。
<style>
.panel {
font-size: 1rem;
padding: 1em;
border: 1px solid #999;
border-radius: 0.5em;
}
.panel.large {
font-size: 1.2rem;
}
</style>
em 和 rem 都是相对于 font-size 定义的,但 css 里不止有着一种相对单位。还有相对于浏览器定义长度的视口相对单位。视口就是浏览器窗口里网页可见部分的边框区域。不包括浏览器的地址栏,工具栏,状态栏。vmin:视口宽,高中较小的一方的 1/100.vmax:视口宽,高中较大一方的 1/100。
视口相对长度非常适合展示一个填满屏幕的大图。相对视口单位有一个不起眼的用途,就是设置字号,比如 font-size:2vw 会发生什么,在一个 1200px 的桌面显示器上,计算值为 24px,1200 的 2%,这个当视口大小改变时,元素会逐渐过渡。不过屏幕越大字体越大,24px 也很大了。在手机上会很小。所以可以搭配 calc()函数搭配使用。比如 font-size:calc(0,5em + 1vw);这样 0.5em 保证了最小字号。1vw 确保了字体会随窗口变化而变化。要注意运算符号两边必须有空白。
有些属性允许无单位的值(即一个不指定单位的数)。支持这种值的属性包括 line-height(数字,该属性的应用值时这个无单位数字乘以该元素的字体大小,大多数情况下,这是设置 line-height 的推荐方法),z-index,font-weight(700 等于 bold,400 等于 normal)。任何长度单位 px,em,rem 都可以用无单位值的 0,因为这些情况下单位不影响计算值。不过一个无单位的 0 只能用于长度值和百分比,比如内边距,边框和宽度等,而不能用于角度值,比如度,或者时间相关值,比如秒。
自定义属性:要定义一个自定义属性,只需要像其他 css 属性那样声明即可,比如:
<style>
:root {
--main-font: Helvetica;
--brand-color: #369;
}
p {
font-family: var(--main-font);
color: var(--brand-color, blue);
}
</style>
这个代码定义了一个名叫--main-font 的变量。将其值设置为一些常见的字体。变量名前面必须有两个连字符(--),用来跟 css 属性区分,剩下的部分可以随意命名。变量必须在一个声明块内声明。这里使用了:root 选择器,因此该变量可以在整个网页使用。变量声明本身声明也没做,我们使用时才能看到效果。
调用函数 var()就能使用该变量。利用该函数引用前面定义的变量--main-font。在样式表某处自定义属性定义一个值,作为单一数据源,然后在其他地方复用它。这种方式特别适合反复出现的值,比如颜色值。var()函数接受第二个参数,它指定了备用值。如果第一个参数指定的变量未定义,那么就会使用第二个值。如果 var()函数算出来的是一个非法值,对应的属性就会设置为其初始值。比如给 padding 一个颜色值。
前面的示例中,自定义属性只不过为减少重复代码提供了一种便捷方式,但它真正的意义在于,自定义属性的声明能够层叠和继承:可以在多个选择器中定义相同的变量,这个变量在网页的不同地方有不同的值。例如,可以定义一个变量为黑色,然后在某个容器中重新将其定义为白色。那么基于该变量的任何样式,在容器外部会动态解析为黑色,在容器内部会动态解析为白色。
<style>
:root {
--background-color: #13a4a4;
--in-color: #fff;
}
.dark {
--background-color: #333;
--in-color: blue;
}
.slogan {
font-size: 1.2em;
background-color: var(--background-color);
color: var(--in-color);
padding: 1.2em;
}
</style>
<div class="slogan">we love coffee</div>
<div class="dark">
<div class="slogan">we love coffee</div>
</div>
自定义属性就像是作用域变量一样,因为它的值会被后代元素继承。可以结合 js 改变自定义属性。比如 document.documentElement.style.setProperty('--background-color','#333')。利用这种技术就可以用 js 实时切换网站主题,或者在网页中突出显示某些元素,或者实时改变任意多个元素。
在网页上实现元素布局设计很多技术。在复杂网站上,可能会用到浮动元素,绝对定位元素以及其他各种大小的元素,甚至也会使用较新的 css 特性,比如 flexbox 或者网格布局。不过我们要打好基础,深刻理解浏览器是如何设置元素的大小和位置的。高级的布局话题基于文档流和盒模型等概念,这些是决定网页元素的大小和位置的基本规则。
<style>
*,
:before,
:after {
box-sizing: border-box;
}
body {
background-color: #eee;
font-family: Arial, Helvetica, sans-serif;
}
header {
color: #fff;
background-color: #0072b0;
border-radius: 0.5em;
}
main {
display: block;
}
.main {
background-color: #fff;
border-radius: 0.5em;
float: left;
width: 70%;
box-sizing: border-box;
}
.sidebar {
padding: 1.5em;
background-color: #fff;
border-radius: 0.5em;
float: left;
width: 30%;
box-sizing: border-box;
}
</style>
<body>
<header>
<h1>Running Club</h1>
</header>
<div class="container">
<main class="main">
<h2>Come join us!</h2>
<p>
The New England Patriots are a professional American football team based
in the Greater Boston area. They compete in the National Football League
(NFL) as a member club of the league's American Football Conference
(AFC) East division. The Patriots play home games at Gillette Stadium in
Foxborough, Massachusetts, which is 22 miles (35 km)[7] southwest of
downtown Boston.
</p>
</main>
<aside class="sidebar">
<div class="widget"></div>
<div class=""></div>
</aside>
</div>
<script></script>
</body>
我们用一个上面是网页头部,下面是两列内容。这个是因为两列的宽度加起来等于 100%宽度加上 3em.因为放不下,所以两列便折行显示了。最笨的方法是减少一列的宽度。比如把侧边栏改为宽 26%。两列能够并排放下,但是这种方式不可靠。屏幕不确定的情况下可能结果不同。这种可以浏览器帮忙计算。比如 calc(30% - 3em)。
还有解决方案通过 box-sizing 属性来调整。box-sizing 的默认值是 content-box。这意味着任何指定的宽和高都只会设置内容盒子的大小。将 box-sizing 设置为 border-box 后,height 和 width 属性会设置内容,内边距以及边框的大小总和,这刚好符合示例的要求。这种一般其他元素也会遇到这个问题。所以我们可以通过通用选择器*改变默认样式。
有一种简单点的方式,是利用继承改一下修改盒模型的方式。
<style>
:root {
box-sizing: border-box;
}
*,
:before,
:after {
box-sizing: inherit;
}
</style>
盒模型通常不会被继承,但是使用 inherit 关键字可以强制继承。这样网站上每个元素都有一个可预测更好的盒模型来。这个代码要在代码创建时就加上,不然假如你已经基于默认的盒模型写了很多样式,可能就会出现问题。我们接下来的所有示例都假设已经修改了 border-box。
通常在列之间加上一个小小的间隔会更好看。有两种方式可以实现这种效果。给其中一列加上外边距,再调整元素的宽度,将多出来的空间减掉。
<style>
.sidebar {
padding: 1.5em;
background-color: #fff;
border-radius: 0.5em;
float: left;
width: 29%;
margin-left: 1%;
}
</style>
这段代码加上了间隔,但是间隔的宽度由外层容器的宽度决定,百分比时相对于父元素的完整宽度的。正常设计中间隔可能是 px,这可以用 clac()来实现。比如我们间隔 1.5em。
.sidebar { padding: 1.5em; background-color: #fff; border-radius: 0.5em; float:
left; width: calc(30% - 1.5em); margin-left: 1.5em; }