这篇文章,我们学习一个新的布局方法——定位。
定位在网站布局中随处可见,像地图的标记点,电商网站的各种标识和按钮,浮动快捷入口,吸附导航等等效果。
position 属性指定了一个元素定位方式,它有五个不同的类型值:static 静态定位,relative 相对定位,fixed 固定定位,absolute 绝对定位,sticky粘性定位。给元素设置了 position 属性后,再使用 top、bottom、left 和 right 属性对元素进行定位。
我们先来学习相对定位。
position 属性值 relative,可以设置元素为相对定位,相对定位有什么特点呢?我们通过例子来看。
创建 position.html 文件和 position-style.css 文件。打开 html 文件,构建基础代码,引入外部样式。在body里输入 emmet 命令:div.container>(div[class=box$]{盒子$})*3,回车。在一个大的容器里创建了三个小盒子。
HTML
盒子1
盒子2
盒子3
打开 css 文件,定义通用选择器,声明样式 box-sizing: border-box。定义分组选择器 html, body,声明样式 height: 100%,让 html 和 body 撑满整个页面。定义选择器 body,声明样式 margin: 0,去除 body 的外边界。
给外部容器里的三个盒子(.container > div)定义样式: float: left,width: 150px,height: 150px,border: 1px solid black,line-height: 150px,text-align: center,固定的宽高,1 像素的边框,文本水平垂直居中,水平横向排列。
为了消除浮动对其他容器的影响,给 container 定义伪元素(.container::after ),声明样式为:content: "",clear: both,display: block。
再分别给 box1 添加背景颜色 orange,给 box2 添加背景颜色 skyblue,给 box3 添加背景颜色 hotpink。
CSS
* {
box-sizing: border-box;
}
html, body {
height: 100%;
}
body {
margin: 0;
}
.container > div {
float: left;
width: 150px;
height: 150px;
border: 1px solid black;
line-height: 150px;
text-align: center;
}
.container::after {
content: "";
clear: both;
display: block;
}
.box1 {
background-color: orange;
}
.box2 {
background-color: skyblue;
}
.box3 {
background-color: hotpink;
}
到浏览器里看一下效果,三个用来实验的盒子就做好了。
回到 css,我们给 box2 添加样式 position: relative,让它相对定位。
此时,我们发现盒子2没有任何变化。
再回到 css,给 box2 添加样式 left: 50px,top: 50px。
CSS
.box2 {
position: relative;
left: 50px;
top: 50px;
}
再来看效果,盒子2向右和向下各偏移了 50px,并盖在了盒子3的上面。
通过这个实验,我们总结相对定位的几个特点:第一,position: relative ruai 定位样式需要配合 left、top、right、bottom 这些定位属性才能生效。第二,relative 相对的是容器自身的屏幕坐标 0,0 点。第三,容器位置发生位移后,原来占据的空间依然保留。第四,默认会覆盖没有定位的容器。
接下来学习绝对定位。
注释掉相对定位的样式代码。给 box2 添加样式 position: absolute,让它绝对定位。
CSS
.box2 {
position: absolute;
}
在浏览器里观察效果,盒子1 怎么消失了?原来,当一个容器为绝对定位时,它会脱离文档流,盒子2 盖在了盒子1 的上面。
给 box2 添加样式 left: 50px,top: 50px。
CSS
.box2 {
position: absolute;
left: 50px;
top: 50px;
}
再看看效果,盒子 1 显露出来了,盒子2 向右和向下各偏移了 50px,盖在了两个盒子的上面。
这里有个问题,盒子 2 已经脱离了文档流,它位移坐标的参照点是哪里呢?目前看,它是相对于窗口的屏幕坐标 0,0 点。再做一个实验。
回到 css,给外部容器 container 声明样式 display: inline-block,margin-top: 100px,margin-left: 100px,让它向下向右偏移 100px 的距离。显示属性设置为 inline-block,是为了防止margin 塌陷。
再仔细观察一下效果,盒子2 的确是相对于窗口左上角发生了位移,窗口对应的元素就是body 了。这说明,默认情况下,绝对定位的参照点是 body 元素的坐标起始点。
可以修改绝对定位元素的参照点吗?我们再做一个实验。
回到 css,给 container 添加样式 position: relative,也就是给盒子2 的父元素添加了一个相对定位。
再看一下效果,盒子2 相对于它的父容器定位了。
如果把 container 的定位样式值改为 absolute,效果如何呢?
我们看,盒子2 的位置没有发生变化。这说明,盒子2 定位的参照元素只要设置了定位属性,无论是哪一种定位方式都可以。但 static 静态定位例外,其实,static 表示元素为静态定位,也就是和不给元素添加 position 属性是等价的。
比如,注释掉 container 容器的定位属性。
此时,盒子2 又相对于 body 来定位了。
如果再添加样式 position: static。
效果是一样的。
你可能还会问,绝对定位只参照父元素和 body 来定位吗?我们再做一个实验。
回到 html,在 container 外部再添加一个父元素 div,定义属性。
HTML
盒子1
盒子2
盒子3
回到 css,给 outer 添加样式:display: inline-block,width: 600px,height: 500px,background-color: aliceblue,margin-left: 100px,margin-top: 100px,定义最外部容器的宽高,背景颜色,并向右下方设置100px的位置偏移。
CSS
.outer {
display: inline-block;
width: 600px;
height: 500px;
background-color: aliceblue;
margin-left: 100px;
margin-top: 100px;
}
此时,盒子1 和 盒子3 随着整个盒子发生偏移,盒子2 还是相对 body 定位。
注释掉 container 的定位样式,重新设置它为绝对定位。再给 outer 声明一个 position: relative 样式。现在,box2 的父容器和祖先容器都设置了定位,它会参照谁来定位呢?
很显然,盒子2 相对于父容器来定位了
如果注释掉父容器 container 的定位样式。盒子2 相对于祖先元素 outer,还是相对于 body 来定位呢?
答案显而易见,相对于 outer 定位了。
再去掉 outer 的定位样式。盒子2 又相对于 body 定位了。
通过绝对定位的这些实验,我们总结绝对定位的几个特点:第一,绝对定位的元素会脱离文档流。第二,绝对定位的参照点为,有定位设置的离他最近的祖先元素的 0,0 点坐标。第三,绝对定位的容器默认会覆盖没有定位的容器。 接下来学习固定定位。注释掉 box2 的定位相关样式。添加样式:position: fixed,right: 0,top: 100px,定义 box2 为固定定位,位置紧贴参照容器右侧
CSS
.box2 {
position: fixed;
right: 0;
top: 100px;
}
我们发现,容器2 相对于 body 定位了。其实,它只相对于 body 定位。
即使祖先元素有定位,比如打开父容器 container 的定位样式注释。
我们看,容器2 的位置依然不变。你会说,这不是和绝对定位类似嘛,是的,固定定位其实就是绝对定位的特例。那它有什么特殊用途呢?
回到 css,给 body 添加 2000px 的高度。
CSS
body {
height: 2000px;
}
滚动页面,我们发现:盒子2 仍旧固定不动。
你在浏览器网站时,是不是见过这个效果呢?
通过实验,我们总结固定定位的特点:第一、固定定位的元素是相对于浏览器视口定位的,这意味着即使页面发生滚动,它也始终保持在同一个位置。第二、top、right、bottom和left属性被用来定位元素,但不是必须的。
最后来学习粘性定位。它会产生动态效果,很像 static 和 fixed 的结合:某些状态下是static 定位,某些状态下自动变成了 fixed 定位。
回到 css,注释掉 box2 里的定位样式,添加样式:position: sticky,top: 100px。
静态预览没有效果,滚动一下窗口,也没有啥特殊效果。
一般情况下,粘性定位没有效果,有几个原因:第一、父元素不能添加 overflow: hidden 或者 overflow: auto 属性。第二、元素自身必须声明 top、bottom、left、right 一个或多个属性,否则就相当于静态定位了。第三,父元素的高度不能低于 sticky si tei k定位元素的高度。第四,sticky 定位元素仅在其父元素内生效。
仔细检查一下,应该是第三个原因。父容器如果滚动起来,就能看到效果了。
回到 html,在 body 里添加一个新的 div 容器,定义 属性,填入一些文本。
CSS
盒子4
回到 css,注释掉 box2 的定位样式。定位选择器 .box4,声明样式:height: 30px,background-color: darkgrey,margin-top: 20px,text-align: center,line-height: 30px,定义容器的基本样式。position: sticky,top: 0,定义容器为粘性定位。
CSS
.box4 {
height: 30px;
background-color: darkgrey;
margin-top: 20px;
text-align: center;
line-height: 30px;
position: sticky;
top: 0;
}
我们来看一下效果:当滚动页面时,开始一段时间盒子4表现的和普通容器一样,随着页面滚动而滚动,当它距离父容器顶部,到达我们在样式里设置的定位值的时候,这里是 top: 0,就表现为固定定位了。
需要注意,这里的 top: 0,指的是当容器为固定定位状态时,相对于父容器的顶部的距离,并不是容器初始定位。比如,把 top 的值改为 100px。我们看,盒子4 初始位置并没有什么变化。当滚动页面时,盒子4 到达了距离父容器顶部 100px的位置,就固定不动了。
通过实验,我们总结粘性定位的几个特点:第一,粘性定位初始状态相当于 static定位。第二,相对于父容器的定位条件符合时,容器变现为固定定位。第三,top、right、bottom或left 至少声明一个,粘性定位才能生效。
本篇文章配套的教程链接:https://www.bilibili.com/vide...