CSS权威指南学习笔记1

2020-05-14

文档基础

元素

元素按替换性可以分为置换元素(img,input)和非置换元素。

我们更熟悉的是按显示方式分可分为块级元素和行内元素。我们可以使用display属性改变元素的显示方式。但按照html规则,行内元素只能出现在块级元素和行内元素中,而且这是一条于css无关的规则。

应用CSS

  • 使用link标签链接外部样式表文件
    • 将link标签放于head中,避免不必要的重绘
    • 填写标签的media属性可以实施媒体查询
  • 使用style元素

    • 使用@import指令同样可以作为链接外部样式表文件,@import指令也支持媒体查询

      @import url(sheet1.css) screen

      @import url(sheet2.css) print

  • 行内样式

媒体查询

媒体查询是用于根据特定媒体特性选择样式表或样式的功能。媒体特性包括媒体类型媒体描述符

可以使用媒体查询的地方:

  • link元素的media属性
  • style元素的media属性
  • @import 指令后可以附加媒体查询
  • @media 指令

媒体类型

媒体类型是最基本的对媒体的定义,从CSS2就有定义了,到现在还存在的有效属性包括:

  • all 所有媒体
  • print 打印媒体
  • screen 屏幕媒体

如下代码可以创建屏幕显示背景红色而打印背景为白色的样式

@media print{
    body {
        background-color: white;
    }
}

@media screen{
    body {
        background-color: red;
    }
}

媒体描述符

媒体描述符是一个布尔表达式,当这个布尔表达式为真时,应用对应的样式表或者样式。如:

@import url(print-color.css) print and (color), screen and (color-depth: 8)

其中重要的逻辑关键字:

  • ,
  • and
  • not
  • only 表示仅当浏览器支持媒体查询特性

媒体描述符经过css3的扩充,支持的值已经非常多了,例如widthmax-device-heightmin-resolution等等。

特性查询

特性查询是用于根据浏览器对特性支持情况选择样式表或样式的功能。可以用于样式的退化显示。语法很简单:

@supports (color: black){
    body{ color: black}
}

选择符

基本选择符

基本的选择符包括:

  • 元素类型选择符p
  • 类选择符.class
  • id选择符#id
  • 通配符*
  • 属性选择符a[class][href="http://w3.org"]
    • [foo*="bar"],foo属性值包含bar
    • [foo^="bar"],foo属性值以bar开头
    • [foo$="bar"],foo属性值以bar结尾
  • 基本选择符的直接组合,表示逻辑“与”,例如p.classA,表示选择所有元素类型为p且类为classA的元素

根据文档结构选择

我们可以根据文档的树结构,利用基本选择符将样式应用到具体元素上:

  • 后代选择符h1 em {color: gray}:选取h1的全部em后代元素
  • 子元素选择符h1 > em {color: gray}:选取h1后面的直接子em元素
  • 紧邻兄弟元素选择符h1 + p {margin-top: 0}:选取紧跟在h1元素后面的一个兄弟p元素
  • 兄弟元素选择符h1 ~ ol{font-style: italic} ,选取h1元素后面的全部兄弟ol元素

注意到选择符+~都是只能选后继的元素。

伪类选择符

伪类是CSS为选择符系统添加的一个非常强大而灵活的功能。伪类包括了元素状态(如已访问:visited),元素位置(如根元素:root),用户操作(如焦点:focus)等等。

伪类是依附元素的,它不会创造元素,用法类似类选择符.class,这是和伪元素选择器的最大区别。

伪类选择器是可以串联的,表示逻辑“与”,这也是与类选择符类似:

/* a标签未访问且鼠标悬停 */
a:link:hover {color: red}

伪类选择符的值太多,常用/查漏补缺:

  • :only-child
  • :only-of-type 唯一类型
  • :first-child
  • :last-child
  • :first-of-type
  • :last-of-type
  • :nth-child(1) 第1个元素,其中的1可以换为其他数字
  • :nth-child(2n+1)每第2n+1个元素(1,3,5,7),2n+1可以换为其他数学表达式
  • :link
  • :visited
  • :focus
  • :hover
  • :active
  • :enabled
  • :disabled
  • :not() 用于表示逻辑“非”,接受一个选择符表达式的输入,如.not(li)

伪元素选择符

伪元素选择符是用来通过css在指定的位置插入虚拟的元素,是向文档新插入元素,而不是找已有元素,这是与伪类选择符最大的区别。

伪元素选择符标准语法是双冒号,例如::first-line,考虑到兼容性,大部分浏览器也支持单冒号。为了可读性,还是建议使用双冒号语法。

伪元素选择符一次只能选择一个元素,且只能出现在选择符表达式的最后。所以以下表达式无效:

p::first-line em

其中比较迷惑的就是::first-line::first-letter,看起来好像是选择已有的元素。但因为根据HTML文档的规则,我们不可能将样式部分应用到一个元素中。其实他的逻辑是:创建一个新元素替代原有元素。我们可以做一个实验:

p::first-letter {
    font-size: 200%;
}
<p>
     This is a line.
</p>

使用开发者工具我们可以看到:

1589467578643

也就是说,首字母其实是创建了一个新的p标签。目前,::first-line::first-letter只能用于块级元素。

常用的伪元素选择符还包括:

  • ::before
  • ::after

曾经遇到有需求在重要内容前面加红色的*符号,这样写:

p.imp::before {
    content: "*";
    color: red;
}

其中content属性除了放纯字符串,还可以放url、图片、图标等等,非常的好用。

规则冲突和继承

由于CSS的语法特点,可能会有多个规则应用到相同的元素;CSS规则也规定了一些继承规则,可以将一个属性直接作用到一个元素子树上。本章讨论这两个问题。

特指度

特指度解决是多个有效的CSS规则都应用到同一个元素上,该元素应该采用哪一个CSS规则的问题。例如以下两条规则肯定作用于相同的h1元素:

h1 {color: red}
body h1 {color: green}

决定哪条规则能够胜出的原理是依靠选择符的组成计算特指度大小,基本的计算公式是:

  • 规则是行内样式:1,0,0,0
  • id选择符:0,1,0,0
  • 类和伪类选择符、属性选择符:0, 0, 1, 0
  • 元素和伪元素选择符:0, 0, 0, 1
  • 将选择符表达式中的特指度计算加和起来,更大的胜出

例如:

p.bright em.dark {color: yellow} /* 0,0,2,2 */
p#sidebar {color: maroon } /* 0,1,1,1 本条规则胜出*/

需要特别指出,CSS规定通用选择符*的特指度为0,0,0,0,其他任何规则与通用选择符规则冲突时都可以胜出。这样的设计也符合CSS“层叠”的理念。

由于属性选择符的特指度小于id选择符,如果需要写低优先级的id规则,可以这样写:

li[id="meadow"]{color:red} /* 0,0,1,1*/

使用!important声明可以确保无论什么特指度,规则都会应用到元素上。如果有!important的规则发生冲突,继续按照特指度规则决定胜者。

继承

CSS的继承是根据文档树形结构,将属性值从父元素传递给子元素的行为。例如对p元素设置color:gray,p元素和p元素中的span元素显示了灰色。

不是所有CSS属性都会继承,例如border就不会继承,多数盒模型属性也不会继承。

继承得来的属性无特指度,优先级低于特指度0,0,0,0(即通配符规则)。

层叠

层叠解决的是特指度边界问题:如果两个特指度相等的冲突规则应用到同一个元素上会发生什么?

主要的解决方案即使按照规则声明的前后顺序决定,后声明的规则胜出。从这个行为我们也可以知道CSS的解析是按照从后往前的。

层叠问题其实还有很多附加规则。但如果重视可读性和特指度去编写CSS规则,这类边界问题其实很难遇到。就不去列举了。

值和单位

值和单位是CSS规则中的重要组成部分。运用好单位是有时可以事半功倍。

值和单位包括:

  • 关键字
  • 字符串
  • URL
  • 图形和图像
  • 数字和百分数
  • 距离
  • 计算值
  • 属性值
  • 颜色
  • 角度
  • 时间
  • 位置
  • 变量

以下会摘一些比较重要和复杂的单位

距离单位

距离单位是在实践中应用很多的单位类型,也比较复杂。距离单位按照相对性可分为绝对长度单位和相对长度单位,也有面向媒体查询和响应式设计的分辨率单位。

绝对长度单位

绝对长度是最易于理解的,例如pxcm等单位。这类单位类似现实中的度量,是一种绝对值。然而用户使用的屏幕、打印机和其他用户代理是开发者不能够掌握的,应该减少使用。

像素单位px是比较抽象的,不是指真实的像素,而是用户代理根据分辨率得到的虚拟像素。甚么是虚拟像素?例如我们现在用的智能手机基本都配备了视网膜级别屏幕,在分辨率这一项指标上与PC显示器相差无几。但如果我们真的按照真实像素去显示我们的页面,会因为太小而根本没法看。用户代理一般会预设一个放缩值,将真实像素放缩为虚拟像素。

分辨率单位

分辨率单位一般用于响应式设计中,常用的为dpi(1英寸范围内的像素点数)

相对长度单位

由于开发者面对的是不同尺寸、分辨率的用户代理,所以相对长度单位是应用更广泛的。值得重点去理解。

字体字号基准

em,ex,rem单位是应用比较多的以字体字号为基准的相对单位。

em定义为:1em等于该元素的的font-size

ex定义为:1ex等于该元素字体和字号决定的小写字母x的高度

rem与em类似,但相对于root元素(html元素)而不是目标元素的字号计算。

此外还有一个比较小众的单位ch,也是根据字体计算。

可视区基准

可视区是指浏览器窗口、可打印区域、移动设备的显示区域等用户视区。这类单位可以更好的适应不同用户代理的屏幕尺寸。

vw:1vw为可视区宽度的1%

vh:1vh为可视区高度的1%

vmin:1vmin可视区宽度1%和高度1%之中的小者

vmax:1vmin可视区宽度1%和高度1%之中的大者

此外,一些百分数其实也表示相对的单位

计算值

计算值在应用中也是比较多的,其特性是可以接受不同的单位,例如

p {width: calc(90% - 2em)} /* 宽度为父元素宽度的90%少2em */

属性值

属性值可以获取元素的属性,例如:

p::before {content: "[id:" attr(id) "]"}
<p id="leadoff">This is a line.</p>

显示效果为:

1589622176375

变量

变量是可以在CSS中预定义的值,这个特性还挺新的,在2017年底才定义,之前只能靠与编译器实现CSS变量。

CSS要求变量名以双连字符开头--,调用时使用var()函数:

html{
    --alison: #639
}

h1 {color: var(--alison)}

因为这个特性比较新(本文写于2020),应用时可以使用@supports特性查询确保特性能够支持