共计 27820 个字符,预计需要花费 70 分钟才能阅读完成。
写作背景
女朋友要我教她 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
设置auto
和 scroll
区别,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>
展示效果如下:
由上图可知,当设置 position
为 relative
后,no position(粉色块)并没有在蓝色块下面,也就是说设置 position
为 relative
后,占据空间还是按照原来的方式计算的,不会因为偏移而改变布局的计算。
经典问题:
- 绝对定位
absolute
,会优先查找父级定位为absolute
或relative
的进行定位,如果父级没有,找上级,那么最终就会根据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
,会优先查找父级定位为absolute
或relative
的进行定位,如果父级没有,找上级,那么最终就会根据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 ✿✿ヽ (°▽°) ノ✿ 就是对我最大的支持啦~)
学如逆水行舟,不进则退