CSS 定位
之前讨论的盒模型, 其作用就是为了控制元素的尺寸的. 接着我们便是要来了解元素的位置, 即左右布局.
在早期的时候, 为了实现盒子的左右布局, 会用到浮动, float: left/right
, 当元素浮动时, 会脱离文档流
, 根据 float 左或者右移, 直到它的边界碰到父元素内边界或者另一浮动元素的边界为止.
浮动的出现是为了当时实现 文字环绕
的效果, 只是后来大家误用来做布局. 用它会带来很多的副作用, 如高度塌陷, 后面处理上都要进行清除浮动处理. 自 flex
即弹性布局出现以后, float
就可以被替代了, 因此也不再多讲.
定位 position
在 css 中, position 属性用于指定一个元素在文档中的定位方式, 其中 top, right, bottom, left 属性则决定元素的最终位置.
- static: 不加任何定位的默认样式
- relative: 相对定位, 不脱离文档流, 相对与自身进行偏移, 原点坐标在盒子左上角
- absolute: 绝对定位, 要脱离文档流, 相对祖先元素进行偏移,若祖先非 static, 则对应视口, 滚动条影响
- fixed: 固定定位, 要脱离文档流, 类似绝对定位, 但会固定在可视区中, 滚动条不影响
- sticky: 粘性定位
相对定位 relative
- 相对定位元素, 是在文档中的正常位置, 偏移给定的值
- 不影响其他的布局
- 相对于自身进行偏移
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>relative</title>
<style>
.box1 {
width: 100px;
height: 100px;
background-color: pink;
}
.box2 {
width: 100px;
height: 100px;
background-color: skyblue;
position: relative;
/* 以左上角为原点, 向右移动 100px */
left: 100px;
/* 仍以左上角为原点, 向下移动 100px */
top: 100px;
}
.box3 {
width: 100px;
height: 100px;
background-color: gold;
}
</style>
</head>
<body>
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</body>
</html>
绝对定位 absolute
-
绝对定位元素会脱离文档流, 并不占据空间
-
具备内联盒子特性, 宽度由内容决定
-
具备块级盒子特性, 支持所有样式
-
相对于最近的非 static 祖先元素定位, 当祖先不存在, 则相对于可视区定位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>absolute</title>
<style>
body {
height: 2000px;
position: relative;
}
.box1 {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: 200px;
/* 当祖先元素定位是非 static时, 则对应安排, 优先参考最近的 */
position: relative;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
/* 若祖先无别的定位布局, 则默认可视区, 即浏览器左上角 */
top: 0;
right: 0;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
这里就产生一个高频常用的定位技巧: 子绝父相
. 即给父元素进行相对定位, 然后子元素进行绝对定位, 这样通过对子元素的 top, left, right, bottom 的控制就是相对于父元素来说的啦.
.box1 {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: 200px;
/* 父元素: 相对定位, 啥也不写 */
position: relative;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
/* 子元素: 绝对定位, 其top,left ... 都是参考父元素来的哈 */
top: 50px;
left: 20px;
}
<body>
<div class="box1">
<div class="box2"></div>
</div>
固定定位 fixed
- 固定定位类似绝对定位, 会脱离文档流, 但会固定在可视区中, 不受滚动条影响
- 具备内联盒子特性, 宽度由内容决定
- 具备块级盒子特性, 支持所有样式
- 固定定位不受祖先元素影响, 就固定在浏览器用户可视区
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fixed</title>
<style>
body {
height: 2000px;
position: relative;
}
.box1 {
width: 500px;
height: 500px;
border: 1px solid #000;
margin: 200px;
position: relative;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
position: fixed;
/* 固定定位, 相对于用户可视区来说的, 不管祖先元素是否有其他定位 */
top: 0;
left: 0;
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
粘性定位 sticky
- sticky 约等于 relative + fixed 的混合, 元素跨定阈值前是相对定位, 超过则为固定定位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fixed</title>
<style>
body {
/* 给 body 设置高就会出现滚动条 */
height: 2000px;
width: 200px;
position: relative;
}
div {
background-color: pink;
position: sticky;
/* 网上滚动, 一开始是相对定位, 一定距离可视区 50px时, 它就固定住啦 */
top: 50px;
}
</style>
</head>
<body>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<div>这是一个粘性盒子</div>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
<p>pppppppppppppppppppp</p>
</body>
</html>
最常用的场景是固定网页导航栏, 或者说表格固定首行首列等.
display 属性
在 css 中, display
属性表示 "显示框类型", 即不同的盒模型.
- display-outside
- block, 将元素转为块级盒子
- inline, 将元素转为内联盒子
- inline-block, 对外表现内联, 对内表现块级
- display-inside
- flex, 子元素弹性布局
- grid, 子元素网格布局
- table, 子元素表格布局的块盒子
- ...
- disply-listitem
- list-item, 生成一个容纳内容和单独列表内元素的块级盒子
- disply-internal -- 不咋用
- display-box -- 不咋用
- dispaly-legacy
- inline-block, 对外表现内联, 对内表现块级
- inline-flex, 对外表现内联, 对子元素表现弹性
- inline-grid, 对外表现内联, 对子元素表现网格
- display-global -- 不咋用
值得关注的一种现象是 inline-block
, 既具备内联盒子特性-横向排列, 同时又支持宽高.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fixed</title>
<style>
.box {
display: inline-block;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box">块01</div>
<div class="box">块02</div>
<div class="box">内联01</div>
<div class="box">内联02</div>
</body>
</html>
当然后面这种横向布局可以梭哈flex
即可, 包括 BFC
等隔离的独立容器实现.
小结
- CSS 盒模型, 标准 / 奇异
box-sizing: border-box
, 宽高包含内边距和边框, 内容往里缩 - 定位相关:
position: relative / absolute / fixed / sticky
, "子绝父相" 用得很多 - diplay 的内外属性, BFC, 默认样式清除, flex 局部引入等
基本就这些, 搞懂之后, 外加一手 flex 布局这块就基本差不多啦.
耐心和恒心, 总会获得回报的.