# 布局

# 盒模型

  • 标准模式:元素的 width/height = content + border + padding
  • 怪异模式:元素的 width/height = content(包含 border 和 padding)

通过 CSS 的 box-sizing 属性切换模式,content-box 就是标准模式,border-box 就是怪异模式。

# BFC

块级排版上下文 (block formatting context),一个区域,CSS 规范决定了这个规范如何生成。可以参考 这一节,从视觉排版模型聊到盒子定位方式,再到块级排版上下文,如何生成、子盒子排列规则。

# float 布局,清除浮动

清除浮动:生成新的块级排版上下文即可。接上题。

# 定位

  • static:正常文档流,无定位;
  • relative(相对定位):正常文档流,相对自身定位;
  • absolute(绝对定位):脱离文档流,相对上级有 position 属性且值不为 static 的元素定位,若没有则相对 body 定位;
  • fixed(固定定位):脱离文档流,相对于浏览器窗口定位;
  • sticky(粘性定位):元素根据正常文档流进行定位,然后相对它的最近滚动祖先元素,基于 top, right, bottom, 和 left 的值进行偏移。偏移值不会影响任何其他元素的位置。

sticky:

  • 动态性:一些时候是 relative 定位(定位基点是自身默认位置),另一些时候自动变成 fixed 定位(定位基点是视口)。
  • 必须搭配 top、bottom、left、right 这四个属性一起使用,不能省略,否则等同于 relative 定位,不产生动态效果。
  • 当页面滚动,父元素开始脱离视口时(即部分不可见),只要与 sticky 元素的距离达到生效门槛,relative 定位自动切换为 fixed 定位;等到父元素完全脱离视口时(即完全不可见),fixed 定位自动切换回 relative 定位。
  • 场景:搜索栏吸顶。

# 水平垂直居中

/* position + margin: auto */
/* 适用于元素:定宽高
当不定宽高时,会铺满整个容器
通常会指定父元素为 relative,相对于父元素进行定位 */

.child {
  /* 核心样式 */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* absolute + transform */
/* 适用于元素:定宽高、不定宽高 */

.child {
  /* 核心样式 */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
1
2
3
4
5
6
7
8
9
10
/* absolute + 负 margin */
/* 适用于元素:定宽高 */

.child {
  /* 核心样式 */
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -50px;
  margin-top: -50px;
}
1
2
3
4
5
6
7
8
9
10
11
/* flex */

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}
1
2
3
4
5
6
7
/* 父容器 table-cell + 子元素 非 block 的方式 */

.parent {
  /* 核心样式 */
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
.child {
  /* 核心样式 */
  display: inline-block;

  background-color: yellow;
  width: 100px;
  height: 100px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 水平居中

/* 行内元素 */
/* 父元素使用 text-align */

.parent {
  text-align: center;
}
1
2
3
4
5
6
/* 块级元素,定宽 */

div {
  width: 200px;
  margin: 0 auto;
}
1
2
3
4
5
6
/* 块级元素,不定宽 */

div {
  display:table;
  margin:0 auto;
}
1
2
3
4
5
6
div {
  display:flex;
  justify-content:center;
}
1
2
3
4

# 垂直居中

  • 父元素 flex
  • 元素本身 position + margin 负值(定高)
  • 元素本身 position + transform: translate(0, -50%)
  • position + top/bottom:0 + margin:auto

# 两列布局

<div class="wrapper">
  <div class="left"></div>
  <div class="right"></div>
</div>
1
2
3
4
/* 1. float */

.wrapper {
  width: 100vw;
  height: 100vh;
}
.left {
  width: 100px;
  float: left;
}
.right {
  padding-left: 100px;
  overflow: hidden;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* 2. flex */

.wrapper {
  width: 100vw;
  height: 100vh;
  display: flex;
}
.left {
  flex: 0 0 100px;
}
.right {
  flex: 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
/* 3. grid */

.wrapper {
  width: 100vw;
  height: 100vh;
  display: grid;
  grid-template-columns: 100px auto;
  /*或者:grid-template-columns: 100px 1fr*/
}
1
2
3
4
5
6
7
8
9

# 三列布局

两边等宽,中间自适应。

圣杯布局

<div class="container">
  <div class="middle">middle</div> // 放前面会优先加载
  <div class="left">left</div>
  <div class="right">right</div>
</div>
1
2
3
4
5
/* 2. float + position */

.wrapper {
  overflow: hidden;
  padding: 0 100px;
}

.wrapper>div {
  float: left;
  height: 200px;
}

.center {
  width: 100%;
  background-color: #ccc;
}

.left {
  width: 100px;
  margin-left: -100%;
  background-color: pink;
  position: relative;
  left: -100px;
}

.right {
  width: 100px;
  margin-left: -100px;
  position: relative;
  right: -100px;
  background-color: skyblue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

缺点:中间宽度小于两侧宽度时布局失效,需设置最小宽度;

双飞翼布局

与圣杯布局的区别:

  • 圣杯布局,为了中间 div 内容不被遮挡,将中间 div 设置了左右 padding-left 和 padding-right 后,将左右两个 div 用相对布局 position: relative 并分别配合 right 和 left 属性,以便左右两栏 div 移动后不遮挡中间 div。
  • 双飞翼布局,为了中间 div 内容不被遮挡,直接在中间 div 内部创建子盒子用于放置内容,子盒子里用 margin-left 和 margin-right 为左右两栏 div 留出位置。


 





<div class="container">
  <div class="middle-container">
    <div class="middle">middle</div>
  </div>
  <div class="left">left</div>
  <div class="right">right</div>
</div>
1
2
3
4
5
6
7


 












 
 
 
 
 





 
 





 
 



.wrapper {
  overflow: hidden;
  /* padding: 0 300px; */
}

.wrapper>div {
  float: left;
  height: 200px;
}

.center {
  width: 100%;
  background-color: #ccc;
}

.middle {
  height: 200px;
  margin-left: 300px;
  margin-right: 300px;
}

.left {
  width: 300px;
  margin-left: -100%;
  background-color: pink;
  /* position: relative;
  left: -300px; */
}

.right {
  width: 300px;
  margin-left: -300px;
  /* position: relative;
  right: -300px; */
  background-color: skyblue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

flex 布局

.main {
  display: flex;
}
.left,
.right {
  flex: 0 0 200px;
}
.main {
  flex: 1;
}
1
2
3
4
5
6
7
8
9
10

grid 布局

.container {
  display: grid;
  grid-template-columns: 200px 1fr 200px;
}
1
2
3
4

# 图文样式

# 隐藏元素

  • display:none:隐藏元素,会从页面中删除掉,会触发重排和重绘;
  • visibility:hidden:隐藏元素,会继续在文档流中占位,会触发重绘。隐藏后不能触发点击事件;
  • opacity:0:透明,会继续在文档流中占位,会触发重绘。由是是作用于元素自身,所以子元素会继承,全部变透明,透明后可以触发点击事件;
  • rgba(0,0,0,0):透明,会继续在文档流中占位,会触发重绘。由于只作用于颜色或背景色,所以子元素不会继承。透明后可以触发点击事件;

# line-height 继承问题

# 行内元素之间空白间隙

inline-block 水平呈现的元素间,换行显示或空格分隔的情况下会有间距。

原因:回车换行被转成一个空白符,在字体不为 0 的情况下,空白符占据一定宽度。当行内元素 font-size:16px 时,间距为 8px。

如何去除:

  • 去掉换行符
  • 父元素设置font-size: 0,子元素单独设置 font-size。
  • margin 负值(不推荐)

# 可继承属性、不可继承属性

可继承属性

  • 所有元素:visibility、cursor
  • 列表元素:list-style、list-style-type、list-style-position、list-style-image
  • 字体属性:line-height、color、font、font-family、font-size、font-style、font-variant、font-weight、font-size-adjust
  • 表格布局属性:caption-side、border-collapse、border-spacing、empty-cells、table-layout
  • 文本属性:text-transform、direction
  • 其它属性:letter-spacing、word-spacing

不可继承属性

  • 盒子模型所有属性:margin、padding、border、width、height
  • 轮廓及背景属性:outline、background
  • 定位、显示、浮动属性:display、position、top、left、right、bottom、max-*(如 max-height 等)、min-*、overflow、clear、float、content、z-index、vertical-align
  • 文本属性:white-space
  • 其它:display

块级元素可以继承,内联元素不能继承属性

text-indent、text-align、text-decoration、text-shadow

# 伪类、伪元素

伪元素:在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成。它们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为“伪”元素。例如:

p::before { content:"第一章:"; }
p::after { content:"Hot!"; }
p::first-line { background:red; }
p::first-letter { font-size:30px; }
1
2
3
4

伪类:将特殊的效果添加到特定选择器上。它是已有元素上添加类别的,不会产生新的元素。例如:

a:hover { color: #FF00FF; }
p:first-child { color: red; }
1
2

总结: 伪类是通过在元素选择器上加⼊伪类改变元素状态,⽽伪元素通过对元素的操作进⾏对元素的改变。

# 单行/多行省略号

/* 单行,必须指定宽度 */

.box {
  width: 200px;
  overflow: hidden;            // 溢出隐藏
  text-overflow: ellipsis;     // 溢出用省略号显示
  white-space: nowrap;         // 规定段落中的文本不进行换行
}
1
2
3
4
5
6
7
8
/* 多行,仅 webkit 可用 */

.box {
  width: 200px;
  overflow: hidden;            // 溢出隐藏
  text-overflow: ellipsis;     // 溢出用省略号显示
  display:-webkit-box;         // 作为弹性伸缩盒子模型显示。
  -webkit-box-orient: vertical; // 设置伸缩盒子的子元素排列方式:从上到下垂直排列
  -webkit-line-clamp: 3;        // 显示的行数

}
1
2
3
4
5
6
7
8
9
10
11

# CSS3

# 为什么有时候⽤ translate 来改变位置⽽不是定位

CSS3 的 translate 使用的 GPU 加速,不会触发回流,而涉及盒子位置的定位会触发回流。

# animation

# requestAnimationframe

# 性能

# 优化方法

加载:

  • css 压缩,减小体积;
  • 样式分开写:padding: 1px 2px 0 0 > padding-left: 1px;padding-right: 2px;
  • 减少使用@import,建议使用link,因为后者在页面加载时一起加载,前者是等待页面加载完成之后再进行加载。

选择器:

渲染:

可维护性:

# 场景应用

# 实现一个三角形

/* 更换最后 3 行代码可修改三角形方向 */

div {
  width: 0;
  height: 0;
  border-top: 50px solid red;
  border-right: 50px solid transparent;
  border-left: 50px solid transparent;
}
1
2
3
4
5
6
7
8
9

# 实现一个扇形

/* 三角形 + border-radius */

div{
  width: 0;
  height: 0;
  border: 100px solid transparent;
  border-top-color: red;
  border-radius: 100px;
}
1
2
3
4
5
6
7
8
9

# 实现一个自适应的正方形

这里的自适应指的是随视口变化而变化。

/* css3 的 vw */

.square {
  width: 10vw;
  height: 10vw;
  background: red;
}
1
2
3
4
5
6
7
/* 子元素 margin 或者 padding 的百分比 */
/* 参照的是父盒子的 width */

.square {
  width: 10%;
  padding-bottom: 10%;
  /* 防止内容过多,撑开高度 */
  height: 0;
  background: red;
}
1
2
3
4
5
6
7
8
9
10

# 画一条 0.5px 的线

transform: scale(0.5,0.5);
1

# 设置小于 12px 的字体

  • 使用图片
  • css3 的 transform 缩放属性 -webkit-transform:scale(0.5)

# TODO

上次更新: 4/17/2022, 10:59:22 AM