深入CSS | 青训营笔记

139 阅读14分钟

深入CSS | 青训营笔记

这是我参与「第四届青训营 」笔记创作活动的的第5天

今天整理一篇 了解CSS | 青训营笔记 的进阶版

选择器的特异度

1. 什么是特异度?

css选择符(selector)的特异度(specificity)是css级联(cascade)范畴内的一套有助于解决样式冲突的机制。它的概念是指,当有两个或者以上拥有相同重要性和起源的css选择符里的声明代码要应用于同一个元素来改变其相同的属性的时候,则特异度最高的选择符的声明代码将优先应用于该元素。

是不是很抽象?一起来看下面的css代码你就会明白了。

p {
    color: black;
    background-color: white;
}

div.warning p {
    color: red;
}

div#caution p {
    color: yellow;
}

body#home div p {
    color: white;
}

上面的代码包含了四种都可以匹配p元素的不同选择符,而且都包含了设置color的声明代码,所以浏览器/用户代理需要一种方法来决定哪一种选择符的声明代码将应用于p元素,你猜一下p元素最后将会是什么颜色?

简单地说,拥有最高特异度的选择符的颜色设置声明代码将会优先应用,浏览器/用户代理会计算每一种选择符的特异度,然后逐一比较,最后选择特异度最高的。

2. 特异度的计算

下面先简单描述一下计算步骤

  • 第一步,如果声明代码是在元素的style属性里,也就是行内样式(Inline Style)的话,那么该声明代码拥有最高的优先级,如果不是属于行内样式,那么跳到第二步;行内样式例子:<span style=”color:red:></span>;

  • 第二步,统计ID选择符的数量,数量越多的则特异度越高。如果拥有相同个数的ID选择符,或者都没有ID选择符,那么跳到第三步;

  • 第三步,统计类选择符(如,.test),属性选择符(如,[type=”submit”])和伪类(如,:hover)的总和,数值越大则特异度越高,如果总和相同或者都为0,那么跳到第四步;

  • 第四步,统计元素类型选择符(如,div)和伪元素(如,:first-letter),数值越大则特异度越高。

如果两个或以上的选择符拥有相同的物异度,那么根据css级联的规则,后来者居上,也就是最后指定的将会被应用。

如果你想变得更加专业,那么可以参考W3C recommendation (6.4.3)的计算方法。计算结果用逗号分隔的a,b,c,d四列格式表示,其中a列的值是最重要的,而d的值则是最不重要的。一个选择符的特异度计算方式如下:

  • 计算a列的值,如果是行内样式(Inline Style)的话,则该列的值为1,否则为0;

  • 计算b列的值,值等于选择符所有ID属性个数的总和;

  • 计算c列的值,值为选择符非ID属性的其他属性个数及伪类个数的总和

  • 计算d列的值,值为选择符中的所有元素名个数及伪元素个数的总和

例如,一个形如”[id=p33]”的css属性选择符的计算结果如下是:a=0,b=0,c=1,d=0。

继承

在 css 中,每个CSS 属性定义的概述都指出了这个属性是默认继承的 ("Inherited: Yes") 还是默认不继承的 ("Inherited: no")。这决定了当你没有为元素的属性指定值时该如何计算值。

1. 继承属性

当元素的一个继承属性(inherited property 没有指定值时,则取父元素的同属性的计算值 computed value (en-US)。只有文档根元素取该属性的概述中给定的初始值initial value)(这里的意思应该是在该属性本身的定义中的默认值)。

继承属性的一个典型例子就是 color 属性。给出以下样式规则:

p { color: green; }

若将其应用在下面这段 HTML 代码上…

<p>This paragraph has <em>emphasized text</em> in it.</p>

文本 "emphasized text" 就会呈现为绿色,因为 em 元素继承了 p 元素 color 属性的值,而没有获取 color 属性的初始值(这个 color 值用于页面没有指定 color 时的根元素)。

2. 非继承属性

当元素的一个非继承属性(在 Mozilla code 里有时称之为reset property ) 没有指定值时,则取属性的初始值 initial value(该值在该属性的概述里被指定)。

非继承属性的一个典型例子就是 border 属性。给出以下样式规则:

 p { border: medium solid; }

若将其应用在下面这段 HTML 代码上…

  <p>This paragraph has <em>emphasized text</em> in it.</p>

文本 "emphasized text" 就没有边框,因为 border-style 属性的初始值为none

3. 注意

inherit 关键字允许显式的声明继承性,它对继承和非继承属性都生效。

可以使用 all 简写属性一次控制所有属性的继承,该属性将其值应用于所有属性,例如:

font {
  all: revert;
  font-size: 200%;
  font-weight: bold;
}

这会将 font 属性的样式恢复为用户代理(浏览器)的默认值,除非存在用户样式表,在这种情况下使用该样式表。然后它将字体大小加倍并应用 font-weight 属性 为"bold"

布局(Layout)

1. 布局是什么?

  • 确定内容的大小和位置的算法
  • 依据元素、容器、兄弟节点和内容等信息来计算

2. 布局技术

(1)常规流

a. 概念

在 CSS 2.1 规范中我们定义了常规流(Normal Flow)。常规流中的任何一个盒子总是某个格式区域formatting context)中的一部分。块级盒子是在块格式区域block formatting context)中工作的盒子,而内联盒子是在内联格式区域inline formatting context)中工作的盒子。任何一个盒子总是块级盒子或内联盒子中的一种。

规范中还规定了块格式区域与内联格式区域中的元素行为。对于块级格式环境,规范内规定:

“在一个块格式区域中,盒子会从包含块的顶部开始,按序垂直排列。同级盒子间的垂直距离会由“margin”属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠。

在一个块格式区域中,每个盒子的左外边缘会与包含块左边缘重合(如果是从右到左的排版顺序,则盒子的右外边缘与包含块右边缘重合)。” - 9.4.1

对于内联格式区域中的元素:

“在内联格式区域中,盒子会从包含块的顶部开始,按序水平排列。只有水平外边距、边框和内边距会被保留。这些盒子可以以不同的方式在垂直方向上对齐:可以底部对齐或顶部对其,或者按文字底部进行对齐。我们把包含一串盒子的矩形区域称为一个线条框。(The rectangular area that contains the boxes that form a line is called a line box.)” - 9.4.2

b. 盒子模型(Box Model)

所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用。

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。

盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。

下面的图片说明了盒子模型(Box Model):

image.png

不同部分的说明:

  • Margin(外边距)  - 清除边框外的区域,外边距是透明的。
  • Border(边框)  - 围绕在内边距和内容外的边框。
  • Padding(内边距)  - 清除内容周围的区域,内边距是透明的。
  • Content(内容)  - 盒子的内容,显示文本和图像。

width

  • 指定content box宽度
  • 取值为长度,百分数,auto
  • auto由浏览器根据其它属性确定
  • 百分数相对于容器的content box 宽度

height

  • 指定content box高度
  • 取值为长度,百分数,auto
  • auto由内容计算得来
  • 百分数相对于容器的content box 高度
  • 容器有指定的高度时,百分数才生效

padding

  • 指定元素四个方向的内边距
  • 百分数相对于容器的content box 宽度
  • 该属性可以有1到4个值

1. padding:10px 5px 15px 20px;

  • 上填充是 10px
  • 右填充是 5px
  • 下填充是 15px
  • 左填充是 20px

2. padding:10px 5px 15px;

  • 上填充是 10px
  • 右填充和左填充是 5px
  • 下填充是 15px

3. padding:10px 5px;

  • 上填充和下填充是 10px
  • 右填充和左填充是 5px

4. padding:10px;

  • 所有四个填充都是 10px

border

margin

  • 指定元素四个方向的外边距
  • 取值为长度,百分数,auto
  • 百分数相对于容器宽度
c. 块级元素VS行级元素

块级元素

特点:1.每个块级元素都是独自占一行,其后的元素也只能另起一行,并不能两个元素共用一行。

   2.元素的高度、宽度、行高和顶底边距都是可以设置的。  

   3.元素的宽度如果不设置的话,默认为父元素的宽度。

常见的块级元素: <div><p><h1>...<h6><ol><ul><dl><table><address><blockquote><form>

行级元素

特点:1.可以和其他元素处于一行,不用必须另起一行。

   2.元素的高度、宽度及顶部和底部边距不可设置。

   3.元素的宽度就是它包含的文字、图片的宽度,不可改变。

image.png

image.png

d. display属性

image.png

(2) Flexbox 布局模块

在 Flexbox 布局模块(问世)之前,可用的布局模式有以下四种:

  • 块(Block),用于网页中的部分(节)
  • 行内(Inline),用于文本
  • 表,用于二维表数据
  • 定位,用于元素的明确位置

弹性框布局模块,可以更轻松地设计灵活的响应式布局结构,而无需使用浮动或定位。

a. 定义
  • 一种新的排版上下文
  • 可以控制子级盒子的:
    • 摆放流向
    • 摆放顺序
    • 盒子的宽度和高度
    • 水平和垂直方向对齐
    • 是否允许折行
b. flex-direction 属性

flex-direction 属性定义容器要在哪个方向上堆叠 flex 项目。

column 值设置垂直堆叠 flex 项目(从上到下):

.flex-container {
  display: flex;
  flex-direction: column;
}

image.png 亲自试一试

column-reverse 值垂直堆叠 flex 项目(但从下到上):

.flex-container {
  display: flex;
  flex-direction: column-reverse;
}

image.png 亲自试一试

row 值水平堆叠 flex 项目(从左到右):

.flex-container {
  display: flex;
  flex-direction: row;
}

image.png 亲自试一试

row-reverse 值水平堆叠 flex 项目(但从右到左):

.flex-container {
  display: flex;
  flex-direction: row-reverse;
}

image.png 亲自试一试

c. justify-content 属性

justify-content 属性用于对齐 flex 项目:

image.png

亲自试一试

d. align-items 属性

align-items 属性用于垂直对齐 flex 项目。

image.png

亲自试一试

e. align-self 属性

align-self 属性规定弹性容器内所选项目的对齐方式。

align-self 属性将覆盖容器的 align-items 属性所设置的默认对齐方式。

image.png

在这些例子中,我们使用 200 像素高的容器,以便更好地演示 align-self 属性:

把第三个弹性项目对齐到容器的中间:

<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div style="align-self: center">3</div>
  <div>4</div>
</div>

image.png 亲自试一试

将第二个弹性项目在容器顶部对齐,将第三个弹性项目在容器底部对齐:

<div class="flex-container">
  <div>1</div>
  <div style="align-self: flex-start">2</div>
  <div style="align-self: flex-end">3</div>
  <div>4</div>
</div>

image.png 亲自试一试

f. order 属性

order 属性规定 flex 项目的顺序。

代码中的首个 flex 项目不必在布局中显示为第一项。

order 值必须是数字,默认值是 0。

image.png

order 属性可以改变 flex 项目的顺序:

<div class="flex-container">
  <div style="order: 3">1</div>
  <div style="order: 2">2</div>
  <div style="order: 4">3</div> 
  <div style="order: 1">4</div>
</div>

image.png 亲自试一试

g. Flexibility
  • 可以设置子项的弹性;当容器有剩余时,会伸展;容器控件不足时,会收缩。
  • flex-grow有剩余空间时的伸展能力
  • flex-shrink容器控件不足时收缩的能力
  • flex-basis没有伸展或收缩时的基础长度

image.png

(3)Grid布局

网格是一组相交的水平线和垂直线,它定义了网格的列和行。

CSS 提供了一个基于网格的布局系统,带有行和列,可以让我们更轻松地设计网页,而无需使用浮动和定位。

以下是一个简单的网页布局,使用了网格布局,包含六列和三行:

image.png

  • display:grid 使元素生成一个Grid容器
  • 使用grid-template相关属性将容器划分为网格
  • 设置每一个子项占哪些行列
a. 网格轨道

我们通过 grid-template-columns 和 grid-template-rows 属性来定义网格中的行和列。

这些属性定义了网格的轨道,一个网格轨道就是网格中任意两条线之间的空间。

在下图中你可以看到一个绿色框的轨道——网格的第一个行轨道。第二行有三个白色框轨道。

image.png

以下实例我们使用 grid-template-columns 属性在网格容器中创建四个列:

.grid-container { 
    display: grid; 
    grid-template-columns: auto auto auto auto; 
}

image.png 尝试一下 »

以下实例我们使用 grid-template-rows 属性在网格容器中设置行的高度:

 .grid-container { 
     display: grid; 
     grid-template-rows: 100px 300px; 
 }

image.png 尝试一下 »

b. fr 单位

轨道可以使用任何长度单位进行定义。

网格引入了 fr 单位来帮助我们创建灵活的网格轨道。一个 fr 单位代表网格容器中可用空间的一等份。

以下实例定义了一个网格定义将创建三个相等宽度的轨道,这些轨道会随着可用空间增长和收缩。

c. 网格单元

一个网格单元是在一个网格元素中最小的单位, 从概念上来讲其实它和表格的一个单元格很像。现在再看回我们前面的一个例子, 一旦一个网格元素被定义在一个父级元素当中,那么他的子级元素将会排列在每个事先定义好的网格单元中。在下面的图中,我会将第一个网格单元作高亮处理。

image.png

d. 网格区域

网格元素可以向行或着列的方向扩展一个或多个单元,并且会创建一个网格区域。网格区域的形状应该是一个矩形 - 也就是说你不可能创建出一个类似于"L"形的网格区域。下图高亮的网格区域扩展了2列以及2行。

e. 网格列

网格元素的垂直线方向称为列(Column)。

f. 网格行

网格元素的水平线方向称为行(Row)。

g. 网格间距

网格间距(Column Gap)指的是两个网格单元之间的网格横向间距或网格纵向间距。

您可以使用以下属性来调整间隙大小:

  • grid-column-gap
  • grid-row-gap
  • grid-gap
h. 网格线

列与列,行与行之间的交接处就是网格线。

Grid 会为我们创建编号的网格线来让我们来定位每一个网格元素。

例如下面这个三列两行的网格中,就拥有四条纵向的网格线(灰色圆圈标记),以及三条横向的网格线(黑色圆圈标记)。

网格元素设置时可以参考这些行号。

下图则定义了四条纵向的网格线,以及四条横向的网格线:

网格线的编号顺序取决于文章的书写模式。在从左至右书写的语言中,编号为 1 的网格线位于最左边。在从右至左书写的语言中,编号为 1 的网格线位于最右边。

(4) position属性补充

image.png

image.png

image.png

课后总结

整理不易,还请列位点赞关注!最后偷下懒搬一下上一篇了解CSS | 青训营笔记 的总结

吧哈哈哈。

第二堂课真的是干货爆棚了!!!足足两个半小时讲解CSS,虽然给10个小时也讲不完

(因为CSS知识点真的太多了orz),但是真的学到了很多也很前沿的东西!本节课最难的部分是属性的介绍,太多单词要记 住了~(梦回高中英语课 3.png)下节课继续加

油~~