定位
定位允许你从正常的文档流布局中取出元素,并使它们具有不同的行为,例如放在另一个元素的上面,或者始终保持在浏览器视窗内的同一位置。
定位是你的工具。或者,如果你想要创建一个浮动在页面其他部分顶部的 UI 元素,并且/或者始终停留在浏览器窗口内的相同位置,无论页面滚动多少?定位使这种布局工作成为可能。
文档流
默认情况下,块级元素的内容宽度是其父元素的宽度的100%,并且与其内容一样高。
内联元素高宽与他们的内容高宽一样。你不能对内联元素设置宽度或高度——它们只是位于块级元素的内容中。如果要以这种方式控制内联元素的大小,则需要将其设置为类似块级元素 display: block;
。
静态定位
静态定位是每个元素获取的默认值——它只是意味着“将元素放入它在文档布局流中的正常位置 ——这里没有什么特别的。
相对定位
与静态定位相似,占据在正常的文档流中。
1 | position: relative; |
介绍 top、bottom、left 和 right
这四个属性分别用来精确定位元素要移动的位置。
相对移动(理解成一个力在推动):
- top ->力从上往下
- bottom->从下往上
- left->从左往右
- right->从右往左
1 | .positioned{ |
绝对定位
1 | position: absolute; |
我们观察到,定位的元素在文档流的间隙不再存在,第一个元素和第三个元素已经靠在一起,仿佛第二个元素不存在了。
绝对元素不再存在于正常的文档流中。
可以使用top等设置元素位置。
定位上下文
如果所有的父元素都没有显式地定义 position 属性,那么所有的父元素默认情况下 position 属性都是 static。
绝对定位元素会被包含在初始块容器中。这个初始块容器有着和浏览器视口一样的尺寸,并且<html>元素也被包含在这个容器里面。简单来说,绝对定位元素会被放在<html>元素的外面,并且根据浏览器视口来定位。
绝对定位元素在 HTML 源代码中,是被放在<body>中的,但是在最终的布局里面,它的显示位置是相对于浏览器页面的。
我们可以改变定位上下文 —— 绝对定位的元素的相对位置元素。通过设置其中一个父元素的定位属性 —— 也就是包含绝对定位元素的那个元素(如果要设置绝对定位元素的相对元素,那么这个元素一定要包含绝对定位元素)。
例如:我们在body元素中设置position:relative
,则body中使用绝对定位的元素将以body作为参照。
介绍 z-index
决定哪些元素出现在其他元素的顶部
在源代码中的后定位的元素将赢得先定位的元素,也就是说后定位的元素将覆盖显示在先定义的元素之上。
使用z-index
属性。
“z-index”是对 z 轴的参考。
你可以从源代码中的上一点回想一下,我们使用水平(x 轴)和垂直(y 轴)坐标来讨论网页,以确定像背景图像和阴影偏移之类的东西的位置。
(0,0)位于页面(或元素)的左上角,x 和 y 轴跨页面向右和向下(适合从左到右的语言,无论如何)。
网页也有一个 z 轴:一条从屏幕表面到你的脸(或者在屏幕前面你喜欢的任何其他东西)的虚线。z-index
值影响定位元素位于该轴上的位置;正值将它们移动到堆栈上方,负值将它们向下移动到堆栈中。默认情况下,定位的元素都具有 z-index 为 auto,实际上为 0。
z-index 只接受无单位索引值
固定定位
这与绝对定位的工作方式完全相同,只有一个主要区别:绝对定位将元素固定在相对于其位置最近的祖先。(如果没有,则为初始包含它的块)而固定定位固定元素则是相对于浏览器视口本身。这意味着你可以创建固定的有用的 UI 项目,如持久导航菜单。
position: sticky
比起其他位置值要新一些。它基本上是相对位置和固定位置的混合体,它允许被定位的元素表现得像相对定位一样,直到它滚动到某个阈值点
(例如,从视口顶部起 10 像素)为止,此后它就变得固定了。
定位实例练习
列表消息盒子
效果
结构
1 | section(info-box)- ul- li-a(active) |
思路
- 将样式化选项卡看起来是一个标准的水平导航菜单,使用绝对定位样式化面板互相坐落其顶上。
- 当选项卡被按下时,显示对应的面板,并且样式化选项卡本身。
实现
一般设置
1 | html { |
- 设置了无衬线的字体
- 使用 box-sizing 模型
- 去掉<body>默认外边距。
样式设置
设置信息盒子宽高、位置
1 | .info-box { |
设置选项卡样式
从外到内,设置边框,选项卡高度,内外边距,设置外溢部分自动隐藏
1 | .info-box ul { |
设置选项卡选项,左浮动,取消无序列表图形,设置每个选项的宽度
1 | .info-box li { |
设置选项卡选项超链接文本样式
1 | .info-box li a{ |
设置鼠标悬停时和点击后的选项卡样式
1 | .info-box li a:focus, .info-box li a:hover { |
设置默认时选中的选项卡样式
1 | .info-box li a.active { |
设置信息面板盒子样式
从外到内,清除面板盒子两侧浮动、设置面板盒子子元素的参照为父元素、设置面板盒子高度
1 | .info-box .panels{ |
设置acticle盒子样式、设置背景颜色、设置为绝对定位、设置内边距、设置高度、设置偏移量
1 | .info-box article{ |
设置默认显示的面板
1 | .info-box .active-panel { |
脚本设置
1 | <script> |
- 首先我们保存所有的选项卡和所有的面板引用到两个变量中,名为
tabs
和panels
,这样此后我们可以容易地为它们做事。 - 然后我们使用
for
循环遍历所有的选项卡,并且在每一个上运行叫做setTabHandler()
的函数,此函数建立当每个选项卡被点击时应该发生的功能。运行时,函数会被传递选项卡,和一个索引数i
指明选项卡在tabs
数组中的位置。 - 在
setTabHandler()
函数中,这个标签创建了一个onclick
事件来处理点击,所以当标签被点击的时候,接下来会发生:- 用一个
for
循环清除所有标签当前存在的类。 - 当点击的时候在标签上创建了一个
active
类——从相关联的元素中继承了 CSS 的一些属性,具有和 panels 的样式相同的color
和background-color
。 - 用一个
for
循环清除所有面板当前存在的类。 - 当标签被点击的时候在和标签相对应的面板上创建了一个
active-panel
类——从相关联的元素中继承了 CSS 的一些属性,使其z-index
属性被设置为 1,让它能位于所有的面板的上面。
- 用一个
一个固定位置的列表消息盒子
使用
position:fixed
固定
一个滑动隐藏的面板
效果
点击某处,然后消息盒子从边界滑出主界面。
结构
1 | body-lable(for="toggle") |
思路
利用有名的 checkbox hack 技术,可以提供无 JavaScript 的方法来通过按钮来控制一个元素。本例中利用
label
和input
标签控制aside
的隐藏和显示。
通过for属性绑定id
到了<input>
标签的 checkbox 元素。(实现的效果是点击lable,相当于是点击了label和input标签,因为他们绑定在了一起。)
实现
样式设置
设置label样式,字体大小、固定位置、设置z-index避免信息面板覆盖图标、改变悬浮时鼠标指针为手型
1 | label[for="toggle"] { |
设置checkbox样式,只需要隐藏掉就行,我们不需要用户看到它
使用checkbox是为了记录当前的状态。
1 | input[type="checkbox"] { |
面板设置
设置背景、字体颜色、
设置宽高和内边距、
设置位置,默认时隐藏(将绝对定位的偏移值设置为负值)、
1 | aside { |
设置checkbox被选中后,aside滑出
我们选择与 <input>
元素邻接的 <aside>
元素,但是仅仅在它被选择时(请注意使用 :checked
伪类来实现此目的),在这种情况下,我们将 <aside>
的 right
属性设置为 0px,会造成面板再次出现在屏幕上(由于过渡属性会平滑的出现)。再一次点击这个标签会取消选中 checkbox,面板将会跟着再一次消失。
1 | input[type=checkbox]:checked + aside { |
这中hack
方法的不足
这种效果确实有一些问题 ——这是有点滥用表单元素(它们不是为了这个目的),并且在无障碍方面效果不是很好——标签在默认情况下不可聚焦,并且表单元素的非语义使用可能会导致屏幕朗读器出现问题。JavaScript 和链接或按钮可能更合适,但这样的实验仍然很有趣。