CSS 学习之 position 定位

2018/09/30 FrontEnd

前端页面的定位比安卓页面的定位略微复杂一些。

定位

默认情况下,块级元素的内容宽度是其父元素的宽度的100%,并且与其内容一样高。

内联元素高宽与他们的内容高宽一样。

您不能对内联元素设置宽度或高度——它们只是位于块级元素的内容中。

如果要以这种方式控制内联元素的大小,则需要将其设置为类似块级元素 display: block

默认情况下,块级元素每个都单独一行,外边距会把块级元素分隔开。

如果两个相邻元素都在其上设置外边距,并且两个外边距接触,则两个外边距中的较大者保留,较小的一个消失——这叫“外边距折叠”。

CSS 中使用 position 实现定位,可选的值:

  1. static,默认值,将元素放在前一个元素后面,没什么特别的
  2. relative,相对布局,相当于在静态布局的基础上增加了设置上下左右边距的功能
  3. absolute,绝对布局,不再存在于正常文档流
  4. fixed, 固定定位,相对于浏览器窗口
  5. sticky, 粘性定位

relative 相对定位

relative 表现的和 static 一样,除非你添加了一些额外的属性(left right top bottom)。

在使用相对定位时,就算元素被偏移了,但是他仍然占据着它没偏移前的空间。

absolute 绝对定位

绝对布局坐在它自己的层独立于一切。这是非常有用的:这意味着我们可以创建不干扰页面上其他元素的位置的隔离的UI功能 。例如,弹出信息框和控制菜单;翻转面板;可以在页面上的任何地方拖放的UI功能…

绝对布局的 top bottom left right指定的是元素距离每个包含元素的边的距离,而不是指定元素应该移入的方向,也就是说,到包含元素上下左右边框的距离,如果都设置为 0,那它可能会超出父布局的范围。

【重要】⤵️

如果想为元素设置层模型中的绝对定位,需要设置元素为 position:absolute(表示绝对定位),将元素从文档流中拖出来,然后使用left、right、top、bottom 属性相对于其最接近的一个具有定位属性(position 值非 static)的父包含块进行绝对定位。

如果不存在这样的包含块(就是它的祖先标签里并没有设置非 static 定位的属性),则相对于body元素,即相对于浏览器窗口。

默认情况下,绝对布局的包含元素是 body 元素。

我们可以通过给绝对布局的祖先元素设置定位来改变它的包含元素,祖先元素的 position 值为relativeabsolute 效果不一样,但一致的是,绝对布局元素会被限制在设置了定位的祖先元素范围内。

fixed 固定定位

相对于浏览器窗口固定,可以用于创建固定的导航栏等。

定位的内容不再出现在文档流中,所以其他内容会跑到它的下面,解决办法是设计外边距。

h1 {
	position: fixed;
	width: 500px;
	top: 0; 		//top:0 表示贴到顶部
	margin: 0 auto;
	background: #eeeeee;
	padding: 10px;
}

广告位招租(•̀ᴗ•́)و

sticky 粘性定位

MDN 粘性定位

粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。

z-index(Z 轴层级)

(0,0)位于页面(或元素)的左上角,x和y轴跨页面向右和向下,和安卓的一样。

z-index 值影响定位元素位于该轴上的位置;正值将它们移动到堆栈上方,负值将它们向下移动到堆栈中。

默认情况下,定位的元素都具有 z-indexauto,实际上为0。

z-index 属性适用于定位元素(position 属性值为 relative 或 absolute 或 fixed 的对象),用来确定定位元素在垂直于显示屏方向(称为Z轴)上的层叠顺序。也就是说:如果元素是没有定位的,对其设置的 z-index 会是无效的。

如果父元素 z-index 失效(未定位或者使用默认值),那么定位子元素的 z-index 设置生效;否则子元素的 z-index 无效。

Z 轴层级小结:

  1. z-index 只对定位元素有效
  2. z-index 有效子无效;父无效子有效
  3. 都没有 z-index,定位元素在上层
  4. 都没有,且都定位,源代码中后面的在上层

定位实战

MDN 定位实战

所谓的”单页应用“正在变得非常流行——尤其是移动网页UI——因为把一切的服务放在一个单独的文件上可以减少HTTP请求的数量来浏览所有内容,从而提高性能。

实战 1:切换 tab 效果

实现一个切换 tab 的思路:

  1. 无序列表作为 tab,css 里设置不同状态下的样式、浮动
  2. 用几个相同类型的布局 (article,div…)放置内容
  3. 内容的父布局设置为相对布局 relative,那样子布局就可以相对父布局放置,而不是默认的相对 body 放置
  4. 内容布局设置为绝对布局 absolute,左上角距离都是 0
  5. 然后设置一个选中状态下的内容样式,z-index 增加为 1,那样它就会显示到最上层
  6. 最后在 js 中,在每个 tab 的点击事件里,移除所有旧 tab 的 class,给当前 tab 设置选中状态下的 class
<!DOCTYPE html>
<html>
<head>
	<title>定位实战</title>
	<link rel="stylesheet" type="text/css" href="css/day-7-layout-1.css">
	<script type="text/javascript">
		var tabs = document.querySelectorAll('.info-box li a');
		var panels = document.querySelectorAll('.info-box article');

		for (var i = 0; i < tabs.length; i++) {
			var tab = tabs[i];
			setClickHandler(tab, i);
		}

		function setClickHandler(tab, tabPos){
			tab.onclick = function () {
				alert('click' + tabPos);

				for(var i = 0; i < tabs.length; i ++ ){
					if (tabs[i].getAttribute('class')) {
						tabs[i].removeAttribute('class');
					}
				}

				tab.setAttribute('class', 'active');

				for(var i = 0; i < panels.length; i ++ ){
					if (panels[i].getAttribute('class')) {
						panels[i].removeAttribute('class');
					}
				}
				panels[tabPos].setAttribute('class', 'active-panel');
			}
		}
	</script>
</head>
<body>
<section class="info-box">
  <ul>
    <li><a href="#" class="active">Tab 1</a></li>
    <li><a href="#">Tab 2</a></li>
    <li><a href="#">Tab 3</a></li>
  </ul>
  <div class="panels">
    <article class="active-panel">
      <h2>The first tab</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. Vestibulum et orci scelerisque, vulputate tellus quis, lobortis dui. Vivamus varius libero at ipsum mattis efficitur ut nec nisl. Nullam eget tincidunt metus. Donec ultrices, urna maximus consequat aliquet, dui neque eleifend lorem, a auctor libero turpis at sem. Aliquam ut porttitor urna. Nulla facilisi.</p>
    </article>
    <article>
      <h2>The second tab</h2>

      <p>This tab hasn't got any Lorem Ipsum in it. But the content isn't very exciting all the same.</p>
    </article>
    <article>
      <h2>The third tab</h2>

      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. And now an ordered list: how exciting!</p>

      <ol>
        <li>dui neque eleifend lorem, a auctor libero turpis at sem.</li>
        <li>Aliquam ut porttitor urna.</li>
        <li>Nulla facilisi</li>
      </ol>
    </article>
  </div>
</section>
</body>
</html>

实战 3:抽屉效果

<!DOCTYPE html>
<html>
<head>
	<title>定位实战3</title>
	<style type="text/css">
		label[for="toggle"] {
		  font-size: 3rem;
		  position: absolute;
		  top: 4px;
		  right: 5px;
		  z-index: 1;
		  cursor: pointer;
		}

		input[type="checkbox"] {
		  position: absolute;
		  top: -100px;
		}

		aside {
		  background-color: #a60000;
		  color: white;

		  width: 340px;
		  height: 98%;
		  padding: 10px 1%;

		  position: fixed;
		  top: 0;
		  right: -370px;

		/*在元素上设置 transition 属性,Transitions是一个有意思的特性,允许你在状态改变的时候平滑的过渡,而不是粗暴的“开”或“关”*/
		  transition: 0.6s all;
		}

		input[type=checkbox]:checked + aside {
		  right: 0px;
		}
	</style>
</head>
<body>
<label for="toggle"></label>
<input type="checkbox" id="toggle">
<aside>

  balabala

</aside>
</body>
</html>

在元素上设置 transition 属性,Transitions是一个有意思的特性,允许你在状态改变的时候平滑的过渡,而不是粗暴的“开”或“关”

实现抽屉效果思路:

  1. 使用 label 标签,for 值为我们给 checkbox 设置的 id,表示点击这个标签等于点击了这个开关
  2. 将 label 放置在屏幕右侧,定位为绝对定位,z-index 为 1,位于最上层
  3. 将 checkbox 隐藏
  4. 将要作为抽屉的布局设置为固定布局,那样将来页面滚动它也始终在同一位置,同时可以使用 topright 控制它的位置
  5. 给抽屉布局设置 transition 属性,允许布局状态改变时使用动画
  6. 最后在 checkbox 被选中时,修改抽屉布局的 right 属性,即水平位置

Search

    Table of Contents