CSS - 布局 - 元素定位
标准流 - Normal Flow
默认情况下,元素都是按照normal flow(标准流、常规流、正常流、文档流【document flow】)进行排布
- 块级元素独占一行,多个行内元素或行内块级元素可以在同一行进行显示
- 元素按照从左到右、从上到下按顺序依次摆放好
- 默认情况下,元素互相之间不存在层叠现象
在标准流中,可以使用margin、padding对元素进行定位
但是在标准流中,设置一个元素的margin或者padding,通常会影响到标准流中其他元素的定位效果
此外在标准流中,不便于实现元素层叠的效果
为此CSS 提供了position属性,来帮助我们实现将一个元素脱离标准流(脱标),并对其进行定位操作
position属性可选值
| 值 | 说明 |
|---|---|
| static | 静态定位, 默认值, 不脱标, 即布局为 normal flow |
| relative | 相对定位, 不脱标 |
| absolute | 绝对定位, 脱标 |
| fixed | 固定定位, 脱标 |
| sticky | 粘性定位,可以在脱标和不脱标之间切换 |
固定定位 - fixed
.box {
/*
通过将position的值设置为fixed
来为某个元素开启相对定位
*/
position: fixed;
}
-
元素脱离normal flow (脱离标准流、脱标)
-
可以通过left、right、top、bottom进行定位
-
定位参照对象是视口(viewport),
- 当画布滚动时,因为viewport是固定不动,所以开启了固定定位的元素也会固定不动
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.handle {
position: fixed;
right: 30px;
bottom: 30px;
}
.handle .item {
width: 80px;
height: 40px;
text-align: center;
line-height: 40px;
background-color: brown;
color: #fff;
border-radius: 8px;
cursor: pointer;
}
.handle .item:hover {
background-color: red;
}
.top {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="handle">
<div class="item top">顶部</div>
<div class="item bottom">反馈</div>
</div>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
<br><br><br><br><br>
</body>
</html>
绝对定位 - absolute
-
开启了绝对定位的元素脱离normal flow (脱离标准流、脱标)
-
可以通过left、right、top、bottom进行定位
- 定位参照对象是
最邻近的定位祖先元素 - 如果
找不到这样的祖先元素,参照对象是视口
- 定位参照对象是
开启了绝对定位的元素的定位参照元素是最近的那个定位元素,也就是最近的那个position不是fixed的元素
而我们绝大多数情况下,都希望父元素不脱标,只是作为绝对定位元素的定位参照元素,
所以在绝大多数情况下,绝对定位元素的定位参照元素开启的都是相对定位
因为相对定位成为了定位元素,但不脱标,此时我们可以简称为 子绝父相
绝对定位元素特点
-
可以随意设置宽高且 元素宽高默认由内容决定
- 此时看上去 特性和行内块级元素的特性是一致的,但是它不是行内块级元素
当一个元素的position值为absolute或者fixed的时候,这个元素就被称之为 绝对定位元素(absolutely positioned element)
-
不再受标准流的约束
不再严格按照从上到下、从左到右排布不再严格区分块级(block)、行内级(inline),行内块级(inline-block)
- 不再给父元素汇报自己的宽度或高度
- 脱标元素内部默认还是按照标准流布局
此外,对于绝对定位元素来说,存在如下计算方式
定位参照对象的宽度 = left + right + margin-left + margin-right + 绝对定位元素的实际占用宽度 定位参照对象的高度 = top + bottom + margin-top + margin-bottom + 绝对定位元素的实际占用高度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father {
width: 300px;
height: 300px;
background-color: red;
position: relative;
}
/*
此时div.child的参照定位元素为box.father
fatherWidth = childWidth + left + right + marginLeft + marginRight
因为 marginLeft 和 marginRight的默认值是0
得到300 = auto + 0 + 0 + 0 + 0
所以在这里 auto的值为 300
因此auto的本质是 由浏览器来决定需要显示的具体值是多少
高度同理
*/
.child {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: blue;
}
</style>
</head>
<body>
<!-- 绝对定位元素的宽高和定位参照对象一样 -->
<div class="father">
<div class="child"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.father {
width: 300px;
height: 300px;
background-color: red;
position: relative;
}
/*
此时div.child的参照定位元素为box.father
tips:
1. 一定要设置元素的宽度和高度
2. margin四个方向的值都需要设置为auto
fatherWidth = childWidth + left + right + marginLeft + marginRight
此时设置childWidth的值为100
得到 300 = 100 + 0 + 0 + 0 + 0
公式不成立 => 默认情况下,浏览器会把剩余的值全部赋值给marginRight
但是这里设置margin各个方向上的值为auto
=> 300 = 100 + 0 + auto + auto
=> 2auto = 300
=> auto = 150
=> marginLeft = marginRight = 150
=> div.child相对于div.father 水平居中
*/
.child {
width: 100px;
height: 100px;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background-color: blue;
}
</style>
</head>
<body>
<!-- 绝对定位元素在定位参照对象中居中显示 --- 同时满足水平居中和垂直居中 -->
<div class="father">
<div class="child"></div>
</div>
</body>
</html>
粘性定位 - sticky
另外还有一个定位的值是position: sticky,比起其他定位值要新一些.
sticky可以看做是相对定位和固定(绝对)定位的结合体 --- 在展示效果上
它允许被定位的元素表现得像相对定位一样,直到它滚动到某个阈值点
当达到这个阈值点时, 就会变成固定(绝对)定位
sticky是相对于最近的滚动祖先元素,也就是sticky是相对于滚动视口( scrollport )的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.nav {
background-color: #f00;
color: #fff;
/* position: relative;
top: 0;
left: 0;
right: 0; */
position: sticky;
top: 0;
}
</style>
</head>
<body>
<h1>我是标题</h1>
<div class="nav">
<span>电脑</span>
<span>手机</span>
<span>衣服</span>
<span>鞋子</span>
</div>
<ul>
<li>电脑列表1</li>
<li>电脑列表2</li>
<li>电脑列表3</li>
<li>电脑列表4</li>
<li>电脑列表5</li>
<li>电脑列表6</li>
<li>电脑列表7</li>
<li>电脑列表8</li>
<li>电脑列表9</li>
<li>电脑列表10</li>
<li>电脑列表11</li>
<li>电脑列表12</li>
<li>电脑列表13</li>
<li>电脑列表14</li>
<li>电脑列表15</li>
<li>电脑列表16</li>
<li>电脑列表17</li>
<li>电脑列表18</li>
<li>电脑列表19</li>
<li>电脑列表20</li>
<li>电脑列表21</li>
<li>电脑列表22</li>
<li>电脑列表23</li>
<li>电脑列表24</li>
<li>电脑列表25</li>
<li>电脑列表26</li>
<li>电脑列表27</li>
<li>电脑列表28</li>
<li>电脑列表29</li>
<li>电脑列表30</li>
<li>电脑列表31</li>
<li>电脑列表32</li>
<li>电脑列表33</li>
<li>电脑列表34</li>
<li>电脑列表35</li>
<li>电脑列表36</li>
<li>电脑列表37</li>
<li>电脑列表38</li>
<li>电脑列表39</li>
<li>电脑列表40</li>
<li>电脑列表41</li>
<li>电脑列表42</li>
<li>电脑列表43</li>
<li>电脑列表44</li>
<li>电脑列表45</li>
<li>电脑列表46</li>
<li>电脑列表47</li>
<li>电脑列表48</li>
<li>电脑列表49</li>
<li>电脑列表50</li>
<li>电脑列表51</li>
<li>电脑列表52</li>
<li>电脑列表53</li>
<li>电脑列表54</li>
<li>电脑列表55</li>
<li>电脑列表56</li>
<li>电脑列表57</li>
<li>电脑列表58</li>
<li>电脑列表59</li>
<li>电脑列表60</li>
<li>电脑列表61</li>
<li>电脑列表62</li>
<li>电脑列表63</li>
<li>电脑列表64</li>
<li>电脑列表65</li>
<li>电脑列表66</li>
<li>电脑列表67</li>
<li>电脑列表68</li>
<li>电脑列表69</li>
<li>电脑列表70</li>
<li>电脑列表71</li>
<li>电脑列表72</li>
<li>电脑列表73</li>
<li>电脑列表74</li>
<li>电脑列表75</li>
<li>电脑列表76</li>
<li>电脑列表77</li>
<li>电脑列表78</li>
<li>电脑列表79</li>
<li>电脑列表80</li>
<li>电脑列表81</li>
<li>电脑列表82</li>
<li>电脑列表83</li>
<li>电脑列表84</li>
<li>电脑列表85</li>
<li>电脑列表86</li>
<li>电脑列表87</li>
<li>电脑列表88</li>
<li>电脑列表89</li>
<li>电脑列表90</li>
<li>电脑列表91</li>
<li>电脑列表92</li>
<li>电脑列表93</li>
<li>电脑列表94</li>
<li>电脑列表95</li>
<li>电脑列表96</li>
<li>电脑列表97</li>
<li>电脑列表98</li>
<li>电脑列表99</li>
<li>电脑列表100</li>
</ul>
</body>
</html>
postiton各值比较
sticky在效果上是在多个定位状态之间进行切换,所以没有列在表中
对于定位元素,当脱标后,不设置left,right,top,bottom的时候,他们的默认值皆为auto
表现形式为
- 尽可能到达父级定位元素的左上角(也就是left和top值为0)
- 定位元素后边的元素上移
- 定位元素之前的元素不动,且不会被定位元素覆盖
z-index
对于定位元素,默认情况下,写在后面的那个元素会层叠在写在前面的那个元素上
如果我们需要调整定位元素的层叠顺序,我们可以使用z-index
z-index属性用来设置定位元素的层叠顺序(仅对定位元素有效) 取值可以是正整数、负整数、0
z-index的比较原则
-
对于兄弟定位元素
- z-index越大,层叠在越上面
- z-index相等,写在后面的那个元素层叠在上面
-
如果不是兄弟关系
- 各自从元素自己以及祖先元素中,找出
最邻近的那几个兄弟定位元素来进行比较 - 而且这几个兄弟定位元素必须有设置z-index
- 各自从元素自己以及祖先元素中,找出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.item {
position: fixed;
width: 100px;
height: 100px;
left: 0;
top: 0;
background-color: #f00;
}
.box2 {
left: 20px;
top: 20px;
background-color: #0f0;
z-index: -1;
}
.box3 {
left: 40px;
top: 40px;
background-color: #00f;
}
.info {
position: absolute;
z-index: 999;
}
</style>
</head>
<body>
<div class="item box1">1</div>
<div class="container">
<div class="item box2">
<div class="info">哈哈哈</div>
<div>呵呵呵</div>
</div>
</div>
<div class="item box3">3</div>
</body>
</html>