目录
浏览器的渲染过程⭐⭐⭐
CSS 、JS 阻塞 DOM 解析和渲染
回流(重排)和重绘⭐⭐
选择器
ID选择器、类选择器、标签选择器(按优先级高到低排序)⭐⭐
特殊符号选择器(>,+,~,空格,逗号)
属性选择器
伪类和伪元素选择器(⭐手写)伪类和伪元素选择器
优先级⭐⭐⭐
样式方式(按优先级高到低排序)⭐⭐
内联样式表(在标签内设置元素的样式)
嵌入样式表(在head标签内)
外部样式表(在head标签内)
position关键字⭐⭐⭐
水平 & 垂直对齐 (⭐手写)
水平居中
水平垂直居中
transform:translate
flex(强烈推荐)
flex布局⭐⭐⭐
align-items和justify-content的区别
flex:1
BFC规范⭐⭐⭐
问题
常见触发条件
规则
单位⭐⭐⭐
px转rem
px转vw
行内素、块级元素和行内块元素⭐⭐⭐
响应式布局⭐⭐
浏览器的渲染过程⭐⭐⭐
1.解析HTML的所有标签,深度遍历生成DOM Tree
2.解析CSS,构建层叠样式表模型CSSOM(CSS Object Model)
2.5.JS脚本加载
a. 普通js/sync
文档解析的过程中,如果遇到script脚本,就会停止页面的解析进行下载,当脚本都执行完毕后,才会继续解析页面。
(因为JS可以操作DOM和CSS,可能会改动DOM和CSS,所以继续解析会造成浪费)。
如果脚本是外部的,会等待脚本下载完毕,再继续解析文档。
所以常见的做法是将js放到页脚部分。
b. async(异步:HTML加载和解析,js加载)
async脚本会在加载完毕后执行。
<script type="text/javascript" src="x.min.js" async="async"></script>
async脚本的加载不计入DOMContentLoaded事件统计,也就是说下图两种情况都是有可能发生的:
HTML 还没有被解析完的时候,async脚本已经加载完了,那么 HTML 停止解析,去执行脚本,脚本执行完毕后触发DOMContentLoaded事件。
HTML 解析完了之后,async脚本才加载完,然后再执行脚本,那么在HTML解析完毕、async脚本还没加载完的时候就触发DOMContentLoaded事件
c. defer(推迟)
文档解析时,遇到设置了defer的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析和渲染完毕后,会等到所有的defer脚本加载完毕并按照顺序执行完毕才会触发
<script type="text/javascript" src="x.min.js" defer="defer"></script>
DOMContentLoaded事件,也就是说下图两种情况都是有可能发生的:
HTML 还没有被解析完的时候,defer脚本已经加载完了,那么 等待HTML 解析完成后执行脚本,脚本执行完毕后触发DOMContentLoaded事件。
HTML 解析完了之后,defer脚本才加载完,然后再执行脚本,脚本执行完毕后触发DOMContentLoaded事件。
defer是“渲染完再执行”:依赖于页面中的DOM元素(文档是否解析完毕),或者被其他脚本文件依赖
async是“下载完就执行”:并不关心页面中的DOM元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。
3.构建Render Tree(渲染树)
DOM和CSSOM根据一定的规则组合起来生成了Render Tree
4.布局(Layout)
确定各个元素的位置,以及大小。浏览器使用一种流式处理的方法,只需要一次绘制操作就可以布局所有的元素。
5.绘制(Painting)
浏览器会遍历Render Tree渲染树,调用“paint”方法,将渲染树的各个节点绘制到屏幕上。
CSS 、JS 阻塞 DOM 解析和渲染
浏览器将页面从网络下载到本地后:
解析HTML,创建DOM,同时加载依赖的资源:CSS、图片等(加载资源的过程不会阻塞DOM解析),然后调用渲染进程渲染到界面上。
所谓渲染,就是显示
- css不阻止dom的解析
- js阻止dom的解析:js有可能影响dom的解析,比如在js里面新增dom等这些操作
- css js都会阻止dom的渲染:dom的渲染 是需要等js,css都解析完成后才进行的
尽量将CSS
放头部,JS
放底部,这样可以提高页面的性能。
为了减缓渲染被阻塞的情况,现代的浏览器都使用了猜测预加载。
当解析被阻塞的时候,浏览器会有一个轻量级的HTML(或CSS)扫描器(scanner)继续在文档中扫描,查找那些将来可能能够用到的资源文件的url,在渲染器使用它们之前将其下载下来。
回流(重排)和重绘⭐⭐
回流(重排)
元素改变 尺寸,宽高,边框,内容,位置 都会引起重排,导致需要重新构建页面的时候
- 增删可见的 DOM 元素的时候
- 元素的位置发生改变
- 元素的尺寸发生改变
- 内容改变
- 页面第一次渲染的时候
重绘
外观发生改变,但没有改变布局
列举一些相关的 CSS 样式:color、background、background-size、visibility、box-shadow
选择器
ID选择器、类选择器、标签选择器(按优先级高到低排序)⭐⭐
<html>
<head>
<meta charset=utf-8>
<style type="text/css">
div{
color:#ff0000;
font-size:20px;
}
.green{
color:#008000;
}
#black{
color:#000000;
}
</style>
</head>
<body>
<div>红色</div>
<div class='green'>绿色</div>
<div id='black'>黑色</div>
</body>
</html>
特殊符号选择器(>,+,~,空格,逗号)
群组选择器(’,’)
/* 表示同时选择h1,h2 */
h1, h2 {
...
}
子元素选择器(空格)
/* 表示选择 h1 下面的所有 span 元素,不管是否以 h1 为直接父元素 */
h1 span {
...
}
直接子元素选择器(’>’)
/* 表示 h1 下面的所有以 h1 为直接父元素的 span 元素,注意与空格的区别*/
h1 > span {
...
}
相邻兄弟选择器(’+’)
/* 表示选择紧跟在 h1 后的首个兄弟 span 元素,h1 和 span 必须有相同的父元素,即二者必须是同一级元素 */
h1 + span {
...
}
兄弟选择器(’~’)
/* 表示选择 h1 后的所有兄弟 span 元素,h1 和 span 必须有相同的父元素,即二者必须是同一级元素。注意与 + 的区别,+ 必须是紧跟着的兄弟元素,而 ~ 不要求紧跟,是所有兄弟元素 */
h1 ~ span {
...
}
属性选择器
属性选择元素
[title]
{
color:blue;
}
伪类和伪元素选择器(⭐手写)伪类和伪元素选择器
伪类选择器:逻辑选择元素
selector:pseudo-class {property:value;}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
a:link {color:#000000;} /* 未访问链接*/
a:visited {color:#00FF00;} /* 已访问链接 */
a:hover {color:#FF00FF;} /* 鼠标移动到链接上 */
a:active {color:#0000FF;} /* 鼠标点击时 */
</style>
</head>
<body>
<p><b><a href="/css/" target="_blank">这是一个链接</a></b></p>
<p><b>注意:</b> a:hover 必须在 a:link 和 a:visited 之后,需要严格按顺序才能看到效果。</p>
<p><b>注意:</b> a:active 必须在 a:hover 之后。</p>
</body>
</html>
- nth-child(n)
nth-child(n)匹配属于其父元素的第n个子元素,不论元素类型,n可以是数字、关键词、或公式。关键词odd和even是可用于匹配下标是奇数或偶数的子元素的关键词(第一个子元素的下标是 1)
<html>
<head>
<meta charset=utf-8>
<style type="text/css">
ul li:nth-child(even) {
background-color: rgb(255,0,0);
}
</style>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</body>
</html>
- 伪元素
<head>
<meta charset=utf-8>
<style type="text/css">
div::after{
content:"";
width: 20px;
height: 20px;
background-color: rgb(255,0,0);
display: block;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
html模块的div元素加一个后伪元素
- 伪类只能使用“:”,伪元素既可以使用“:”,也可以使用“::”
- 伪元素其实相当于伪造了一个元素,伪类没有伪造元素,例如first-child只是给子元素添加样式而已。(本质区别就是是否抽象创造了新元素)
优先级⭐⭐⭐
- 在同一层级下:权值由高到低
- !important (会覆盖CSS的任何声明,其实与优先级毫无关系) 权值
- 内联样式(style=“ ”) 1000
- ID选择器(id=" “) 100
- 伪类选择器(如:hover)
- 属性选择器[title]{color:blue;})
- Class类选择器(class=” ") 10
- HTML标签选择器 (p{}) 1
- 通用选择器(*) 0
- 不同层级下:
正常来说权重值越高的优先级越高,但是一直以来没有具体的权重值划分,所以目前大多数开发中层级越深的优先级越高
样式方式(按优先级高到低排序)⭐⭐
内联样式表(在标签内设置元素的样式)
写一次只能设置一个
<p style="background:red"></p>
嵌入样式表(在head标签内)
<head>
<title></title>
<style type="text/css">
p{
background-color:yellow;
}
</style>
</head>
外部样式表(在head标签内)
rel=relationship
href=hypertext Reference
<head>
<title></title>
<link href="xxx.css" rel="stylesheet" type="text/css"/>
</head>
通过 link 进行对外部CSS样式文件的引用,也可以引用网上别人写好的样式
transform旋转,缩放,平移⭐⭐
修改 CSS 坐标空间,实现旋转,缩放,倾斜或平移
默认相对元素的中心点
Css3 Transform 各种变形旋转 | 菜鸟工具
position关键字⭐⭐⭐
static(默认)
该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top
, right
, bottom
, left
和 z-index
属性无效。
z-index 属性指定一个元素的堆叠顺序。
拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。
- inherit
从父元素继承 position 属性的值。
relative
相对于其正常位置进行定位。
元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。
absolute
相对于 static 定位以外的第一个父元素进行定位。
元素会被移出正常文档流,并不为元素预留空间。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。
- fixed:相对于浏览器窗口进行定位。在屏幕滚动时不会改变
- sticky(CSS3新增) :基于用户滚动的位置,屏幕滚出时会粘住
水平 & 垂直对齐 (⭐手写)
水平居中
指在水平方向上处于中间的位置。
- 元素/图片:
margin: auto;
行内元素会占整行,看不出来水平居中,所以需要:width: 50%;
- 文本:
文本标签除了<p>都是行内元素,text-align=center
垂直居中
- 单行文本:
line-height = height
- 图片:
vertical-align: middle;
水平垂直居中
transform:translate
top: 50%;left: 50%;, 是以元素左上角为原点,故不处于中心位置,
加上transform:translate(-50%,-50%) ,元素原点(中心点)往上(x轴),左(y轴)移动自身长宽的 50%,
flex(强烈推荐)
只需要设置 align-items:center; 属性
.wrap {
width: 300px;
height: 300px;
border: 1px solid red;
display:flex;
justify-content:center;
align-items:center;
}
.box {
height: 100px;
width: 100px;
border: 1px solid blue;
}
flex布局⭐⭐⭐
布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。
关键是flex布局能触发BFC规范
Flexible box设置或检索弹性盒模型对象的子元素如何分配空间
align-items和justify-content的区别
水平的主轴(main axis)和垂直的交叉轴(cross axis)
flex-direction 属性决定主轴的方向(也就是排列方向)。有4个属性值可以设置。
- column:主轴为垂直方向,起点在上沿。
- column-reverse:主轴为垂直方向,起点在下沿。
- row(默认值):主轴为水平方向,起点在左端。
- row-reverse:主轴为水平方向,起点在右端。
- align-items 属性定义项目在交叉轴上如何对齐。
baseline | 元素位于容器的基线上。 如弹性盒子元素的行内轴与侧轴为同一条,则该值与'flex-start'等效。其它情况下,该值将参与基线对齐。 |
stretch | 默认值。元素被拉伸以适应容器。 如果指定侧轴大小的属性值为'auto',则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照'min/max-width/height'属性的限制。 |
- justify-content 属性定义了项目在主轴上的对齐方式。
space-between | 均匀排列每个元素,首个元素放置于起点,末尾元素放置于终点。 |
space-evenly | 均匀排列每个元素,每个元素之间的间隔相等。 |
space-around | 均匀排列每个元素,每个元素周围分配相同的空间。 |
flex:1
flex 属性是 flex-grow, flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。
flex 属性属性有两个快捷值:auto
(1 1 auto
) 和 none (0 0 auto
)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
/* 一个值,width/height: flex-basis */
flex: 10em;
flex: 30px;
flex: min-content;
/* 两个值:flex-grow | flex-basis */
flex: 1 30px;
/* 两个值:flex-grow | flex-shrink */
flex: 2 2;
/* 三个值:flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;
flex-grow 属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。
负值对该属性无效。
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小
BFC规范⭐⭐⭐
问题
- 外边距重叠:
块的上外边距margin-top和下外边距margin-bottom会合并为单个边距(为单个边距的最大值)
- 浮动导致父高度塌陷:
- 不浮动的元素被浮动元素覆盖:
BFC块级格式化上下文(Block Fromatting Context)
决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用
独立布局,盒子内子元素样式不会影响到外面的元素。
常见触发条件
- overflow: hidden
- display: flex | inline-block | table-cell
- position: absolute | fixed
规则
BFC
就是一个块级元素,块级元素会在垂直方向一个接一个的排列BFC
就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签- 垂直方向的距离由margin决定, 属于同一个
BFC
的两个相邻的标签外边距会发生重叠 - 计算
BFC
的高度时,浮动元素也参与计算
overflow: hidden示例
overflow属性指定如果内容溢出一个元素的框,会发生什么
值 | 描述 |
---|---|
visible | 默认值。内容不会被修剪,会呈现在元素框之外。 |
hidden | 内容会被修剪,并且其余内容是不可见的。 |
scroll | 内容会被修剪,但是浏览器会显示滚动条以便查看其余的内容。 |
auto | 如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。 |
inherit | 规定应该从父元素继承 overflow 属性的值。 |
overflow:hidden
- 避免外边距重叠
- 清除浮动
- 阻止元素被浮动元素覆盖:
单位⭐⭐⭐
- 绝对长度单位:px 像素
- 百分比: %
- 相对父元素字体大小单位: em
- 相对于根元素字体大小的单位: rem(默认16px)
- 相对于视口*宽度的百分比(100vw即视窗宽度的100%): vw
- 相对于视口*高度的百分比(100vh即视窗高度的100%): vh
px转rem
相对于根元素字体大小的单位: rem(默认16px)
PostCss是一个用JavaScript工具和插件转换CSS代码的工具。postcss-pxtorem
px转vw
网页宽度=1920px 网页高度=1080px
1920px = 100vw
1080px = 100vh
宽 300px 和 200px 的 div ,其所占的宽高,以 vw 和 vh 为单位
vwDiv = (300px / 1920px ) * 100vw
vhDiv = (200px / 1080px ) * 100vh
当屏幕放大或者缩小时,div 还是以 vw 和 vh 作为宽高的,就会自动适应不同分辨率的屏幕
可自定义scss函数。
$vm_base: 1920;
$vh_base: 1080;
@function vw($px) {
@return ($px / $vm_base) * 100vw;
}
@function vh($px) {
@return ($px / $vh_base) * 100vh;
}
.head{
font-size:vh(100);
}
opacity: 0、visibility: hidden、display: none⭐⭐⭐
区别 | opacity: 0 | visibility: hidden | display: none |
页面布局 | 不改变 | 不改变 | 改变 |
触发事件 | 能触发 | 不能触发 | 不能触发 |
行内素、块级元素和行内块元素⭐⭐⭐
display:inline;// 转换为行内元素
display:block;// 转换为块级元素
display:inline-block// 转换为行内块元素
从 HTML 的角度来讲,标签分为:
- 文本级标签:p、span、a、b、i、u、em
- 容器级标签:div、h系列、li、dt、dd
行内元素:除了p之外,所有的文本级标签,都是行内元素,p是个文本级,但是是个块级元素
块级元素:所有的容器级标签都是块级元素,还有p标签
块标签:div、h1~h6、ul、li、table、p、br、form。
特征:独占一行,换行显示,可以设置宽高,可以嵌套块和行
行标签:span、a、img、textarea、select、option、input。
特征:只有在行内显示,不会自动进行换行,内容撑开宽、高,不可以设置宽、高(img、input、textarea等除外)。(设置float后可以设置宽、高)
对 margin 仅设置左右方向有效,上下无效,padding 设置上下左右都有效
响应式布局⭐⭐
- 使用媒体查询(@media)
- 使用flex弹性布局
- 使用百分比单位:rem单位,VH、HW单位