在本章中,我们就来关注下所有CSS里面的值和单位,这是基础中的基础。通过学习,那么你学习后面的内容将会更加得心应手。
1. 关键词,字符串和其他文本数值
样式表里基本都是文本,不过也有不少是数字或是颜色等,还有URL或是图片。
关键词
有些特定的词在CSS是有特殊含义的,比如none,如果想要去掉html中超链接的下划线,可以这样做:
a:link, a:visited {text-decoration: none;}
全局关键词
在CSS3中定义了3个全局的关键词,其实这里的全局的额意思是通用的意思,基本上每个属性都可以使用。它们是:inherit, initial和unset。
inherit:这个关键词就是希望元素能够继承父元素的属性。一般来说都不用刻意指定,因为很多属性是自动继承的,不过有些情况就不一定了,举个例子:
#toolbar {background: blue; color: white;}
<div id="toolbar">
<a href="one.html">One</a> | <a href="two.html">Two</a> |
<a href="three.html">Three</a>
</div>
在上面这个例子中,虽然div本身会把样式实现,但是里面的a后代就不会,而是按照浏览器默认的样式进行显示,这时候就可以使用继承属性:
#toolbar a {color: inherit;}
initial: 这个关键词就是要把属性的值进行初始化,比如font-weight的默认值为normal。
虽然这开上去显得比较傻,不过当你明白不是所有值都有初始值的时候想法就会改变。距离来说color的初始值就完全依赖浏览器。这的意思是color一般会从浏览器的默认偏好设置中获取,虽然很少会有人去改默认为黑色的默认值,但万一出现这种情况,将color设置为initial就是让浏览器将默认值重新设置回来。
unset: unset可以同时实现inherit和initial的功能。如果属性继承了,那么unset设置后跟inherit是一样的;如果属性没有被继承,那么unset的效果就跟initial一样。
这些全局的值是所有属性通用的,但有个属性只接受全局的关键词,那就是all:
all代表了除了direction和unicode-bidi的所有属性,所以说如果在一个元素上设置了all:inherit,那么意思就是让所有的属性都从父元素中继承下来。来看个例子:
section {color: white; background: black; font-weight: bold;}
#example {all: inherit;}
<section>
<div id="example">This is a div.</div>
</section>
你可能会想div应该继承了section定义的color,background和font-weight属性,没错,事实确实这样,不过不仅仅是这些,所有section有关的属性都会被继承。所以有时候这并不是想要的结果,如果你只是想要继承section定义的那几个属性,那么可以这样写:
section {color: white; background: black; font-weight: bold;}
#example {color: inherit; background: inherit; font-weight: inherit;}
字符串
字符串需要注意的点不多,一个是必须以',''这两种分隔符来包围,另一个是在字符串中需要引用其他字符时需要转义。例如换行符就是在\A后面直接加:
"This is a better place \Afor a newline."
而如果只是想在书写时换行,而在显示时不换行,则直接在行末用\符号就行了,在实际显示时解析器会自动忽略,下面两个字符串是一样的效果:
"This is the right place \
for a newline."
"This is the right place for a newline."
URL
如果你写过网页,一定很熟悉URL了,统一的格式基本都是:
url(protocol://server/pathname)
这个例子中定义了一个绝对路径,绝对路径到哪都是通用的,而相对路径相对于的是使用的文档,其通用形式为:
url(pathname)
在CSS中,相对路径相对的是样式本身,而不是引用样式的HTML文档(很重要)。举例来说,如果有个外部样式import了其他样式,那么使用一个相对路径来引用的时候,这个相对路径相对的是第一个样式文件。
比如一个html文档的地址为:http://web.waes.org/toppings/ tips.html, 而在文档中应用的样式为:
<link rel="stylesheet" type="text/css" href="http://web.waffles.org/styles/basic.css">
而在basic.css中引入另一个样式:
@import url(special/toppings.css);
那么猜猜浏览器搜寻toppings.css的路径是什么呢?答案就是http:// web.wa es.org/styles/special/toppings.css,而不是http://web.wa es.org/toppings/ special/toppings.css.
注意在url和括号之间是没有空格的,如果有空格则整个表达式会报错并被忽略:
body {background: url(http://www.pix.web/picture1.jpg);} /* correct */
body {background: url (images/picture2.jpg);} /* INCORRECT */
图片
图片的语法是<image>,它的值就是一个<url>的值,在高级的浏览器中,<image>代表了下面三种特性:
- <url>: 一个指向外部资源的地址;
- <image-set>:一系列的图片来针对不同的设备及尺寸来显示不同。截止2016年末,浏览器中支持image-set的只有safari,chrome和桌面版的Opera。
- <gradient>:定义图片的渐变,可以是linear线性的或是radial辐射的,将在第九章详细介绍。
标识符
有些属性可以接受用户自己定义的某些符号,而最多的就是生成的list counter。标识符(Identifier)本身其实是一些区分大小写的单词,只要不和CSS本身定义的重复就可以了。
2. 数值和百分比
这两类是后面很多值类型的基础,举例来说,font-size就可以用em标识符,前面跟上对应的数值来表示。具体到底有哪些数值类型,我们一一看下。
整型
整型是最常见的,前面可以跟+-号来表示正负。
通用数字
这里指的是包括上面整型和浮点型的数字,也支持正负表示。不过有些属性(像z-index)只接受整型,而有些数字只接受浮点型(像flex-grow)。
百分比
number后面跟%,百分比都是有一个参考的,一般都是元素的父元素。
分数
分数值后面跟着fr的标识,例如一分就是1fr,这个概念是在Grid布局中提到的,主要用于在一个未受限的空间中对空间进行分割,我们将在第13章详细讨论。
3. 距离
很多的CSS特性都需要用到长度的测量,而在CSS也有多种测量方式。从表达式来看长度单位基本都是相同的,正负号后跟一个单位,数字的话包括整数,小数等。有个特例就是0,不需要跟单位。而所有的值按照布局特点可以分为绝对长度单位和相对的长度单位。
绝对长度单位
一共有6种的绝对单位:
- 英寸(inches, in)
参照的是美国的英寸计量单位,果然美国对CSS的贡献还是挺大的。 - 厘米(cm)
国际标准单位 - 毫米(m)
国际标准单位 - 四分之一毫米(q)
奇葩的单位,貌似只有Firefox上会使用,只能说脑洞真大。 - 点(Points, pt)
印刷单位, 一英寸分布72个点。 - Picas(pc)
Picas是另一个印刷的单位,1pc=12pt, 6pc=1in
7.像素(px)
像素本身就代表屏幕上的一个点,不过在CSS里面对像素的定义更加抽象:每英寸上面覆盖96个像素。不过很多浏览器是不太在意这个定义的,在页面放大缩小或者打印的时候,会引入一个叫尺寸因子的变量(scaling factor)来调整实际的显示像素,设置为100px的元素实际显示时可能就会有变化。
绝对的单位在打印文档里面特别有用。
像素长度
像素其实显示出来就是一个个马赛克,如果你放大看的话。
分辨率单位
随着media query和响应式设计的引入,出现了三种描述显示分辨率的单位:
Dots per inch (dpi)
定义为每英寸上的显示dot数Dots per centimeter(dpcm)
跟dpi类似,只不过长度换成了1厘米。Dots per pixel unit (dppx)
每个CSS px单元所显示的dot数目。对于CSS3来说,1dppx等于9dpi。不过很有可能未来的CSS版本中会有所修改。
截止2017年末,上述三个单位还只能用在媒体查询中。举个例子:
@media (min-resolution: 500dpi) { /* rules go here */
}
相对长度单位
之所以称为相对是因为其数值是有一个参照值的,因此相对值最终显示的结果依赖于多个因素,比如说屏幕的分辨率,视口的宽度,用户的偏好设置等等。
em和ex单位
首先我们来看看em和ex单位,这两个非常接近。em的定义为相对于一个给定字体的font-size。所以其实你就可以想见每个元素都可以是不一样的基准值,还是距离来说,分别定义h1,h2, p三个元素的字体大小,然后再基于此顶一个通用的margin-left,来看下效果:
h1 {font-size: 24px;}
h2 {font-size: 18px;}
p {font-size: 12px;}
h1, h2, p {margin-left: 1em;} small {font-size: 0.8em;}
<h1>Left margin = <small>24 pixels</small></h1> <h2>Left margin = <small>18 pixels</small></h2> <p>Left margin = <small>12 pixels</small></p>
当设定玩字体大小后,em的值是相对于父元素的font-size的。有人会很好奇,这个em的命名是怎么来的,理论上说这是个印刷术语,e代表equal, m代表小写的m,而这个m是一个老的印刷术语。类比下em,那ex的定义是小写x的高度。
可能不好理解,来举个例子:如果两个段落的字体大小都是24ex,但每个段落的字体是不相同的,那么最后显示的结果也是不相同的,因为每个字体中对于小写x的高度都是不一样的。
rem单位
就像em单位一样,rem单位也是基于字体的大小。不同的是rem相对的对象是root根元素。在HTML中就是html元素。
来看下面的例子:
<p> This paragraph has the same font size as the root element thanks to inheritance.</p>
<div style="font-size: 30px; background: silver;">
<p style="font-size: 1em;">This paragraph has the same font size as its parent
element.</p>
<p style="font-size: 1rem;">This paragraph has the same font size as the root
element.</p>
</div>
从效果上看rem修正了传统的从祖先继承的字体大小。根元素字体可以这样设置:
html {font-size: 13px;}
那如果根元素设置的是百分比怎么办?
html {font-size: 75%;}
那其实这个百分比相对的是用户的默认大小。
ch单元
ch单位是CSS3新加入的,代表的是'one character',CSS3的官方定义为:
Equal to the advance measure of the “0” (ZERO, U+0030) glyph found in the font used to render it.
CSS中将ch对应到某个字体中字符0的‘宽度’,这和em的计算方式是很接近的。那么怎么才能直观的看到ch是基于字符宽度来定义的呢。下面的例子我们给出不同字体时的显示效果,上面是对应的字符个数,下面是对应的基于img的ch样式设置,来对比下吧:
img {height: 1em; width: 25ch;}
如果是等宽字体(monospace font)的话,所有的字符宽度正好都是1ch,而在比例字体中(覆盖绝大部分西文字体),字符可能与‘0’的宽度有变化,所以不一定是1ch。
跟视口相关的单位
另一块在CSS3中引入的单位是3个跟视口相关的。那什么是视口的,很多情况下就是你所看到的显示区域,对于浏览器来说是它的窗口大小,对于打印设备来说是它的打印范围等等。
视口宽度单位(viewport width unit, vw)
这一单位将视口的宽度进行了100等分,例如如果宽度为937px的话,那么1vw就是9.37px。视口高度单位(viewport height unit, vh)
同上讲视口高度100等分。视口最小单位(viewport minimum unit, vmin)
vmin的取值为同时对视口宽度和高度进行100等分,然后取两个方向上最小的一分作为其值。例如对于一个宽度937px,高度650px,那么1vmin就等于6.5.视口最大单位(viewport maximum)
跟上面相对取最大值,例如对于一个宽度937px,高度650px,那么1vmax就等于9.37px.
来看个具体的例子:
div {width: 50vh; height: 33vw; background: gray;}
上面有没有发现,vh和vw其实不是限定在自己的坐标轴上的,width同样可以用vh的高度单位来设置。
4. 计算数值
有时候需要计算相关的数值,CSS本身提供了calc()来处理。在括号里面可以放入简单的数学表达式,加减乘除和括号都是可以的。
举个例子,如果想要将宽度设置为父元素的90%减去2em,就可以这样写:
p {width: calc(90% - 2em);}
有没有发现calc中的数值可以有2种方式,其实像长度,频率,角度,时间,百分比,数值都是允许的。不过如果以为可以随便乱用的就大错特错了,在计算前calc会做检查来确保数值的计算兼容性:
- 加减号的两边必须是相同的类型。例如5+2.7是可以的,而5em+2.7就不允许,而5em + 20px就是允许的,因为em和px都是长度单位,而5em和2.7,前者是长度单位,后者却不是。
- 如果是乘号,那么符号两边至少得有一个数字,比如2.5rem * 2或是2 2.5rem都是可以的,但是2.5rem * 2rem就是不合理的。
- 如果是除号/,那么右边的元素必须是数字.
- 除号右边是0也是不允许的。
另外一个值得注意的限制就是加减号两边都得有一个空格,而乘除就没有这个要求,这个要求主要为了区别负数。
同样在标准中也规定了calc中的表达式的操作数上限为20个,如果超过这个限制,也会被认为是无效的表达式。
5. 属性数值
在一些css属性中,还可以吧html元素的属性获取到,这要借助attr()表达式。
p::before {content: "[" attr(id) "]";}
没怎么见过,没事,我们将在15章里面详细说明。上面这个表达式的功能就是在p的before位置放置内容,而这个内容是由[]加上<p>中的id字段组成的。来看下:
<p id="leadoff">This is the first paragraph.</p> <p>This is the second paragraph.</p>
<p id="conclusion">This is the third paragraph.</p>
理论上来说任何属性值都可以通过attr()获取到。
input[type="text"] {width: attr(maxlength em);}
<input type="text" maxlength="10">
同样是理论上,上面的input元素的宽度被设置为10em。
6. 颜色
学习css的第一个问题很可能是怎么设置我页面上的颜色,而一般有两种选择:一是使用一定数量的预先定义好的颜色名称,比如red,purple等;二是使用16进制的颜色来表示。
有名称的颜色
最早由16种基本的颜色,这些颜色是在HTML 4.01定义的:
还是举个例子吧:
h1 {color: silver;}
h2 {color: fuchsia;}
h3 {color: navy;}
截止到2017年年底,最新的CSS颜色已经扩展到了148中,全部的列表会在附录C中列出。这些都是由CSS的Color Module Level 4定义的。
RGB和RGBa
很多人都知道RGB,但是不知道哦括号中除了正整数还可以传百分比,0%~100%, 整数范围0~255.
比如下面用百分比定义了黑白色:
rgb(100%,100%,100%)
rgb(0%,0%,0%)
再用整数实现一遍:
rgb(255,255,255)
rgb(0,0,0)
不过请记住,不要混用百分比和数值。例如像这样的表达式是明显错误的:rgb(255,66.67%,50%).为了更好的显示rgb的颜色变化,我们来挨个遍历下:
p.one {color: rgb(0%,0%,0%);}
p.two {color: rgb(20%,20%,20%);}
p.three {color: rgb(40%,40%,40%);}
p.four {color: rgb(60%,60%,60%);}
p.five {color: rgb(80%,80%,80%);}
p.six {color: rgb(0,0,0);}
p.seven {color: rgb(51,51,51);}
p.eight {color: rgb(102,102,102);}
p.nine {color: rgb(153,153,153);}
p.ten {color: rgb(204,204,204);}
另外,rgb中分数的百分比也是支持的
h2 {color: rgb(25.5%,40%,98.6%);}
如果给定数值超出了范围,那么浏览器就会自动修正到最接近的值:
P.one {color: rgb(300%,4200%,110%);} /* 100%,100%,100% */
P.two {color: rgb(0%,-40%,-5000%);} /* 0%,0%,0% */
p.three {color: rgb(42,444,-13);} /* 42,255,0 */
rgba 颜色
在CSS3中,rgba在rgb三通道的前提下新增了alpha透明度通道,如果想要半透明效果,则可以:
rgba(255,255,255,0.5)
rgba(100%,100%,100%,0.5)
alpha通道设定的范围为[0,1],0代表完全透明,1代表完全不透明。所以说 rgb(0,0,0) 和 rgba(0,0,0,1) 是完全一样的。来看几个简单的例子:
p.one {color: rgba(0,0,0,1);}
p.two {color: rgba(0%,0%,0%,0.8);}
p.three {color: rgba(0,0,0,0.6);}
p.four {color: rgba(0%,0%,0%,0.4);}
p.five {color: rgba(0,0,0,0.2);}
跟上面一样,你可以可以超出范围,不过系统会自动修正,因为是0到1范围的值,所以用百分比也是可以的。
16进制的rbg颜色
16进制颜色长啥样呢:
h1 {color: #FF0000;} /* set H1s to red */
h2 {color: #903BC0;} /* set H2s to a dusky purple */
h3 {color: #000000;} /* set H3s to black */
h4 {color: #808080;} /* set H4s to medium gray */
16进制颜色在web设计上已经有悠久的历史了,最早是在HTML,后面CSS也引进过来。组成也很简单,对应于rgb的三个通道,这里用范围[00, FF]的值来表示一个通道,然后再把三个通道连在一起,因此想rgb(255,255,255)就等价于#FFFFFF.其本质都是用1个字节的数据来表示一个通道的颜色值。
16进制中每个通道相同的数值可以简写:
h1 {color: #000;} /* set H1s to black */
h2 {color: #666;} /* set H2s to dark gray */
h3 {color: #FFF;} /* set H3s to white */
那么浏览器是怎么实现的呢?其实当检测到是3位的时候,浏览器读取每一位,然后将其替换一下。比如#6FA替换为#66FFAA。
16进制的rgba颜色
截止到2017年底,为16进制颜色引入了第4个16进制的值,来对应rgba的alpha通道。来看下例子吧:
p.one {color: #000000FF;}
p.two {color: #000000CC;}
p.three {color: #00000099;}
p.four {color: #00000066;}
p.five {color: #00000033;}
第4位同样享受之前说的缩进,#663399AA 可以写成#639A。所以说综上其实16进制的#后面可以跟3位,4位,6位,8位共4种长度的数值。
HSL和HSLa 颜色
CSS3中引入了HSL颜色,三个字母分别代表Hue(色调),Saturation(饱和度),Lightness(亮度)。这是描述颜色的新的3个维度。其中色调的范围是[0,360]的角度值,饱和度的范围是[0, 100]的百分数值,亮度也是[0, 100]
的数值。色调在展示的时候是一个彩色的圆环,红色为0度,就像下面这张图:
色调可能还好理解,但是饱和度和亮度可能有点难度。饱和度其实表现的是颜色的密度。如果饱和度设为0%那么就是一片灰,无论色调设置为啥都是一样的,而饱和度设置为100%则会在给定亮度下覆盖全部的颜色区域。同理,亮度表现的是颜色的亮暗,如果亮度等于0%就变成黑色,而如果设置为100%就会变成白色。具体的来看几个例子吧:
p.one {color: hsl(0,0%,0%);}
p.two{color: hsl(60,0%,25%);}
p.three {color: hsl(120,0%,50%);}
p.four {color: hsl(180,0%,75%);}
p.five {color: hsl(240,0%,0%);}
p.six {color: hsl(300,0%,25%);}
p.seven {color: hsl(360,0%,50%);}
我们可以把之前说的16个命名的颜色映射到图上,看下他们的位置:
就像rgb有rgba一样,hsl也有hsla,alpha的范围还是[0, 1]:
p.one {color: hsla(0,0%,0%,1);}
p.two {color: hsla(0,0%,0%,0.8);}
p.three {color: hsla(0,0%,0%,0.6);}
p.four {color: hsla(0,0%,0%,0.4);}
p.five {color: hsla(0,0%,0%,0.2);}
颜色的关键词
对于颜色来说有两个比较重要的关键词: transparent和currentColor。基本上能用到颜色的地方都可以使用。
transparent顾名思义就是把颜色设置为透明,等同于rgba(0,0,0,0)。虽然在设置文本颜色的时候很少使用,不过像元素的背景默认色,渐变等都是非常常见的。
而curentColor就有点意思了,它有点像个颜色的提取器,将本元素的color属性值提取出来作为参数值。举个例子:
main {color: gray; border-color: currentColor;}
这就把gray复制到了border-color。
7. 角度
我们刚刚讨论到了HSL颜色里面H就是用角度来设置的,那这个角度到底怎么表示呢?在文章中我们取个代号<angle>,数值的组成就是数字加个后缀,后缀有下面4种:
- deg: 跟数学上一样,360度一圈
- grad: 用的比较少,400grad环绕一圈,英文中还有专门的术语grades或是gons
- rad: 这就比较熟悉了,2π 环绕一周
- turn:相当于一圈,这个单位特别在动画旋转的时候很有用,因为有时候你需要让某个元素旋转几圈。
值得注意的是,角度单位大多是用在2D和3D的tranform中,尤其在HSL颜色中,角度单位是不能用的,因为色调的角度数值默认就是deg。
8. 时间和频率
为了表述一段时间,引入了时间的单位,组成的话由数字和后面的单位组成。单位只有两种:s(秒)和ms(毫秒)。时间的单位大多是也是用在过渡和动画中,举个例子:
a[href] {transition-duration: 2.4s;}
a[href] {transition-duration: 2400ms;}
接着介绍下频率单位,有赫兹hz和千赫mhz,单位大小写是不敏感的,也来两个例子:
h1 {pitch: 128hz;}
h1 {pitch: 0.128khz;}
9. 位置
位置单位主要用于在背景范围内如何摆放元素,不过其语法还是有点复杂的:
如果你只定义了一个值,那么第二个值center是默认带上的,例如left等于left center。而且在值得设置上,如果给了2个值,例如25% 25px, 那么前者默认是表示水平方向,后者默认是表示垂直方向。所以像25% left的这种表达式都是不合理的。但是另一方面,如果你给的2个值虽然顺序反了,但是正好覆盖了水平和垂直方向,也是可以的。比如:right 35px。
接下来考虑4个值的情况,那么规则是第2和第4个值作为水平和垂直方向的偏离值,例如right 10px bottom 30px就表示从右边起10px的位置和从底部起30px的位置。
有人会问,那传入3个值怎么办,那么规则对标4个值的情况,只不过第4个值默认是0.
10. 自定义数值
本书是在2017年底写成的,而截至到这时候,正好CSS有新的特性添加,称为custom properties。可以称为自定义属性吧,不过它们的主要用途其实就是创建css的变量,来看个例子:
html {
--base-color: #639; --highlight-color: #AEA;
}
h1 {color: var(--base-color);}
h2 {color: var(--highlight-color);}
注意声明css变量的语法,前面有两个横杠--,变量是大小写敏感的,所以这两个值--main-color 和 --Main-color是不一样的。
虽然这些值很容易被称为CSS变量,不过不要真把它们当成变量了,它们其实更像是宏,定义完后会把对应的位置做一个替换。
另一个有意思的关于自定义属性的特点就是它们其实是有上下文的,来看个例子:
html {
--base-color: #639;
} aside {
--base-color: #F60; }
h1 {color: var(--base-color);} <body>
<h1>Heading 1</h1><p>Main text.</p>
<aside>
<h1>Heading 1</h1><p>An aside.</p>
</aside>
<h1>Heading 1</h1><p>Main text.</p> </body>
如果害怕有兼容性问题,可以采取下面的方式来进行兼容:
@supports (color: var(--custom)) {
/* variable-dependent styles go here */
}
@supports (--custom: value) {
/* alternate query pattern */
}