avatar

前端知识梳理之CSS篇

写作背景

女朋友要我教她CSS,于是我就折腾了一周,终于完成了这篇长文…

然后,然后?然后当我发布这篇文章的时候,她会感动到哭吗?

熟悉HTML知识

HTML常见元素

head 部分

body部分

doctype的意义是什么

  • 让浏览器以标准模式渲染
  • 让浏览器知道元素的合法性

HTML、XHTML、HTML5的关系

  • HTML属于SGML(标记语言)
  • XHTML属于XML,是HTML进行XML严格化的结果
  • HTML5不属于SGML或XML,比XHTML宽松

    HTML5有什么变化

  • 新的语义化元素
  • 表单增强
  • 新的API(离线、音视频、图形、实时通信、本地存储、设备能力)
  • 分类和嵌套变更

em和 i 有什么区别

  • em是语义化的标签,表强调
  • i 是纯样式的标签,表斜体
  • HTML5中 i 不推荐使用,一般用作图标

语义化的意义

  • 开发者容易理解
  • 机器容易理解(搜索、读屏、软件)
  • 有利用SEO
  • semantic microdata(语义微数据)例电影有评分

哪些元素可以自闭合

  • 表单元素 input
  • 图片 img
  • br hr
  • meta link

HTML和DOM关系

  • HTML是“死”的(字符串)
  • DOM是由HTML解析而来的,是活的
  • JS可以维护DOM

property 和 attritube 区别

  • attritube 是“死”的
  • property 是活的
  • 相互之间不会影响

form的好处

  • 直接提交表单
  • 使用 submit / reset 按钮
  • 便于浏览器保存表单
  • 第三方库可以整体取值
  • 第三方库可以进行表单验证

CSS精华(Cascading Style Sheet)层叠样式表

选择器

  • 用于适配HTML元素
  • 分类和权重
  • 解析方式和性能
  • 值得关注的选择器

选择器分类

  • 元素选择器 a{}
  • 伪元素选择器 ::before{}
  • 类元素选择器 .link{}
  • 属性选择器 [type=radio]{}
  • 伪类选择器 :hover{}
  • ID选择器 #id{}
  • 组合选择器 [type=checkbox] + label{}
  • 否定选择器 :not(.link){}
  • 通用选择器 *{}

选择器权重(1)

  • ID选择器 #id{}+100
  • 类 属性 伪类 +10
  • 元素 伪元素 +1
  • 其它选择器 +0

例子:计算一个不进位的数字

#id.link a[href]
————————————————
计算过程:
#id +100
.link +10
a +1
[href] +0
结果:111
#id .link.active
————————————————
计算过程:
#id +100
.link +10
.active +10
结果:120

那么,我们怎么理解 不进位的数字 这关键字眼呢?用一个简单例子吧:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS选择器</title>
<style>
#test1{
color: red;
}
#test1.test1{
color: blue;
}
.test2{
color: red;
}
div.test2{
color: blue;
}
#test3{
color: red;
}
.c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11{
color: blue;
}
</style>
</head>
<body class="body" id="body">
<div id="test1" class="test1">蓝色</div>
<div class="test2">蓝色</div>
<div id="test3" class="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11">红色</div>
</body>
</html>

结果如下图所示:

不妨发现,最后一个 div,尽管我们类选择器有11个,加起来有110,但是依旧没有 id 选择器优先级高,正是因为这个不进位的数字,简单说:你大爷还是你大爷!

选择器权重(2)

  • !important 优先级最高
  • 元素属性 优先级高
  • 相同权重 后写的生效

举个栗子:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS选择器</title>
<style>
.test1{
color: red;
}
.test1{
color: blue;
}
.test2{
color: red!important;
}
.test2{
color: blue;
}
#test3{
color: red;
}
</style>
</head>
<body class="body" id="body">
<div class="test1">蓝色</div>
<div class="test2">红色</div>
<div id="test3" style="color: blue;">蓝色</div>
</body>
</html>

运行结果如下图所示:

非布局样式

字体

  • 字体族 例如: serif、monospace(不能添加引号)衬线字体
    • 多字体fallback 例如: “monaco”、”Microsoft Yahei”、”PingFang SC”
    • 网络字体、自定义字体
    • iconfont

行高(经典问题)

  • 行高的构成(由line-box组成,line-box由inline-box组成)
  • 行高相关的现象和方案(可以通过设置 line-height来实现垂直居中效果)
  • 行高的调整

经典问题:图片下面有空隙,原理是什么?怎样去除?

原理是因为图片按照 inline 进行排版,排版的时候会涉及到字体对齐,默认按照 baseline 对齐,baseline和底线之间是有偏差的,偏差大小是根据字体大小而定,如果是12px字体大小,则图片空隙就是3px左右。这就是经典图片3px空隙问题。

解决方式

  • 由于默认按照baseline对齐,不妨将 vertical-align 设为 bottom,按照底线对齐。
  • 设置 display:block 可以解决该问题,但是会独占一行,如下图所示:

    背景

  • 背景颜色
  • 渐变色背景
  • 多背景叠加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>渐变色背景(线性梯度)</title>
<style>
.div1{
height: 90px;
}
.div2{
height: 90px;
/*background: linear-gradient(to right,red,green);*/
/*background: linear-gradient(180deg,red,green);*/
/*background: linear-gradient(135deg,red 0,green 15%,yellow 50%,blue 90%);*/

/*网格线*/
background: linear-gradient(135deg,transparent 0,transparent 49.5%,green 49.5%,green 50.5%,transparent 50.5%,transparent 100%),
linear-gradient(45deg,transparent 0,transparent 49.5%,red 49.5%,red 50.5%,transparent 50.5%,transparent 100%);
background-size: 30px 30px;
}
</style>
</head>
<body>
<div class="div1"></div>
<div class="div2"></div>
</body>
</html>

最后一个例子展示效果:

  • 背景图片和属性(雪碧图)
background-repeat: no-repeat;
background-size: 30px 30px; //相对于容器偏移
background-position: 30px 30px;

雪碧图 就是将很多个图片进行拼接成一个图片,然后通过 background-position等属性进行偏移,在网页中得到对应图片,来达到减少http请求。

  • base64和性能优化

    将图片进行base64编码后,就是一个字符文本,缺点之一就是图片的体积会增大 1/3 左右,并且放入css文件中,也会导致css文件变大。另外,虽然能减少http请求,但增大了解码的开销。适用于小图标icon,例如loading文件等。最后,在开发环境一般不采用直接将图片进行 base64 编码,因为对于协同开发来说,无法知晓图片原样,只有一个文本。

    一般情况下,是在生产环境下,通过打包的方式,将小图片进行 base64编码。

  • 多分辨率适配

边框(经典问题)

  • 边框的属性:线型 大小 颜色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>边框</title>
<style>
.c1{
width: 400px;
height: 200px;
border: 1px solid red;
/*border: 5px solid red;*/
/*border: 5px dotted red;*/
/*border: 5px dashed red;*/
}
</style>
</head>
<body>
<div class="c1"></div>
</body>
</html>
  • 边框背景图

经典问题:九宫格问题,例如下面图片,我们如果想要实现9个不同形式,然后中间放内容,如果用原本9个div方法,那么会非常麻烦,而css3提供了 border方式可以解决上述问题。


在没有在 border-image处设置 round之前,是如上效果,后面 30 是用来切出四个角。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>边框</title>
<style>
.c1{
width: 400px;
height: 200px;
border: 30px solid transparent;
border-image: url(./xx.png) 30 round; /*round将图片进行整数个拼接*/
}
</style>
</head>
<body>
<div class="c1"></div>
</body>
</html>

border-image处设置 round之后,是如下效果,基本达到我们想要的效果。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>边框</title>
<style>
.c2{
width: 400px;
height: 200px;
border: 30px solid transparent;
border-image: url(./xx.png) 30 round; /*round将图片进行整数个拼接*/
}
</style>
</head>
<body>
<div class="c2"></div>
</body>
</html>
  • 边框衔接(三角形)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>边框</title>
<style>
.c3{
width: 0px;
height: 200px;
border-bottom: 30px solid red;
border-left: 30px solid transparent;
border-right: 30px solid transparent;
}
</style>
</head>
<body>
<div class="c3"></div>
</body>
</html>

实现三角形,效果如下:

滚动

产生滚动的原因:当内容比容器多的时候,即容器装不下内容的时候,就需要滚动。滚动主要包括如下几个方面:

  • 滚动行为和滚动条

    overflow 设置autoscroll 区别,auto 是内容多于容器时显示滚动条,反正,不显示。而 scroll 是一直显示滚动条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>滚动</title>
<style>
.div1{
background: red;
height: 200px;
overflow: scroll; /*可选值: hidden visible auto scroll*/
}
</style>
</head>
<body>
<div class="div1">
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
<p>test</p>
</div>
</body>
</html>

文字折行(经典问题)

  • overflow-wrap(word-wrap)通用换行控制(是否保留单词)
  • word-break 针对多字节文字(中文句字也是单词)
  • white-space 空白处是否断行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文字折行</title>
<style>
.div1{
border: 1px solid;
width: 8em;
overflow-wrap: normal;
word-break: normal;
white-space: normal;
}
</style>
</head>
<body>
<div class="div1">
学如逆水行舟,不进则退!Learning is like sailing against the current, retreating if not advancing
</div>
</body>
</html>

展示效果:

经典问题:怎么让一个很长的文本不换行?

将上述属性设置为 nowrap即可

white-space: nowrap;

装饰性属性

  • 字重(粗体)font-weight
  • 斜体 font-style:itatic
  • 下划线 text-decoration
  • 指针 cursor
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>font-weight</title>
<style>
.div1{
font-weight: normal; /*400*/
font-weight: bold; /*700*/
font-weight: bolder;
font-weight: lighter;
font-weight: 100;
}
</style>
</head>
<body>
<div class="div1">学如逆水行舟,不进则退!</div>
</body>
</html>

CSS Hack(了解)

hack


用来处理浏览器兼容性做法,好处就是简单粗暴

  • Hack即不合法但生效的写法
  • 主要用于区分不同浏览器
  • 缺点:难理解 难维护 难失效
  • 替代方案:特性检测(检测浏览器是否有相关特性,没有的话就针对性处理)
  • 替代方案:针对性加class(例如检测到 IE6,那么就加IE6的class)

CSS 面试真题

css样式(选择器)的优先级

  • 计算权重确定
  • !important
  • 内联样式
  • 后写的优先级高

雪碧图的作用

  • 雪碧图 就是将很多个图片进行拼接成一个图片,然后通过 background-position等属性进行偏移,在网页中得到对应图片,来达到减少http请求,提高页面加载性能。
  • 有一些情况下可以减少图片大小(例如png格式图片,每张图片颜色基本上一样的,有可能总的图片大小是小于每个图片加起来的大小的)

自定义字体的使用场景

  • 宣传 / 品牌 / banner 等固定文案
  • 字体图标(将文字变为图标)

base64的作用

将图片进行base64编码后,就是一个字符文本,缺点之一就是图片的体积会增大 1/3 左右,并且放入css文件中,也会导致css文件变大。另外,虽然能减少http请求,但增大了解码的开销。适用于小图标icon,例如loading文件等。最后,在开发环境一般不采用直接将图片进行 base64 编码,因为对于协同开发来说,无法知晓图片原样,只有一个文本。

  • 用于减少http请求
  • 适用于小图片
  • base64的体积约为原图的 4/3

伪类和伪元素的区别?

  • 伪类 表 状态(某元素是个链接 link状态)
  • 伪元素是真的有元素(::before{},在页面中会显示内容)
  • 前者使用单冒号,后者使用双冒号

如何美化checkbox

  • label [for] 和 id
  • 隐藏原生 input(所有的样式由 label 来搞定)
  • :checked + label

CSS 布局

CSS体系知识的重中之重

  • 早期以 table 为主(简单)
  • 后来以技巧性布局为主(难)
  • 现在有 flexbox / grid(偏简单)

常用布局方式

  • table表格布局
  • float 浮动+ margin
  • inline-block 布局
  • flexbox 布局

布局方式(表格)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>table布局</title>
<style>
.table{
margin-top: 20px;
width: 500px;
height: 100px;
display: table;
}
.table-row{
display: table-row;
}
.table-cell{
vertical-align: center;
display: table-cell;
}
.left{
background: red;
vertical-align: middle;
}
.right{
background: blue;
vertical-align: middle;
}
</style>
</head>
<body>
<div class="table">
<div class="table-row">
<div class="left table-cell">left</div>
<div class="right table-cell">right</div>
</div>
</div>
</body>
</html>

展示效果如下图所示:

display / position(经典问题)

  • display 常用属性值: block(块级) / inline(内联) / inline-block(对内表现为block,可以有宽高,对外表现为inline,可以与其它元素排在同一行)
  • position 常用属性值:static(静态) / relative(相对) / absolute(绝对) / fixed(固定)

display

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>display</title>
<style>
.block{
height: 200px;
background: red;
}
.inline{
display: inline;
background: green;
}
.inline-block{
display: inline-block;
width: 200px;
height: 100px;
background: blue;
}
</style>
</head>
<body>
<div class="block">
block
</div>
<div class="inline">inline</div>
<div class="inline-block">inline-block</div>
</body>
</html>

position

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>position</title>
<style>
.p1{
width: 100px;
height: 100px;
background: red;
}
.p2{
position: relative;
width: 100px;
height: 100px;
left: 20px;
top: -10px;
background: blue;
}
.p3{
position: absolute;
width: 100px;
height: 100px;
left: 80px;
top: 30px;
background: yellow;
}
.p4{
position: fixed;
width: 100px;
height: 100px;
left: 0;
bottom: 10px;
background: green;
}
.p5{
width: 100px;
height: 100px;
background: pink;
}
</style>
</head>
<body>
<div class="p1">position:static</div>
<div class="p2">position:relative</div>
<div class="p3">position:absloute</div>
<div class="p4">position:fixed</div>
<div class="p5">no position</div>
</body>
</html>

展示效果如下:

由上图可知,当设置 positionrelative 后,no position(粉色块) 并没有在蓝色块下面,也就是说设置 positionrelative 后,占据空间还是按照原来的方式计算的,不会因为偏移而改变布局的计算。

经典问题

  • 绝对定位 absolute,会优先查找父级定位为 absoluterelative的进行定位,如果父级没有,找上级,那么最终就会根据 body进行定位,它和 fixed一样,也是脱离了文档流。

  • fixed相对于屏幕进行定位

层叠问题 ,因为默认会根据先后顺序显示,因此会有覆盖情况,此时,可以通过设计 z-index 解决,权重越大,优先显示。

flexbox(圣杯布局)

  • 弹性盒子
  • 盒子本来就是并列的
  • 指定宽度即可
  • 移动端常用

(目前用的不是很热的原因是虽然简单方便,但是兼容性有点问题)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flexbox</title>
<style>
.container{
width: 800px;
height: 200px;
display: flex;
border: 1px solid black;
}
.flex{
background: blue;
flex: 1;
margin: 5px;
}
</style>
</head>
<body>
<div class="container">
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
<div class="flex">flex</div>
</div>
</body>
</html>

展示效果如下:

由这个很方便的布局,我们可以写一个圣杯布局的例子(即左右固定,中间自适应):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局-flexbox</title>
<style>
*{
margin: 0;
}
.container{
min-height: 200px;
display: flex;
}
.left{
width: 200px;
display: flex;
background: red;
}
.center{
background: yellow;
flex: 1;
}
.right{
width: 200px;
display: flex;
background: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
</body>
</html>

float

  • 元素”浮动”
  • 脱离文档流(不会对其它元素的布局造成影响)
  • 但不脱离文本流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>float布局</title>
<style>
.container{
width: 400px;
background: red;
}
.p1{
width: 200px;
height: 80px;
float: left;
background: pink;
}

</style>
</head>
<body>
<div class="container">
<span class="p1">float元素</span>
<div class="p2">很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字很多文字</div>
</div>
</body>
</html>

展示效果如下:

float 特性的影响(经典问题)

float 特性对自己的影响

  • 形成块(BFC,可以使得inline元素能够设置宽高,例如上文代码,原本span元素不能设置宽高的,但通过设置float布局,使得可以设置宽高)
  • 位置尽量靠上
  • 位置尽量靠左(右)(对于上述解释,是如果 container宽度够的话,就尽量靠上和靠左,如果不行的话,就往下排了)

简单例子:


float 特性对兄弟的影响

  • 上面贴非 float 元素
  • 旁边贴 float 元素
  • 不影响其它块级元素位置(不脱离文档流)
  • 影响其它块级元素内部文本(脱离了文本流)

float 特性对父级的影响

  • 从布局上 “消失”(父级不会管它的宽高)
  • 经典问题:高度塌陷 (假设float元素,原本是 100px 高度,这个时候很期望父级能撑开100个像素,但因为设置了 float,等于消失了,并不会在意这 100个像素,因此,如果没有其它元素支撑高度的话,父级的高度就会设置为0,这就是高度塌陷)

清楚浮动的方式

经典问题

清除浮动的方式

① 当我们设置为 float 后,会将元素设为 BFC,接管自己的宽高,因此我们也可以让父级元素设置为 BFC,来接管自己的宽高。

初始状态:

在父级元素设置 overflow: auto/hidden;

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮动</title>
<style>
.container{
background: red;
width: 400px;
overflow: auto;
margin: 10px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
</style>
</head>
<body>
<div class="container">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>

最终状态效果图如下:
在这里插入图片描述

② 由于 float 不脱离文档流(不会影响其它元素布局),那么就可以使得元素刚好到达下面位置。就可以通过其它元素将父级撑起来,当父级刚好撑到下方位置时,就可以将浮动清除掉。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮动</title>
<style>
.container{
background: red;
width: 400px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
.removeFloat::after{
content: 'aaa';
clear: both; /*保证当前元素左右没有浮动元素*/
display: block;
height: 0;
visibility: hidden;
}
</style>
</head>
<body>
<div class="container removeFloat">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>

经典清除浮动方式,效果图如下:

float(圣杯布局)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圣杯布局-float</title>
<style>
.container{
min-height: 200px;
}
.left{
float: left;
background: red;
width: 200px;
}
.center{
margin-left: 200px;
margin-right: 200px;
background: yellow;
}
.right{
float: right;
background: blue;
width: 200px;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="right">right</div>
<div class="center">center</div>

</div>
</body>
</html>

展示效果如下:

inline-block 布局

  • 像文本一样排block元素
  • 没有清楚浮动等问题
  • 需要处理间隙

例如下图,红蓝之间有一个间隙,是因为 inline-block就像文本一样,我们没办法让两个字紧紧地挨着,于是我们就有了下文所述解决方式:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>inline-block布局</title>
<style>
.container{
width: 800px;
height: 200px;
font-size: 0;
}
.left{
font-size: 15px;
background: red;
display: inline-block;
width: 200px;
height: 200px;
}
.right{
font-size: 15px;
background: blue;
display: inline-block;
width: 500px;
height: 200px;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
</html>

展示效果如下:

查看上述代码,将父级元素字体大小设置为0即可解决间隙问题,但子元素需要设置自己的字体大小,不然就不会显示。

因此,做自适应方面会有点麻烦,不像上文 float+margin 那样简单

响应式设计和布局

  • 在不同的设备上正常使用
  • 一般处理屏幕大小问题
  • 主要方法:隐藏 + 折行 + 自适应空间(rem:通过html的字体大小(即 font-size)来确定元素大小,但不太精确 / viewport:通过 js或手工 确定整个界面放到多大 / media query:媒体查询,根据不同的设备来匹配不同的样式)

下图含义就是只有在宽度小于 640px 时才会生效,即让移动端进行适配。

CSS 面试真题

实现两栏(三栏)布局的方法

  • 表格布局
  • float + margin 布局(兼容性好)
  • inline-block 布局(需要处理间隙问题)
  • flexbox布局(简单,但兼容性不是很好)

position:absolute / fixed 有什么区别?

经典问题

  • 绝对定位 absolute,会优先查找父级定位为 absoluterelative的进行定位,如果父级没有,找上级,那么最终就会根据 body进行定位,它和 fixed一样,也是脱离了文档流。

  • fixed相对于屏幕(viewport)进行定位

层叠问题 ,因为默认会根据先后顺序显示,因此会有覆盖情况,此时,可以通过设计 z-index 解决,权重越大,优先显示。

display:inline-block 的间隙

  • 原因:字符间距
  • 解决:消灭字符(把标签写在一起或者添加注释)或者消灭间距(将font-size设为0)

如何清除浮动?为什么要清除浮动?

原因:浮动的元素不会占据父元素的布局空间,也就是父级元素不会管浮动元素,有可能浮动元素会超出父元素,从而对其它元素产生影响。

经典问题

清除浮动的方式

① 当我们设置为 float 后,会将元素设为 BFC,接管自己的宽高,因此我们也可以让父级元素设置为 BFC,来接管自己的宽高。

初始状态:

在父级元素设置 overflow: auto/hidden;

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮动</title>
<style>
.container{
background: red;
width: 400px;
overflow: auto;
margin: 10px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
</style>
</head>
<body>
<div class="container">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>

最终状态效果图如下:
在这里插入图片描述

② 由于 float 不脱离文档流(不会影响其它元素布局),那么就可以使得元素刚好到达下面位置。就可以通过其它元素将父级撑起来,当父级刚好撑到下方位置时,就可以将浮动清除掉。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>清楚浮动</title>
<style>
.container{
background: red;
width: 400px;
}
.p1{
background: pink;
float: left;
width: 200px;
height: 50px;
}
.removeFloat::after{
content: 'aaa';
clear: both; /*保证当前元素左右没有浮动元素*/
display: block;
height: 0;
visibility: hidden;
}
</style>
</head>
<body>
<div class="container removeFloat">
<span>xxxxxx</span>
<span class="p1">float</span>
<span class="p1">float</span>
</div>
<div class="container" style="height: 200px; background: blue;">
<p>第一行</p>
<p>第二行</p>
<p>第三行</p>
</div>
</body>
</html>

经典清除浮动方式,效果图如下:

如何适配移动端页面?

主要方法:隐藏 + 折行 + 自适应空间(rem:通过html的字体大小(即 font-size)来确定元素大小,但不太精确 / viewport:通过 js或手工 确定整个界面放到多大 / media query:媒体查询,根据不同的设备来匹配不同的样式)

效果属性(CSS最出彩的一部分)

box-shadow


属性值介绍:前两个是偏移量,第三个是模糊区域度,第四个是拓展区域度,第五个是颜色(最后一个是透明度)

box-shadow: 5px 5px 10px 0 rgba(0, 0, 0, .2);

text-shadow

  • 立体感
  • 印刷品质感

border-radius

  • 圆角矩形
  • 圆形
  • 半圆 / 扇形
  • 一些奇怪的角角
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>border-radius</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>

展示效果如下:

background

  • 纹理、图案
  • 渐变
  • 雪碧图动画
  • 背景图尺寸适应

    clip-path

  • 对容器进行裁剪
  • 常见几何图形
  • 自定义路径

3D-transform

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D-transform</title>
<style>
.container{
margin: 50px;
padding: 10px;
border: 1px solid red;
width: 200px;
height: 200px;
position: relative;
perspective: 500px;
}
#cube{
width: 200px;
height: 200px;
transform-style: preserve-3d;
transform: translateZ(-100px);
transition: transform 1s;
}
#cube:hover{
transform: translateZ(-100px) rotateX(90deg) rotateY(90deg);
}
#cube div{
width: 200px;
height: 200px;
position: absolute;
line-height: 200px;
font-size: 50px;
text-align: center;
}
.front{
background: rgba(255, 0, 0, .3);
transform: translateZ(100px);
}
.back{
background: rgba(0, 255, 0, .3);
transform: translateZ(-100px) rotateY(180deg);
}
.left{
background: rgba(0, 0, 255, .3);
transform: translateX(-100px) rotateY(-90deg);
}
.right{
background: rgba(255, 255, 0, .3);
transform: translateX(100px) rotateY(90deg);
}
.top{
background: rgba(255, 0, 255, .3);
transform: translateY(-100px) rotateX(-90deg);
}
.bottom{
background: rgba(0, 255, 255, .3);
transform: translateY(100px) rotateX(90deg);
}
</style>
</head>
<body>
<div class="container">
<div id="cube">
<div class="front">1</div>
<div class="back">2</div>
<div class="right">3</div>
<div class="left">4</div>
<div class="top">5</div>
<div class="bottom">6</div>
</div>
</div>
</body>
</html>

展示效果图如下:

CSS 面试真题

如何用div画一个 xxx

  • box-shadow 无限投影
  • ::before
  • ::after

如何产生不占空间的边框

  • box-shadow
  • outline

如何实现圆形元素(头像)

  • border-radius:50%

如何实现iOS图标的圆角

  • clip-path:(svg)

如何实现半圆、扇形等图形

  • border-radius 组合:有无边框、边框粗细、圆角半径

如何实现背景图居中显示 / 不重复 / 改变大小

  • background-position
  • background-repeat
  • background-size(cover / contain)

如何平移 / 放大一个元素

  • transform:translateX(100px)
  • transform:scale(2)
  • transform本身与动画没有关系

如何实现3D效果

  • perspective:500px(指定透视角度)
  • transform-style:preserve-3d;(3d效果)
  • transform:translate rotate …

CSS 动画

动画的原理

  • 视觉暂留作用:就是说看到的画面,会在脑海中保留一段片段
  • 画面逐渐变化

动画的作用

  • 愉悦感
  • 引起注意
  • 反馈(输入密码错误时,登录框晃动)
  • 掩饰

CSS中动画的类型

  • transition 补间动画(从一个状态到另一个状态,状态切换之间是有动画的)
  • keyframe 关键帧动画(指定的每一个状态就是一个关键帧)
  • 逐帧动画(跳动)

transition 补间动画

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>transition补间动画</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
transition: width 1s, background 2s;
}
.container:hover{
width: 300px;
background: blue;
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>

展示效果如下:

动画进度与时间的关系


例子:

推荐:动画进度与时间关系模拟网站

关键帧动画

  • 相当于多个补间动画
  • 与元素状态的变化无关
  • 定义更加灵活
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>keyframe关键帧动画</title>
<style>
.container{
width: 100px;
height: 100px;
background: red;
animation: run 1s;
animation-direction: reverse;
animation-iteration-count: infinite;
/*animation-fill-mode: forwards;*/
/*animation-play-state: paused;*/
}
@keyframes run {
0%{
width: 100px;
}
100%{
width: 800px;
}
}
</style>
</head>
<body>
<div class="container"></div>
</body>
</html>

展示效果:

逐帧动画

  • 属于关键帧动画特殊的一种
  • 适用于无法补间计算的动画
  • 资源较大
  • 使用 steps() (设置关键帧之间有几个画面,一般设置为1,也可以说是将关键帧去掉补间)

例如:一个动物跑动的过程,通过将每个动作的图片逐帧显示,形成动画的感觉。

CSS 面试真题

CSS 动画的实现方式有几种

  • transition
  • keyframes(animation)

过渡动画和关键帧动画的区别

  • 过渡动画需要有状态变化
  • 关键帧动画不需要状态变化
  • 关键帧动画能控制更精细

如何实现逐帧动画

  • 使用关键帧动画
  • 去掉补间(steps)

CSS动画的性能

  • 性能不坏
  • 部分情况下优于JS
  • 但JS可以做的更好
  • 部分高危属性(例如 box-shadow等)

CSS 预处理器

  • 基于CSS的另一种语言
  • 通过工具编译为CSS
  • 添加了很多CSS不具备的特性
  • 能提升CSS文件的组织

常见的有 less(基于node写的,编译比较快,入门简单)和 sass(基于Ruby写的)

  • 嵌套 反映层级和约束
  • 变量和计算 减少重重复代码
  • Extend 和 Mxxin 代码片段
  • 循环 适用于复杂有规律的样式
  • import CSS 文件模块化

less嵌套

全局安装 less

npm install less -g


创建一个 test.less 文件

body{
padding: 0;
margin: 0;
}
.wrapper{
background: white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background: red;
}
}
}

在该文件处调用终端,执行以下命令:

lessc test.less

输出结果:

执行如下命令,输出到 test.css 文件中

lessc test.less > test.css

查看 test.css 文件,得到如下结果:

body {
padding: 0;
margin: 0;
}
.wrapper {
background: white;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}

sass嵌套

全局安装 sass

cnpm install node-sass -g

创建一个 test.scss 文件

body{
padding: 0;
margin: 0;
}
.wrapper{
background: white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background: red;
}
}
}

执行如下命令,查看输出结果:

node-sass test.scss


执行如下命令,输出到 test-scss.css 文件中

node-sass test.scss > test-scss.css

查看 test-scss.css 文件,得到如下结果:

body {
padding: 0;
margin: 0; }

.wrapper {
background: white; }
.wrapper .nav {
font-size: 12px; }
.wrapper .content {
font-size: 14px; }
.wrapper .content:hover {
background: red; }

从以上代码来看,sass嵌套会保留原来嵌套样式,对于css观赏性来说,并不是我们特别想要的,于是我们可以执行如下命令,更改输出样式:

node-sass --output-style expanded test.scss > test-scss.css

输出结果就和less嵌套一样了,读者可以自己跑一遍!

less变量

创建 variable-less.less 文件

@fontSize: 12px;
@bgColor: red;

body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
font-size: @fontSize;
}
.content{
font-size: @fontSize+2px;
&:hover{
background: @bgColor;
}
}
}

创建 variable-less.css 文件,执行如下命令:

lessc variable-less.less > variable-less.css

可以得到如下代码:

body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}

sass变量

类似less变量,只需要将 @ 改为 $ 即可,因为 less 变量命名这样做,是更贴近CSS。而 sass是为了区别CSS。

less mixin

创建 mixin.less 文件,复制如下代码:

@fontSize: 12px;
@bgColor: red;

.block(@fontSize){
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
.block(@fontSize);
}
.content{
.block(@fontSize+2px);
&:hover{
background: @bgColor;
}
}
}

创建 mixin-less.css 文件,执行如下代码:

lessc mixin.less > mixin-less.css

查看mixin-less.css 文件,发现 .block 没有了,在CSS内部就完成了样式复用。

body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content:hover {
background: red;
}

sass mixin

创建 mixin.scss 文件,复制如下代码:

$fontSize: 12px;
$bgColor: red;

@mixin block($fontSize){
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten($bgColor,40%);
.nav{
@include block($fontSize);
}
.content{
@include block($fontSize+2px);
&:hover{
background: $bgColor;
}
}
}

创建 mixin-sass.css 文件,执行如下代码:

node-sass --output-style expanded mixin.scss > mixin-sass.css

查看mixin-sass.css 文件,发现 .block 没有了,在CSS内部就完成了样式复用。

body {
padding: 0;
margin: 0;
}

.wrapper {
background: #ffcccc;
}

.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}

.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}

.wrapper .content:hover {
background: red;
}

总结:从上文对比来看,sass mixin 除了调用变量符号要换为 $ 外,抽离公共样式需要使用 @mixin ,此外,调用时还需要使用 @include

那么,mixin还能做什么呢?

例如,对于布局方面,我们在上文提到了清楚浮动的方式,那么,我们就可以将这段样式进行复用,只需要在需要的元素处引用即可。

less extend

上文提到过的,使用过 less mixin 抽离之后,我们可以得到如下代码,但是呢,又会有一个小问题,就是我们会有重复样式代码。在生产环境下,就会有大量这样的形式出现,这就会影响到我们的CSS体积了。

一种比较好的方式,如下,我们再讲公共样式代码进行抽离,这显然会降低我们的CSS体积。

因此,extend就发挥了它的作用

创建 extend-less.less 文件,复制如下代码:

@fontSize: 12px;
@bgColor: red;

.block{
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten(@bgColor,40%);
.nav{
&:extend(.block);
}
.content:extend(.block){
&:hover{
background: @bgColor;
}
}
}

创建 extend-less.css 文件,执行如下代码:

lessc extend-less.less > extend-less.css

查看 extend-less.css 文件,发现代码体积相对减少了。

.block,
.wrapper .nav,
.wrapper .content {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .content:hover {
background: red;
}

总结:mixin 和 extend 区别, mixin 能处理一些复杂逻辑,比如添加变量,但会导致体积增大问题。而 extend的话,是将选择器提取出来,更加简单,不适合处理复杂逻辑,能将体积进行一定减少。

sass extend

创建 extend-sass.scss 文件,复制如下代码:

$fontSize: 12px;
$bgColor: red;

.block{
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding: 0;
margin: 0;
}
.wrapper{
background: lighten($bgColor,40%);
.nav{
@extend .block;
}
.content{
@extend .block;
&:hover{
background: $bgColor;
}
}
}

创建 extend-sass.css 文件,执行如下代码:

node-sass --output-style expanded extend-sass.scss > extend-sass.css

查看 extend-sass.css 文件,发现代码体积相对减少了。

.block, .wrapper .nav, .wrapper .content {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}

body {
padding: 0;
margin: 0;
}

.wrapper {
background: #ffcccc;
}

.wrapper .content:hover {
background: red;
}

less loop

创建 loop-less.less 文件,复制如下代码

.gen-col(@n) when (@n > 0){
.gen-col(@n - 1);
.col-@{n}{
width: 1000px/12*@n;
}
}

.gen-col(12);

创建 loop-less.css 文件,执行如下代码:

lessc loop-less.less > loop-less.css

查看 loop-less.css 文件,发现有12个样式

.col-1 {
width: 83.33333333px;
}
.col-2 {
width: 166.66666667px;
}
.col-3 {
width: 250px;
}
.col-4 {
width: 333.33333333px;
}
.col-5 {
width: 416.66666667px;
}
.col-6 {
width: 500px;
}
.col-7 {
width: 583.33333333px;
}
.col-8 {
width: 666.66666667px;
}
.col-9 {
width: 750px;
}
.col-10 {
width: 833.33333333px;
}
.col-11 {
width: 916.66666667px;
}
.col-12 {
width: 1000px;
}

sass loop

创建 loop-sass.scss 文件,复制如下代码:

@mixin gen-col($n){
@if $n > 0 {
@include gen-col($n - 1);
.col-#{$n}{
width: 1000px/12*$n;
}
}
}

@include gen-col(12);

创建 loop-sass.css,执行如下代码:

node-sass --output-style expanded loop-sass.scss > loop-sass.css

查看 loop-sass.css 文件,发现有12个样式

.col-1 {
width: 83.33333px;
}

.col-2 {
width: 166.66667px;
}

.col-3 {
width: 250px;
}

.col-4 {
width: 333.33333px;
}

.col-5 {
width: 416.66667px;
}

.col-6 {
width: 500px;
}

.col-7 {
width: 583.33333px;
}

.col-8 {
width: 666.66667px;
}

.col-9 {
width: 750px;
}

.col-10 {
width: 833.33333px;
}

.col-11 {
width: 916.66667px;
}

.col-12 {
width: 1000px;
}

上述版本代码或许是挺复杂的,好在 sass提供了for循环,见如下代码:

@for $i from 1 through 12 {
.col-#{$i} {
width: 1000px/12*$i;
}
}

less import

创建 import-less.less 文件,复制如下代码:

@import "./mixin";
@import "./variable-less";

创建 import-less.css 文件,执行如下代码:

lessc import-less.less > import-less.css

查看 import-less.less 文件

body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content {
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
}
.wrapper .content:hover {
background: red;
}
body {
padding: 0;
margin: 0;
}
.wrapper {
background: #ffcccc;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}

sass import

语法上没有什么变化,注意符号是 $

CSS预处理器框架

  • Less - Lesshat / EST(官网
  • SASS - Compass (官网,将有兼容性问题的属性会进行封装成mixin,直接调用就好)
  • 提供现成的 mixin
  • 类似 JS 类库 封装常用功能

CSS 面试真题

常见的CSS预处理器

  • Less(Node.js)
  • Sass(Ruby 有Node版本)

预处理器的作用

  • 帮助更好地组织CSS代码
  • 提高代码复用率
  • 提升可维护性

预处理器的能力

  • 嵌套 反映层级和约束
  • 变量和计算 减少重重复代码
  • Extend 和 Mxxin 代码片段
  • 循环 适用于复杂有规律的样式(网格系统)
  • import CSS 文件模块化(按需拆解CSS文件)

预处理器的优缺点

  • 优点:提高代码复用率和可维护性
  • 缺点:需要引入编译过程 有学习成本

Bootstrap

  • 一个CSS框架
  • twitter 出品
  • 提供通用基础样式

Bootstrap 4

  • 兼容IE10+
  • 使用flexbox布局
  • 抛弃Nomalize.css
  • 提供布局 和 reboot版本
  • 官网,用sass写)
  • 可用于后台管理系统

Bootstrap JS组件

用于组件交互

  • dropdown(下拉)
  • modal(弹窗)

基于jquery写的,同时,依赖第三方库 Popper.js和 bootstrap.js

如上图,第二个js文件包含了 Popper.js

使用方式:

  • 基于 data-*属性
  • 基于 JS API

Bootstrap 响应式布局

非常精华的部分

Bootstrap 定制方法

  • 使用CSS同名类覆盖(操作简单但)
  • 修改sass源码重新构建
  • 引用scss源文件 修改变量(推荐使用,干净)

CSS 面试真题

Bootstrap的优缺点

  • 优点:CSS代码结构合理,现成的样式可以直接使用
  • 缺点:定制较为繁琐 体积大

Bootstrap如何实现响应式布局

  • 原理:通过 media query 设置不同分辨率的class
  • 使用:为不同分辨率选择不同的网格class

如何基于Bootstrap 定制自己的样式

  • 使用CSS同名类覆盖(操作简单但)
  • 修改sass源码重新构建(需要了解Bootstrap 结构)
  • 引用scss源文件 修改变量(按需使用,控制体积,推荐使用,干净,但需要了解结构)

CSS 工程化

关注几个事情:组织、优化、构建、维护

PostCSS

  • 将 CSS 解析成 CSS,和预处理器没太多区别。
  • 本身只有解析能力
  • 各种神奇的特性全靠插件
  • 目前至少有200多个插件

常见:

  • import 模块合并
  • autoprefixer 自动加前缀
  • cssnano 压缩代码
  • cssnext 使用CSS新特性
  • precss 变量、mixin、循环等

PostCSS插件的使用

全局安装 postcss-cli

npm install postcss-cli -g

postcss.config.js 文件进行配置

cssnext

precss

  • 变量(使用和 sass 几乎一样)
  • 条件(if)
  • 循环
  • Mixin Extend
  • import
  • 属性值引用

gulp-postcss

PostCSS 支持的构建工具

  • CLI命令行工具
  • webpack postcss-loader
  • Gulp gulp-postcss
  • Grunt grunt-postcss
  • Rollup rollup-postcss

webpack

  • JS是整个应用的核心入口
  • 一切资源均由JS管理依赖
  • 一切资源均由webpack打包

webpack 和 CSS

  • css-loader 将 CSS变为 JS
  • style-loader 将JS插入到head
  • ExtractTextPlugin 将 CSS 从 JS 中 提取出来
  • CSS modules 解决 CSS命名冲突的问题
  • less-loader sass-loader 各类预处理器
  • postcss-loader PostCSS处理

CSS 面试真题

如何解决CSS模块化问题

  • less sass 等CSS预处理器
  • PostCSS插件(postcss-import / precss等)
  • webpackl处理CSS(css-loader + style-loader)

PostCSS可以做什么?

  • 取决于插件做什么
  • autoprefixer cssnext precss等 兼容性处理
  • import 模块合并
  • css语法检查 兼容性检查
  • cssnano 压缩文件

CSS modules是做什么的,如何使用

  • 解决类名冲突的问题
  • 使用PostCSS或者webpack等构建工具进行编译
  • 在HTML模板中使用编译过程产生的类名

为什么使用JS来引用、加载CSS

  • JS作为入口,管理资源有天然优势
  • 将组件的结构、样式、行为封装到一起,增强内聚
  • 可以做更多处理(webpack)

结尾

话说,我有女朋友吗?我有吗?原来我没有…

扯开女朋友话题,终于完成了这篇史诗级大作,时隔几天时间。更多笔记内容还请关注 小狮子前端笔记仓库 (不要白嫖,给个 star ✿✿ヽ(°▽°)ノ✿ 就是对我最大的支持啦~)

学如逆水行舟,不进则退
文章作者: Yang Chao Yi
文章链接: https://yangchaoyi.vip/posts/2055211/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 超逸の博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论