css由Håkon Wium Lie首先提出
体系化学习
学一门语言必须学会什么?
- 语法(怎么写代码)
- 如何调试(怎么知道自己的代码写错了)
- 在哪查资料(抄代码)
- 标准制定者是谁
语法一:样式语法
选择器 {
属性名:属性值;
/*注释*/
}
例:
p {
color: pink;
/* 字体颜色为粉红色 */
}
【注】
- 所有符号都是英文符号,写错了浏览器会警告
- 区分大小写
- 注释为/* */
语法二:@语法
@charset “UTF-8”;
@import url(2.css);
@media (min-width:100px) and (max-width:200px){
}
【注】
- charset必须放在第一行
- charset是字符集的意思,但UTF-8是字符编码encoding(文件编码),这是历史遗留问题(UTF有9、16、32好几种需要区分)
- 前两个@必须以分号;结尾
- @media以后单独提出来
如何调试
方法:
- 使用W3C验证器
- 使用VSCode看颜色
- 使用webstorm看颜色
- 使用开发者工具看警告
如何使用开发者工具:
- 找到标签
- 看它是否有选择器
- 看它样式是否被划掉
- 看它样式是否有警告
Border调试法
步骤:
- 怀疑某个元素有问题,给这个元素加个border逐次检验
- border没出现?说明选择器错了或者语法错了
- border出现了?看边界是否符合预期
- bug解决后把border删掉
在哪查资料
网站推荐
- Google搜索关键词加MDN
- CSS tricks (英文)
- 张鑫旭的博客
在哪搜练习素材
PSD
- Freepik搜索PSD web(有免费版,注意限定版权问题)
- 中文版有365PSD——UI套件
效果图(不提供下载)
- dribbble.com顶级设计师社区,可以模仿
商业网站
- 模拟常去的网站
几个重要基本概念
- 文档流Normal Flow
- 块、内联、内联块
- margin合并
- 两种盒模型(border-box更符合人类思维)
文档流
流动方向
- inline元素从左到右,到达最右边才会换行(同一部分可以跨行)
- block元素从上到下,每一个都独占一行
- inline-block从左到右,但同一部分不跨行
宽度
- inline宽度为内部inline元素之和(尽量窄),不能用width指定
- block默认自动计算宽度(是auto,不是100%),可用width
- inline-block结合前两者的特点:尽量窄,但可用width
高度
- inline高度由line-height间接决定,与height无关
- block高度由内部文档流元素决定,可以设height
- inline-block与block类似,可设置height
overflow
- 当内容的宽、高大于容器时会溢出,可用overflow来设置是否显示滚动条
- auto灵活设置(溢出则显示,未溢出则不显示);scroll默认显示;hidden直接隐藏溢出部分,拖动不可见;visible直接显示溢出部分;
- overflow-x和overflow-y可以使用,但可能出现bug,暂时不建议
脱离文档流
- float
- position:absolute/fixed;
盒模型
box-sizing: border-box | content-box;
Tips:
- 可以使用caniuse.com来查看css、grid等样式的兼容性
- 记住一个概念:没有定死的块级元素和内联元素之分,因为任何元素都可以变成块级或者内联的(display:block;——display:inline),可以说现在该元素是内联的或块级的
- 不要写宽度100%!!
- 不要在inline里面写block
- 内联元素不接受width和height直接指定宽高
- (用border测试法会发现) div无内容会默认有auto的宽度但不会有高度; span无内容会有line-height默认高度但不会有宽度。 简单来说就是:div无内容则无高度
CSS布局
布局分类:
- 固定宽度布局,一般为960/1000/1024px
- 不固定宽度布局,主要靠文档流原理布局(多见于手机)文档流自适应,不需要加额外的样式
- 响应式布局。意思就是PC上固定宽度、手机上不固定宽度。也就是一种混合布局
布局思路一图流
float布局
步骤
- 子元素上加 float:left和width
- 父元素上加 .clearfix 很重要!
- 因为float后的元素会脱离文档流,父元素加上.clearfix后父元素才会有高度。 (html里的父元素加上class=”clearfix”;css里写出
.clearfix::after {
content: '';
display: block;
clear: both;
}
)
经验
- 留一些空间或者最后一个不设宽度(可以设个最大宽度)
- float布局不需要做响应式,因为手机上无ie,这个布局是专门为ie准备的
- ie6/7存在双倍margin的bug,解决方式有两种 n 将错就错,把margin减半 _margin-left:5px; n 或者,加个display:inline-block;
- _margin-left是ie可识别的,其他网页不识别,正常margin就好
平均布局
- 如果margin布局发现最后多出了一部分margin,在中间加一个div,对该div的样式使用-margin
- 如果在其他地方有个margin-top:10px;使用下面的就不会覆盖
- 如果设置了宽度,且左右分别auto,会直接居中(只针对块元素)
margin: 0 auto;
/* 下面的两句得分高,因为不会覆盖掉上下边距 */
margin-left: auto;
margin-right: auto;
flex布局
flex container样式
先既定一个container和一个item
-
display:flex | inline-flex;(有些类似inline-block)
-
container的主轴方向由他自己控制(比如从左到右、从上到下)
flex-direction:column;(从上到下,默认是row从左到右)
flex-direction:row-reverse;(从右到左)
flex-direction:column-reverse;(从下到上)
-
折行
flex-warp: nowrap;(默认不折行,会挤在一起,导致宽度变窄)
flex-wrap:wrap;(折行,宽度不够会折行)
flex-wrap:wrap;(从下往上折行,一般没啥用)
主轴对其方式
- 默认主轴是横轴,除非改变了flex-direction的方向(前四个比较重要)
次轴对齐方式
- 默认次轴是纵轴
多行内容
- 基本不用
flex item样式
顺序
- 在item上加order,可以改变item的顺序(从小到大,可以有负)
长胖
- 在item上加flex-grow,可以改变各个item的宽度(在不加宽度的情况下,默认为等宽且尽可能窄)
变瘦
- 一般写flex-shrink:0; 防止变瘦,默认为1(谁的数大谁贡献的多)
基准宽度
-
flex-basis控制基准宽度,默认是auto(暂时是不知道干嘛的)Question 缩写
-
flex:flex-grow flex-shrink flex-basis;(有shrink的时候必须加宽度)
一个有宽度的值会被当作flex-basis
定制
- align-self定制align-items 例如:某个元素单独align-self:flex-end;(该元素单独居下)
重点:
- display:flex;
- flex-direction:row / column;
- flex-wrap:wrap / nowrap;
- just-content: center / space-between;
- align-items:center;
经验
-
永远不要把width和height写死,除非特殊情况
-
用min-width / max-width / min-height / max-height
-
flex可以基本满足所有需求
-
flex和margin-left / right:auto配合有意外效果
-
写死
-
width:100px;
-
不写死 (特点:不使用px,或者min max前缀)
-
width:50%;
-
max-width:100px
-
width:30vw;
-
min-width:80%
Tips:
- 如果发现图片下面有多余的部分(奇怪的空隙)就在css里面加上一行:
vertical-align:middle/top;
- 如果border调试的时候影响了,就把border改成outline
- (布局谨记:浮动浮动、clearfix)
Grid布局
grid也分container和items
.container {
display: grid | inline-grid;
}
container
可以划分大小
.container {
display: grid;
grid-template-columns: 50px 100px auto 100px 50px;
grid-template-rows: 50px 100px 50px;
}
分别以线分为第几行列
item
语法如上图所示(n表示第几根线)
.item-a { grid-row-start:n;
grid-row-end:n;
grid-column-start:n;
grid-column-end:n;
}
fr
free space
.container {
display: grid;
/* outline: solid 1px black; */
background-color: skyblue;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
width: 600px;
grid-column-gap: 13px;
grid-row-gap: 13px;
}
img {
outline: red 1px solid;
height: 191px;
width: 191px;
}
效果如图
空隙gap
- grid-column-gap:10px;
- grid-row-gap:15px;
空隙gap效果图
分区grid-template-areas
空隙gap设置同上
分区grid-template-areas代码
分区grid-template-areas效果图
CSS定位
布局和定位有啥区别
- 布局是屏幕平面上的
- 定位是垂直于屏幕的
- 背景的范围:border外边沿围成的区域
position的五个取值
position
- static ——待在文档流里,默认值
- relative ——相对定位,升起来,但不脱离文档流
- absolute ——绝对定位,定位基准是祖先里的非static(不一定是relative)
- fixed ——固定定位,定位基准是viewport视口(有诈——transform) sticky ——粘滞定位,不好描述
经验:
- 如果写了absolute,一般都会补一个relative
- 如果写了absolute或fixed,一定要补top和left
- sticky兼容性很差,主要用于装逼
position: relative;
使用场景
- 用于做位移(很少用)
- 用于给absolute元素做父亲(比如子绝父相) 配合z-index
- z-index:auto默认值,不创建新层叠上下文
- z-index:0/1/2
- z-index:-1/-2
position: absolute;
使用场景
- 脱离原来的位置,另起一层,比如对话框的关闭按钮
- 鼠标提示 配合z-index 经验
- absolute不是相对于relative定位的,而是相对于最近的一个非static的祖先元素
- 某些浏览器如果不写top/left会位置混乱
- 善用left:100%;
- 善用left:50% 加 负margin值;
position: fixed;
使用场景
- 小广告(因为相对于视口,所以划不掉)
- 回到顶部 配合z-index 经验
- 手机上尽量不要用这个属性,坑很多;不信可以搜索 移动端fixed
- transform: scaleZ(1); ——不要和transform一起用,会出问题
position: sticky;
使用场景
- 导航栏
- 页封 (看得见时随页面滑动,本应该看不见时,固定在页面的某个位置) 经验
- 兼容性极差
- 不要使用,会变得不幸
Tips:
- white-space:nowrap; ——文字内容不转行
- button span{ display:none;} ——默认不显示
- button: hover span{ display:inline-block;} ——搭配上一句:光标提示
- left: 50%;
transform: translateX(-50%); ——会自动居中(后面有)
层叠上下文
- 每个层叠上下文独立成一个作用域
- 单个作用域里的index-z与外界无关
- 处于同一作用域的index-z才能比较
哪些不正交的属性可以创建层叠上下文
- MDN文档有写
- 速记: z-index / flex / opacity(<1) / transform
- 不用太花时间记
例:
- a、b在html里,而a1在a里,b1在b里
- 当a index-z:0;a1 index-z:10; b1 index-z:8;最后是b>a1。 因为b是和作用域a里的a1比(相当于8和0比)
- 当a1 index-z:10; b1 index-z:8; 最后是b<a1。 因为b是直接和a1比
Tips:
如果a在一个层叠上下文b的作用域内, 就算a z-index:-1;也不会跑到背景下面去
CSS动画
动画的原理
定义
许多静止的画面(帧)
以一定速度(如每秒30张)连续播放时
肉眼视觉残像产生错觉
而误以为是活动的画面
概念
帧:每个静止的画面都叫做帧 播放速度:每秒24帧
用left做动画
举例 将div从左移动到右
原理 每过一段时间 将div移动一段距离 直到移动到目标地点
注意性能
- 绿色表示重新渲染(repaint)了
- CSS渲染过程以此包含布局、绘制、合成
- 其中布局和绘制有可能被省略
注:
用setInternet做到 F12——Esc——rendering——Paint flashing
例:
<div id="demo">动画</div>
#demo {
width: 100px;
height: 100px;
border: 1px solid red;
background: rgba(255, 0, 0, 0.322);
position: relative;
left: 0;
}
var n = 1
var id = setInterval(() => { //定时器
if (n <= 800) {
demo.style.left = n + "px" //一定要加px,不然无反应
n = n + 1
}
else {
clearInterval(id) //当>800px运动,否则清除定时
}
}, 1000 / 120)
用transform做动画
高手不用left做动画
原理
- transform:translateX(0=>300px)
- 直接修改会被合成,需要等一会修改
- transition过渡性可以自动脑补中间帧 注意性能
- 并没有repaint,只在开始和结束repaint(重新绘制)
- 比left性能好
渲染
浏览器渲染过程
步骤
- 根据HTML构建HTML树(DOM)
- 根据CSS构建CSS树(CSSOM)
- 将两棵树合并成一棵渲染树(render tree)
- Layout布局(文档流、盒模型、计算大小和位置)
- Paint绘制(把边框颜色、文字颜色、阴影等画出来)
- Compose合成(根据层叠关系展示画面)
如何更新样式
一般用JS更新样式,如下
-
div.style.background='red'
-
div.style.display='none'
-
div.classList.add('red')
-
div.remove()直接删掉节点
这些方式有何不同
三种更新方式
第一种,全走
- div.remove()会触发当前消失,其他元素relayout 第二种,跳过layout
- 改变背景颜色,直接跳过repaint+composite 第三种,跳过layout和paint
- 改变transform,只需composite 注意必须全屏查看效果,在iframe里看有问题 优化 参考Google文章
transform
transform 四个常用功能
- 位移translate
- 缩放scale
- 旋转rotate
- 倾斜skew 经验
- 一般都需要配合transition过渡
- inline元素不支持transform,需要先变成block
transition
transitation过渡
作用 补充中间帧(比如鼠标移进移出)
语法
transition:属性名 时长 过渡方式 延迟
- transition:left 200ms linear
- 可以用逗号分隔两个不同属性
- 可以用all代表所有属性
- transition:all 200ms
- 过渡方式有:linear(线性) l ease(非线性)丨ease-in(淡入)丨ease-out(淡出) | ease-in-out(淡入淡出) | cubic-bezier l step-star | step-end丨steps,具体含义靠数学知识
中间点
- 使用两次transform
- .a === transform ===> .b
- .b === transform ===> .c
- 可以用setTimeout或监听transition事件
- 使用animation
- 声明关键帧
- 添加动画
Tips:
- 不是所有属性都能过渡
- display:none => block 就无法过渡(看不见到看见无法直接过渡,只会突然出现)
- 一般可以用visibility:hidden => visible
- background颜色可以过渡
- opacity透明度可以过渡
display: none;与 visibility: hidden;的区别
- 是否继承 display不是继承属性;visibility是继承属性,后代元素存在visibility则不继承,不存在则继承。
- 是否占据空间 display:none;在文档渲染时,元素如同不存在;visibility:hidden;空间会被空白占位。
- 是否重新渲染(页面相关属性值被修改后) display:none;不渲染; visibility:hidden;渲染。