浅记CSS知识点
参考资料
- https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics
- https://c.runoob.com/front-end/61/
- https://developer.mozilla.org/zh-CN/play
- https://codepen.io/pen/
- b 站 UP 小飞有点东西
学习目标
learning outcomes 了解 css 运作浅层原理,了解伪类、布局、定位等概念
简介
CSS(Cascading Style Sheets),叠层样式表
文件扩展名:.css
作用是:为结构化文档(例如 html)添加样式
书写规则:选择器 + 一条或多条声明
选择器是 HTML 元素;声明是 属性: 值 组成的,声明之间用分号 ; 隔开
注释方法:/* 这里面写注释 */
后面定义的样式会覆盖前面的样式
CSS 如何运行
浏览器会将 HTML 文件转换成一个 DOM(Document Object Model)
然后拉取 HTML 页面上的 css、图片、视频等资源
获取到 css 后,浏览器会对其进行解析
CSS 解析会阻塞渲染,关键 CSS 推荐使用内联或优先加载
首先解析其中的选择器(如 div、.class、#id 等),并按类型进行分组
这样做是为了优化后续匹配效率,避免每次都需要遍历所有 CSS 规则
然后是 构建渲染树(Render Tree)
浏览器将 CSS 规则与 DOM 节点匹配,将这些规则计算后的样式应用到 DOM 节点上(如颜色、尺寸等)
例如 width: 50% 仅仅是记录下样式声明值,但尚未计算实际像素值
这一过程会排除不可见节点(如 display: none)
然后是布局
浏览器根据渲染树的结构,计算每个节点的 几何信息,例如位置(坐标)、尺寸(宽高)、边距等
例如 width: 50% 会根据渲染树的结构、父容器尺寸、视口大小等信息,将相对单位转换为绝对像素值
这一步是性能敏感的操作,需减少(频繁修改 DOM 或样式会触发多次布局,影响性能)
最后是 绘制(Painting)
浏览器将布局后的节点转换为屏幕上的实际像素
当浏览器遇到无法解析的 css 代码时,会忽略并继续解析下一个
我们可以通过为一个元素指定多个 CSS 样式来处理兼容性问题,浏览器会加载样式表中的最后的 CSS 代码进行渲染
例如:
1 2 3 4.box { width: 500px; width: calc(100% - 50px); }新式浏览器则会正常解析
calc方法为像素值;老式浏览器解析不了而忽略该行,直接使用500px
起步
我们可以在 HTML 文档中的 head 元素里面添加
|
|
引入本地的 styles.css 文件
|
|
上述 css 表示将 p 和 li 元素中的颜色都修改为绿色
故如果要一次使用多个选择器,可以用逗号隔开
如果要一次性修改很多个相似的区域,可以为这些区域的元素添加类名 class
通过点号访问这个类
|
|
对于涉及嵌套关系的关系或者相邻关系的元素,有一些选择符供我们使用
|
|
上述代码会修改 li 元素之下的 em 元素的颜色
|
|
上述代码只会修改与 h1 紧邻的 p 元素的字体大小
有时候我们需要根据元素是否是未访问的、访问过的、被鼠标悬停的、被键盘定位的,亦或是正在被点击当中等等状态,来设置不同的样式
以 a 元素为例
|
|
以上代码设置了 a 元素在未访问的、访问过的、被鼠标悬停的时候对应的样式
插入样式表的方法
-
外部样式
编写好的 css 文件在 head 中通过<link>标签导入 -
内部样式
在 head 中的<style>标签编写 css -
内联样式
在相应的标签里直接添加<style>属性 -
多重样式表,以上方式结合使用,结果取并集
-
优先级
1、内联样式 Inline style
2、内部样式 Internal style sheet
3、外部样式 External style sheet
4、浏览器默认样式
关于选择器
元素、类、id 选择器
|
|
元素的属性选择器
|
|
上述代码表示如果 a 元素拥有 href 属性,则对其设置相应的 css
|
|
上述代码表示如果 img 元素的 src 等于我们指定的值才设置相应的 css
还有类似正则表达式的使用方法:
div[class~=“box”] 会选择属性 class 不等于 box 的 div 元素
div[class^=“box-”] 会选择属性 class 开头等于 box- 的 div 元素
div[class$="-box"] 会选择属性 class 结尾等于 -box 的 div 元素
div[class*=“box”] 会选择属性 class 中出现了 a 的 div 元素
伪类与伪元素
前面举的 a 元素在未访问的、访问过的、被鼠标悬停的时候对应的样式例子就是通过 伪类 修改元素样式
常见的伪类还包括 :first-child、:last-child、:only-child、:invalid
伪类用于选择处于特定状态的元素,比如当它们是这一类型的第一个元素时,或者是当鼠标指针悬浮在元素上面的时候
例如需要设置文档首段加粗,我们可以为文章首段添加 class=‘first-paragraph’,然后对这个类进行 css 样式修改
但是如果文档有改动,原首段前面又新增了内容,我们就需要删除旧有的 class,在新的首段上添加 class=‘first-paragraph’
而如果我们使用伪类 :first-child,便无需修改任何代码,使得代码更灵活、更易于维护
|
|
上述代码中 ::first-line 是 伪元素 的用法,会选择 p 元素的中的第一行进行修改
伪元素一般用于修改指定部分的样式,常见的伪元素还包括 ::before、::after、::first-letter 和 ::selection
伪元素的表现像是往 html 中加入全新的 HTML 元素一样,而不是向现有的元素上添加 class 进行样式修改
-
::before和::after
它们和content属性一同使用,可以将content插入到 html 中
content可以是一个文本字符串,但是一般不会在 Web 浏览器上经常这么做
因为对于一些屏幕阅读器来说,::before和::after插入的文本屏幕阅读器不会读出它
更常见的用法是插入一个图标,例如下面的示例加入的一个小箭头,作为一个视觉性的提示1<p class="box">我的 HTML 页面的盒子中的内容。</p>1 2 3.box::after { content: " ➥"; } -
伪类
是选择器的一种,它用于选择处于特定状态的元素
比如当它们是这一类型的第一个元素时,或者是当鼠标指针悬浮在元素上面的时候
帮助减少多余的类的使用,让代码更灵活、更易于维护用来添加一些选择器的特殊效果,例如
使用 :first-child 伪类来选择父元素的第一个子元素
使用 :lang 伪类定义特殊的规则1 2 3 4q:lang(no) { quotes: "~""~"; } /* 为属性值为 no 的 q 元素定义引号的类型 */还有许多的伪类可以使用,例如
:last-child
:only-child
:invalid -
伪元素
实际上,设计伪元素的目的就是去选取诸如元素内容第一个字(母)、第一行,选取某些内容前面或后面这种普通的选择器无法完成的工作 伪元素的作用就像是你已向 DOM 添加了全新的元素,并允许你为其设置样式
::before 和 ::after 伪元素可以使用 CSS 将内容插入文档
但是它本身只是基于元素的抽象,并不存在于文档中,所以叫伪元素
盒模型
css 中的所有元素都被一个个盒子包围着
想象一个盒子,从外到内分别是
1、margin,外边距
2、border,盒子(边框)
3、padding,内边距
4、content,内容
当指定一个 CSS 元素的宽度和高度属性时,只是设置了里面内容区域的宽度和高度
元素的完整大小还必须添加内边距,盒子和外边距
-
盒子类型
- 块级盒子(block boxes)
- 行内盒子(inline boxes)
-
显示类型
- 外部显示(outer display type)
- 内部显示(inner display type)
<h1> 和 <p> 默认使用块级盒子作为外部显示
<a>、<span>、<em> 以及 <strong>,默认使用行内盒子作为外部显示
块级盒子
- 外部显示
会产生换行
width 和 height 属性设置有效
内边距、外边距和边框会将其他元素从当前盒子周围“推开”
如果未指定 width,方框将沿行向扩展,以填充其容器中的可用空间
块元素的前后都自带换行符,例如:<h1>、<p>、<div>
内联元素不强制换行,例如:<span>、<a>
可以通过 display 更改为块或者内联元素
|
|
行内盒子
- 外部显示
不会换行
width 和 height 属性将不起作用
垂直方向 的内边距、外边距以及边框会被应用,但是 不会 把其他处于 inline 状态的盒子推开
水平方向 的内边距、外边距以及边框会被应用,且 会 把其他处于 inline 状态的盒子推开
inline-block
介于区块和行内盒子之间
设置 width 和 height 属性会生效,padding、margin 和 border 也会推开其他元素,但是 不会换行
在下一个示例中,我们将 display: inline-block 添加到 元素中。尝试将此更改为 display: block 或完全删除此行,以查看显示模型中的差异。
标准盒模型
假设一个盒子的 CSS 如下:
|
|
注意外边距不计入盒子的实际大小,但是外边距也影响盒子在页面上所占的总空间
故该 .box 实际大小为:宽 410px(350 + 25 + 25 + 5 + 5),高 210px(150 + 25 + 25 + 5 + 5)
外边距是盒子周围一圈看不到的空间,它会把其他元素退推离盒子。外边距属性值可以为正也可以为负
外边距的计算,假设有两个块级盒子
若上面的盒子的margin-bottom: 50px;,下面的盒子的margin-top: 20px;,则实际上两个盒子之间的外边距之和取的是 max(50, 20)
若上面的盒子的margin-bottom: -50px;,下面的盒子的margin-top: -20px;,则实际上两个盒子之间的外边距之和取的是 min(-50, -20)
若上面的盒子的margin-bottom: 50px;,下面的盒子的margin-top: -20px;,则实际上两个盒子之间的外边距之和是 50-20=30
层叠、优先级与继承层叠、优先级与继承
CSS(Cascading Style Sheets),层叠样式表
CSS 规则的顺序很重要,当一个元素定义了两条同级别规则的时候,写在后面的才是实际使用的规则
关于优先级
如果一个元素选择器不是很具体,例如 div{color: red} 则会选择页面上所有 div 元素,那么该规则的优先级就会低一些
而如果一个类选择器比较具体,例如 .marked-title{color: red},仅对具有该类的元素进行选择,那么它的优先级就要高一点
所以我们知道了类选择器的优先级高于元素选择器,即使类选择器顺序排在元素选择器后面
关于继承
父元素上设置的 一些 css 样式属性值可以被子元素继承
例如在 body 上设置字体颜色,会影响整个页面;而父元素上设置 width 为 50%,子元素并不会继承这个设置
同理 margin、padding 和 border 也不会被继承
控制继承
|
|
设置 inherit 会继承父元素的属性值
设置 initial 会设置为初始值
设置 unset 即复原,如果该属性自然继承则继承,如果是不继承则为初始值
all: unset;重置所有属性值
权重
!important > 内联样式 > ID > class > 元素
选择器中包含 ID 选择器则百位得一分
选择器中包含 class 选择器则十位得一分
选择器中包含元素选择器则个位得一分
但是注意,即使 class 选择器得一万分,其样式属性值也不会覆盖得一分的 ID 选择器
权重计算示例:
| 选择器示例 | 权重值 (ID,Class,Element) |
|---|---|
#nav .item a:hover |
1,2,1 (121) |
div#header |
1,0,1 (101) |
.btn.active |
0,2,0 (020) |
内联样式即写在元素内部的 style 属性里面的 css
推荐做法:先给基本元素定义通用样式,然后给不同的元素创建对应的类,用于修改部分属性的值
!important 规则,用于增加样式的权重
使用 !important 是一个坏习惯,应该尽量避免
因为这破坏了样式表中的固有的级联规则,使得调试找 bug 变得更加困难了
只有在需要覆盖全站或外部 CSS 的特定页面中使用 !important
值和单位
厘米、毫米、英寸等单位多用于印刷,屏幕上常使用像素 px
em 相对于本元素的字体大小,或者在用于 font-size 时相对于父元素的字体大小
rem 相对于根元素的字体大小
vh 和 vw 分别相对于视口的高度和宽度
调整大小
一个空的 <div> 是没有尺寸的,如果为一个空 <div> 添加边框,只会在页面上看到一条线
<div> 是块级元素,故边框宽度会扩展到整个容器宽度,但是它的高度为 0 因为里面内部没有内容
假设有一个盒子,我们给盒子设置了 10% 的 margin 以及 10% 的 padding
我们希望上下外边距是其高度的百分比,元素的左右外边距是其宽度的百分比
但实际上,盒子底部和顶部的内外边距,和左右外边距有同样的大小
这是因为,当使用百分比作为元素外边距(margin)或填充(padding)的单位时,值是以包含块的内联尺寸进行计算的,也就是元素的水平宽度
故上面所有的外边距或填充都是宽度的 10%
溢出的内容
overflow 属性控制一个元素溢出的方式
overflow: hidden 会隐藏溢出内容
overflow-x: scroll 若溢出则会显示横向滚动条
关于图像的大小设置
|
|
如果图片很大,超过了父元素 div 的宽度,该怎么处理溢出问题?
一个常用的方法是将一张图片的 max-width 设为 100%。这将会使图片的尺寸小于等于盒子
或者使用 object-fit 属性
object-fit: cover 维持图像的原始比例进行缩放,但是当比例与外部盒子不同时,会被盒子裁剪掉一部分
object-fit: contain 图像会被缩放到足以完整地放到盒子里面的大小,但是当比例与外部盒子不同时,会出现空白区域
object-fit: fill 可以让图像充满盒子,但是不会维持比例
布局
在 css 中,实现页面布局的主要方法是设定 display 属性
flex
css 弹性盒子布局模块
只需要在想要进行 flex 布局的父元素上应用 display: flex,其直接子元素就都会按照 flex 进行布局
|
|
|
|
.wrapper 中的三个 box 变为了 flex item
因为父元素的 flex-direction 默认为 row,故它们整齐地排成一行
又因为父元素的 align-items 默认为 stretch,故它们被拉伸至和最高元素的高度相同
grid
grid 布局用于将元素在行列维度上排列整齐
|
|
|
|
上述 css 定义了三个 1fr 的列,和两个 100px 的行
可以显式地控制各个 box 的位置:
|
|
还可以通过 grid-area: xxx; 属性自定义名称
然后 grid-template-areas: "xxx"; 即可对内容进行放置
float
一个元素设置为 float 浮动,会被从正常布局流中移除
周围其他元素会在这个浮动元素 周围环绕
若需要清除环绕,可以设置 clear: left; / clear: right; / clear: both;
positioning
定位一般用来 管理和微调 某个元素的位置
-
static 静态定位
默认属性值,位于文档布局流的默认位置 -
relative 相对定位
相对于元素进行移动,可用于元素叠放等等 -
absolute 绝对定位
将元素从布局流中移出,类似单独放在一个图层上,后面的元素会补位
可以相对于<html>元素固定,或者相对于 nearest positioned ancestor element -
fixed 固定定位
与绝对定位类似,但是是相对于浏览器 视口 固定,而不是相对于某个元素
fixed 的元素始终能被我们看到,但是 absolute 可能随着页面向下滚动而消失
可以用于博客系统固定在左侧的章节以及右侧的目录等等 -
sticky 粘性定位 开始时和 static 一样的定位,当该元素的 相对视口位置 达到某个预设值,就会变为 fixed 定位 例如 vscode 上的大纲的各小节标题,文档内容滚动到一定位置时,各小节标题会固定在顶部
常用值包括:static、relative、fixed、absolute、sticky
|
|
|
|
|
|
|
|
|
|
z-index 指定元素堆叠的顺序,谁前谁后
数值越大越前面
居中方案
|
|
响应式设计
媒介查询
|
|
上述 css 判断用户的屏幕是否大于某个宽度或者分辨率,然后选择性地应用 css
在用户的屏幕至少 800px 时,设置上下、左右的 margin 的大小分别为 1em、2em
可指定的媒体类型有:all、print、screen、speech
不同类型可以相互配合,并添加与或非逻辑
viewport 元标签
|
|
上述 meta 标签告诉移动端浏览器,应该将视口宽度设定为设备的宽度
并将文档放大到其预期大小的 100%
这么做的原因是一开始大多数网站没有对移动端做优化,移动端浏览器会直接把视口宽度设置为 960px ,用户体验不好
所以通过设置 width=device-width 覆写 width=960px
💡 现代 CSS 开发应始终考虑移动优先(Mobile First)原则
其他问题
控制文本换行、空白字符的合并
white-space
| 换行符 | 空格和制表符 | 文本换行 | 行末空格 | |
|---|---|---|---|---|
| normal | 合并 | 合并 | 换行 | 移除 |
| nowrap | 合并 | 合并 | 不换行 | 移除 |
| pre | 保留 | 保留 | 不换行 | 保留 |
| pre-wrap | 保留 | 保留 | 换行 | 挂起 |
| pre-line | 保留 | 合并 | 换行 | 移除 |
| break-spaces | 保留 | 保留 | 换行 | 换行 |
单词内部换行
-
word-break 常见取值
-
normal
使用默认的断行规则 -
break-all
对于 non-CJK (CJK 指中文/日文/韩文) 文本,可在任意字符间断行 -
keep-all
CJK 文本不断行。Non-CJK 文本表现同 normal
-
-
overflow-wrap
仅在一个单词无法完整地处于所在行的时候会换行-
normal
例如在两个单词之间的空格处换行 -
anywhere
为防止溢出,如果行中没有其他可接受的断点,则不可断的字符串(如长词或 URL)可能会在任何时候换行 -
break-word
-
css3 的响应式 Web 设计
利用 min-device-width: ?px,对不同设备分别进行设计
-
设置 Viewport
一个常用的针对移动网页优化过的页面的 viewport meta 标签大致如下1<meta name="viewport" content="width=device-width, initial-scale=1.0" />方便移动端访问查看
-
网格视图
很多网页都是基于网格设计的,这说明网页是按列来布局的
使用网格视图有助于我们设计网页,使得添加元素变的更简单
响应式网格视图 通常是 12 列,宽度为 100%,在浏览器窗口大小调整时会自动伸缩1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42/* 确保所有的 HTML 元素都有 box-sizing 属性且设置为 border-box */ /* 确保边距和边框包含在元素的宽度和高度间 */ * { box-sizing: border-box; } .col-1 { width: 8.33%; } .col-2 { width: 16.66%; } .col-3 { width: 25%; } .col-4 { width: 33.33%; } .col-5 { width: 41.66%; } .col-6 { width: 50%; } .col-7 { width: 58.33%; } .col-8 { width: 66.66%; } .col-9 { width: 75%; } .col-10 { width: 83.33%; } .col-11 { width: 91.66%; } .col-12 { width: 100%; } -
图片
1 2 3 4 5 6 7 8div { width: 100%; height: 400px; background-image: url("img_flowers.jpg"); background-repeat: no-repeat; background-size: contain; border: 1px solid red; }- background-size 属性值
“contain”,背景图片将按比例自适应内容区域
“100% 100%” ,背景图片将延展覆盖整个区域
“cover”,虽然全覆盖了,但是背景图像的某些部分无法显示在背景定位区域中
- background-size 属性值
-
框架
响应式 Web 设计框架 Bootstrap1 2 3 4 5 6 7 8 9 10 11<head> <title>Bootstrap Example</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.min.css" /> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <script src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script> </head>
实例
常见设置
-
字体
-
通用字体
sans-serif,无衬线字体,字母末端没有装饰
serif,衬线字体
Monospace 等宽字符 -
特定字体
设置字体系列,如果第一个 Times New Roman 不支持,则尝试 Times,否则使用 serif
|
|
还可以设置样式,是否斜体等
设置字体大小,建议使用 em
普通文本默认 16px = 1em
|
|
- 链接
|
|
可以设置链接的文本、颜色、字体、背景颜色等等
- 列表
|
|
无序列表一般设置标记、有序列表设置文本格式
|
|
-
显示与可见性
- 隐藏且在布局消失
1 2 3h1.hidden { display: none; }- 隐藏但是仍占据空间
1 2 3h1.hidden { visibility: hidden; }
元素居中对齐
|
|
文本居中对齐
|
|
图片居中对齐
|
|
还有左右对齐、垂直居中等等
简约的登录页面
|
|