CSS 知识总结

100 阅读15分钟

1.关于CSS

CSS是李爵士(Tim Berners-Lee)的挪威同事赖先生(Hakon Wium Lie)首先提出的。

CSS全称为Cascading Style Sheets,中文名叫层叠样式表。它是一种用来为结构化文档(如HTML文档或XML应用)添加样式(字体、间距和颜色等)的计算机语言,由W3C定义和维护。

层叠的三种结构:

  • 样式层叠:可以多次对同一选择进行样式说明;
  • 选择器层叠: 可以用不同选择器对同一个元素进行样式说明;
  • 文件层叠: 可以用多个文件进行层叠。

历史版本:

  • CSS1 1996年发明
  • CSS2 1998年发明
  • CSS2.1 2004年~2011年(使用最广泛的版本 IE支持)
  • CSS3 1999年开始起草 现代版本,分模块(IE8部分支持)

通过caniuse网站可以得知哪些浏览器支持CSS哪些特性

2.关于文档流(Normal Flow)

元素流动方向:

  • inline元素(内联元素):从左到右,到最右边才会换行; <span>
  • block元素(块级元素):从上到下,每一个都会起另起一行; <div>
  • inline-block元素也是从左到右。

宽度(width)

  • inline元素宽度为内部inline元素的和 不能用width指定宽度
  • block元素默认自动计算宽度,可用width指定(默认auto,不是100%,最好不设100%);
  • inline-block结合前两者特点,可用width指定。

高度(height)

  • inline元素高度由line-height(行高,也就是实际高度)间接决定(跟字体相关),跟height无关;
  • block高度由内部文档流元素决定,可以设height
  • inline-block跟block类似,可以设height

内容溢出(overflow)

当内容宽度或高度大于容器的宽或高,会溢出

overflow属性

  • overflow: auto 灵活设置(常用)
  • overflow: scroll 永远显示滚动条
  • overflow: hidden 隐藏溢出部分
  • overflow: visible 可看见
  • 可分为overflow-x, overflow-y(x横y竖)

脱离文档流

  • floatposition:absoluteposition:fixed可使元素脱离(跳出)文档流

3.关于盒模型(Box-Sizing)

盒模型

盒模型类型:

  1. content-box 内容盒-内容就是盒子的边界
  2. border-box 边框盒-边框就是盒子的边界

公式:

  • content-box width=内容宽度
  • border-box width=内容宽度+padding+border

margin合并

margin合并是指块级元素的上外边距与下外边距有时会合并为单个外边距。两种情况:父子合并;兄弟合并。

如何阻止合并

父子合并:

  1. 给父容器添加padding/border
  2. 给父容器加overflow:hidden(溢出的元素就会被浏览器隐藏);
  3. 给父容器加display: flex

兄弟合并(符合预期)

  • 给两个div设置display:inline-blcok,并添加 ️width:100%

基本单位

长度单位

  • px(像素)
  • em(相对于自身font-size的倍数)
  • 百分数
  • 整数
  • rem
  • vw、vh

颜色

  • 十六进制 例如#FF6600/#F60
  • RGBA颜色 例如rgb(0,0,0)rhba(0,0,0,1)
  • hsl颜色 例如hsl(360,100%,100%)

4.CSS布局(Display/Layout)

分类

  1. 固定宽度布局 一般为960/1000/1024px (pc端)
  2. 不固定宽度布局 主要靠文档流原理布局 (手机端)
  3. 响应式布局 pc上固定 手机上不固定

布局思路

  1. 从大到小,先定下大局,然后完善每个部分的小布局
  2. 从小到大,先完成小布局,然后组成大布局。

如何决定使用何种布局

再决定用何种布局时要根据两点 1.是否兼容IE92.是否兼容最新浏览器 下面给出图 布局

  • float布局:当需要兼容IE浏览器时使用

  • flex布局:可以简便、完整、响应式地实现各种页面布局

  • grid布局:最强大的布局

必要时可以使用负margin来布局,这里做个提醒

float布局(IE)

重要步骤

  1. 子元素上加float:leftwidth
  2. 父元素上加.clearfix
    .clearfix:after{
        content:'';
        display:block;
        clear:both;
    }

tips

  1. 最后一个标签不设width,可以加max-width: 100%;
  2. 不用做响应式
  3. IE6/7存在双倍margin bug 解决办法:加display:inline-block
  4. 若发现图片下面有多余的背景色,加vertical-align:topvertical-align:middle
  5. 让元素居中:加margin-left:automargin-right:auto这样不会占用其他margin
  6. 若要做平均图层,在父级元素加上X(加.clearfix),再用负margin,例如margin-right= -5px

flex布局

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器";它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。

容器(container)属性

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

让一个元素变成容器

.container{
  display: flex;
}

.container{
  display: inline-flex;
}

flex-direction:属性决定主轴的方向(即项目的排列方向)。

.container{
  flex-direction: row | row-reverse |  column | column-reverse;
}

flex-wrap:默认情况下,项目都排在一条线(又称"轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}

flex-flowflex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap

.container {
  flex-flow: <flex-direction> || <flex-wrap>;
}

justify-content:属性定义了项目在主轴上的对齐方式。

.container{
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}

align-items:属性定义项目在交叉轴上如何对齐。

.container{
  align-items: stretch | flex-start | flex-end | center | baseline;
}

align-content:属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

.container{
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

项目(item)属性

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

order:属性定义项目的排列顺序。数值越小,排列越靠前,默认为0

.item {
  order: <integer>;
}

flex-grow:属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

.item {
  flex-grow: <number>; /* default 0 */
}

flex-shrink:属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

.item {
  flex-shrink: <number>; /* default 1 */
}

flex-basis:属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

.item {
  flex-basis: <length> | auto; /* default auto */
}

flexflex属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。后两个属性可选。

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

align-selfalign-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

重点记住

  • display: flex
  • flex-direction:row | column
  • flex-wrap:wrap
  • justify-content:center | space-between
  • align-items: center

tips

  1. 永远不要把heightwidth写死,除非特殊说明;
  2. 尽量用min-width | max-width | min-width | max-height
  3. flex布局基本可以满足所有需求
  4. flex布局与margin-xxx:auto配合有意外效果

Grid布局

网格布局(Grid)是最强大的 CSS 布局方案。

容器和项目

采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item)。

行和列

容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。 行和列

上图中,水平的深色区域就是"行",垂直的深色区域就是"列"。

单元格

行和列的交叉区域,称为"单元格"(cell)。

正常情况下,n行和m列会产生n 乘以 m个单元格。比如,3行3列会产生9个单元格。

网格线

划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列。

正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。

容器(container)属性

  • display
  • grid-template-columns | grid-template-rows
  • grid-row-gap | grid-column-gap | grid-gap
  • grid-template-areas
  • ...

displaydisplay: grid指定一个容器采用网格布局。

div {
  display: grid;
}

grid-template-columns | grid-template-rows容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。

.container {
  display: grid;
  grid-template-columns: 100px 100px 100px;
  grid-template-rows: 100px 100px 100px;
}
为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr2fr,就表示后者是前者的两倍。
.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
fr可以与绝对长度的单位结合使用,这时会非常方便。
.container {
  display: grid;
  grid-template-columns: 150px 1fr 2fr;
}

grid-row-gap | grid-column-gap | grid-gapgrid-row-gap属性设置行与行的间隔(行间距),grid-column-gap属性设置列与列的间隔(列间距)。grid-gap属性是grid-column-gapgrid-row-gap的合并简写形式。

.container {
  grid-row-gap: 20px;
  grid-column-gap: 20px;
}

等于

.container {
  grid-gap: 20px 20px;
}

grid-template-areas:网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域。示例:

.item-a{
  grid-area:header;
}
.item-b{
  grid-area:main;
}
.item-c{
  grid-area:sidebar;
}
.item-d{
  grid-area:footer;
}
.container{
  display:grid;
  grid-template-columns:50px 50px 50px 50px;
  grid-template-rows:auto;
  grid-template-areas:"header header header header"
                      "main main . sidebar"
                      "footer footer footer footer"
}

便会造出如下图所示的布局

areas

grid属性更多资料来源于CSS Grid 网格布局教程-作者阮一峰

5.CSS定位(Position)

布局是屏幕平面上的 定位是垂直于屏幕的

盒模型定位

背景范围是border外边沿围成的区域

一个div的分层

div的分层

position的属性

  • static默认值,待在文档流里
  • relative相对定位,元素会升起来,但不脱离文档流
  • absolute绝对定位,定位基准是祖先里的非static元素
  • fixed固定定位,定位基准是viewport(浏览器窗口)
  • sticky粘滞定位

tips

  1. 如果写了absolute,一般都要补一个relatvie(有绝对就有相对)
  2. 如果写了absolutefixed,一定要补topleft
  3. sticky兼容性很差,很少用
  4. position:relative可配合z-index使用,很少用

关于z-index

z-index 属性设定了一个定位元素及其后代元素或 flex 项目的 z-order。 当元素之间重叠的时候, z-index 较大的元素会覆盖较小的元素在上层进行显示。取值为整数。 z-index:auto不会创建新的层叠上下文 作用:

  1. 用于做位移(少用)
  2. 用于给absolute做父元素

position: static

staticposition属性的默认值。如果省略position属性,浏览器就认为该元素是static定位。

这时,浏览器会按照源码的顺序,决定每个元素的位置,这称为"正常的页面流"(normal flow)。每个块级元素占据自己的区块(block),元素与元素之间不产生重叠,这个位置就是元素的默认位置。

position: relative

relative相对定位表示,相对于默认位置(即static时的位置)进行偏移,即定位基点是元素的默认位置。 它必须搭配topbottomleftright这四个属性一起使用,用来指定偏移的方向和距离。

div {
  position: relative;
  top: 20px;
}

上面代码中,div元素从默认位置向下偏移20px(即距离顶部20px)。

position: absolute

absolute绝对定位表示,相对于上级元素(一般是父元素)进行偏移,即定位基点是父元素。

它有一个重要的限制条件:定位基点(一般是父元素)不能是static定位,否则定位基点就会变成整个网页的根元素html。另外,absolute定位也必须搭配topbottomleftright这四个属性一起使用。

使用场景:脱离原来位置,另起一层(比如对话框的关闭按钮或者是鼠标提示) 配合z-index使用

/*
  HTML 代码如下
  <div id="father">
    <div id="son"></div>
  </div>
*/

#father {
  positon: relative;
}
#son {
  position: absolute;
  top: 20px;
}

上面代码中,父元素是relative定位,子元素是absolute定位,所以子元素的定位基点是父元素,相对于父元素的顶部向下偏移20px。如果父元素是static定位,上例的子元素就是距离网页的顶部向下偏移20px

tips

  • 某些浏览器上如果不写top/left会位置错乱
  • 善用left: 100%以及left:50%加负margin
  • absolute是相对于祖先元素中最近的一个定位元素

position: fixed

fixed固定定位表示,相对于视口(viewport,浏览器窗口)进行偏移,即定位基点是浏览器窗口。这会导致元素的位置不随页面滚动而变化,好像固定在网页上一样。

它如果搭配top、bottom、left、right这四个属性一起使用,表示元素的初始位置是基于视口计算的,否则初始位置就是元素的默认位置。

使用场景:烦人的广告/回到顶部的按钮,配合z-index使用

div {
  position: fixed;
  top: 0;
}

上面代码中,div元素始终在视口顶部,不随网页滚动而变化。

tips:手机上尽量不用,坑很多

position: sticky

sticky粘滞定位跟前面四个属性值都不一样,它会产生动态效果,很像relativefixed的结合:一些时候是relative定位(定位基点是自身默认位置),另一些时候自动变成fixed定位(定位基点是视口)。

因此,它能够形成"动态固定"的效果。比如,网页的搜索工具栏,初始加载时在自己的默认位置(relative定位)。

层叠上下文(堆叠上下文)

  • 使用了position属性以后,会超越内联子元素,成为定位元素。
  • 每个层叠上下文就是一个新的小世界(作用域)
  • 这个小世界里面的z-index跟外界无关,处在同一个小世界的z-index才能比较
  • background只影响背景色,opacity影响所有元素的透明度(包括文字等)
  • 不正交属性可创建层叠上下文:z-index | flex | opacity | transform
  • 负index逃不出小世界

6.CSS动画(Animation)

动画是由许多静止的画面(也称“帧”)以一定的速度(如每秒30张)连续播放时肉眼因视觉残象产生错觉而误以为是活动的画面。

在CSS中,最简单的例子是div从左往右移动

  • 原理:每过一段时间用计时器(js中的setInterval)将div移动,直到移到目标地点。
  • 老手用transform:translateX()以及transition过渡,比上面的好。

浏览器渲染原理

参考文章

浏览器渲染过程

  1. 根据HTML构建HTML树(DOM)
  2. 根据CSS构建CSS树(CSSOM)
  3. 将两棵树合并成一棵渲染树(render tree)
  4. Layout布局(文档流、盒模型、计算大小和位置)
  5. Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  6. Compose合成(根据层叠关系展示画面)

具体过程如图所示 渲染树

浏览器如何更新样式

一般用js来更新样式 js更新样式

  1. JS/CSS>样式>布局>绘制>合成
  2. JS/CSS>样式>绘制>合成(改变背景颜色,直接repaint和composite)
  3. JS/CSS>样式>合成(改变transform,只需composite) 注意必须全屏查看效果,在开发者工具里的iframe查看问题(报错)

CSS动画优化

  1. JS优化:使用requestAnimationFrame代替setTimeoutsetInterval
  2. CSS优化:使用will-changetranslate

transform属性

  1. translate位移
  2. scale缩放
  3. rotate旋转
  4. skew倾斜

tips

  • 一般都需要配合transition过渡
  • inline元素不支持transform,需要先变成block元素

translate位移

常用写法

  • transform: translateX(<length | percentage>)
  • transform: translateY(<length | percentage>)
  • transform: translate(<length | percentage>,<length | percentage>)
  • transform: translate(<length>)且父容器perspective
  • transform: trabslate3d(x,y,z)

tips

  • 要学会看懂MDN语法示例
  • translate(-50%,-50%)可做绝对定位元素的居中

scale缩放

常用写法

  • transform: scaleX(<number>)
  • transform: scaleY(<number>)
  • transform: scale(<number>,<number>) tips
  • 用得比较少,会使内容变模糊

rotate 旋转

常用写法

  • transform: rotate([<angle> | <zero>])
  • transform: rotateZ([<angle> | <zero>])
  • transform: rotateX([<angle> | <zero>])
  • transform: rotateY([<angle> | <zero>]) tips
  • 一般用于360度旋转制作loading

skew倾斜

常用写法

  • transform: skewX([<angle> | <zero>])
  • transform: skewY([<angle> | <zero>])
  • transform: skew([<angle> | <zero>],[<angle> | <zero>]) tips
  • 用得少,用得到的时候查阅MDN文档

多重效果(组合使用)

例如transform: scale(0.5) translate(-100%, -100%);transform:none tips

  • CSS需要有想象力,而不是逻辑
  • CSS给出的属性很简单,但可以组合得很复杂

transition过渡

作用:补充中间帧

语法

  • transition:属性名,时长,过渡方式,延迟
  • transition:all

过渡方式:linear|ease|ease-in|ease-out|ease-in-out|cubic-beizer|step-start|step-end|steps

具体查看这里

tips

  • 并不是所有属性都能过渡
  • display: none变成display: block或反过来不能过渡
  • 若要有淡入或淡出的过渡效果一般写visibility:hiddenvisibility:visible
  • background颜色可以过渡
  • opacity透明度可以过渡
  • 过渡必须要有起始,若有中间变化,可以使用两种方法
  1. 使用两次transform
.a===transform===>.b
.b===transform===>.c

然后用setTimeout或者监听transitionend事件

  1. 使用animation 需要声明关键帧(keyframes),添加动画;若需要动画停在最后一帧,在后面加forwards

@keyframes完整语法

一种是frmo...to...(从...到...) 另一种是百分数

@keyframes slidein {
  from {
    transform: translateX(0%); 
  }

  to {
    transform: translateX(100%);
  }
}

@keyframes identifier{
  0%{top:0; left:0;}
  30%{top:50px};
  68%,72%{left:50px;}
  100%{top:100px;left:100px;}
}

animation缩写语法

animation: 时长|过渡方式|延迟|次数|方向|填充模式|是否暂停|动画名

  • 时长:1s或者1000ms
  • 过渡方式:跟transition取值一样,如linear
  • 次数:正整数或infinite(无限)
  • 方向:reverse|alternate|alternate-reverse
  • 填充模式:none|forwards|backwards|both
  • 是否暂停:pasued|running 以上属性都有对应的单独属性

小白学习经验分享,若有错误或缺漏,请私信指正,不胜感激