CSS布局 - 定位 -- 笔记4

发布于:2025-09-13 ⋅ 阅读:(22) ⋅ 点赞:(0)

CSS 提供了一些控制网页布局的几个重要工具,这里介绍定位。

元素的定位类型:

定位方式 属性值 描述
静态定位 static 默认值,即标准流,不能通过方位属性进行移动。让盒子固定在屏幕中的某个位置。
固定定位 fixed 在页面中不占位置,相对于浏览器可视区域进行移动。
相对定位 relative 相对于自己之前的位置移动,在页面中占位置(未脱标)。配置绝对定位组(子绝父相),用于小范围的移动
绝对定位 absolute 在页面中不占位置,默认相对于浏览器可视区域进行移动。配置绝对定位组(子绝父相)

前面的布局方式是用各种操作来控制文档流的行为,而定位则不同:它将元素彻底从文档流中移走。它允许你将元素放在屏幕的任意位置。还可以将一个元素放在另一个元素的前面或后面,彼此重叠

定位使用 position 属性,初始值是static。它可以用来构建下拉菜单、模态框以及现代Web应用程序的一些基本效果。定位可能让布局变得很复杂。如果不完全了解定位以及它可能带来的后果,就很容易给自己挖坑。有时候你可能会把错误的元素放在其他元素前面,要解决这个问题却没有那么简单。

固定定位

固定定位是比较好理解的一种定位类型。
给一个元素设置 position: fixed 就能将元素放在视口的任意位置。这需要搭配四种属性一起使用:top、right、bottom和left。这些属性的值决定了固定定位的元素与浏览器视口边缘的距离。比如,top: 3em表示元素的上边缘距离视口顶部3em。

实现一个模态框

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Position Document</title>
  <style>
    :root {
      box-sizing: border-box;
    }

    *,
    ::before,
    ::after {
      box-sizing: inherit;
    }
    /* 设置网页高度,让页面出现滚动条(只为演示) */
    body {
      min-height: 200vh;
      margin: 0;
      font-family: Arial, Helvetica, sans-serif;
    }

    button {
      padding: 0.5em 0.7em;
      border: 1px solid #8d8d8d;
      background-color: white;
      font-size: 1em;
    }

    .top-banner {
      padding: 1em 0;
      background-color: #ffd698;
    }

    .top-banner-inner {
      width: 80%;
      max-width: 1000px;
      margin: 0 auto;
    }

    /* 默认隐藏模态框。打开时,js会设置display: block */
    .modal {
      display: none;
    }

    /* 打开模态框时,用半透明的蒙层遮挡网页剩余内容。四个方向都设置为0,让蒙层填满整个视口 */
    .modal-backdrop {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.5);

      z-index: 1; /* 将模态框的蒙层拉到没有设置z-index的元素前面 */
    }

    /* 模态框主体定位 */
    .modal-body {
      position: fixed;
      top: 3em;
      bottom: 3em;
      right: 20%;
      left: 20%;
      padding: 2em 3em;
      background-color: white;
      overflow: auto; /* 允许模态框主体在需要时滚动 */

      z-index: 1; /* 将模态框的主体拉到蒙层前面 */
    }

    .modal-close {
      position: absolute;
      top: 0.3em;
      right: 0.3em;
      padding: 0.3em;
      cursor: pointer;

      font-size: 2em;
      height: 1em;
      width: 1em;
      text-indent: 10em;
      overflow: hidden;
      border: 0;
    }

    .modal-close::after {
      position: absolute;
      line-height: 0.5;
      top: 0.2em;
      left: 0.1em;
      text-indent: 0;
      content: "\00D7";
    }

    .container {
      width: 80%;
      max-width: 1000px;
      margin: 1em auto;
    }

    /* 创建包含块 */
    .dropdown {
      display: inline-block;
      position: relative;
    }

    .dropdown-label {
      padding: 0.5em 2em 0.5em 1.5em;
      border: 1px solid #ccc;
      background-color: #eee;
    }

    /* 在标签的右边定位元素 */
    .dropdown-label::after {
      content: "";
      position: absolute;
      right: 1em;
      top: 1em;
      border: 0.3em solid;
      border-color: black transparent transparent; /* 用上边框做一个向下的箭头 */
    }

    .dropdown:hover .dropdown-label::after {
      top: 0.7em;
      border-color: transparent transparent black; /* 鼠标悬停时,让箭头向上 */
    }

    /* 最初隐藏菜单; 将菜单移动到下拉菜单下面 */
    .dropdown-menu {
      display: none;
      position: absolute;
      left: 0;
      top: 2.1em;
      min-width: 100%;
      background-color: #eee;
    }

    /* 鼠标悬停时显示菜单 */
    .dropdown:hover .dropdown-menu {
      display: block;
    }

    .submenu {
      padding-left: 0;
      margin: 0;
      list-style-type: none;
      border: 1px solid #999;
    }

    .submenu > li + li {
      border: 1px solid #999;
    }

    .submenu > li > a {
      display: block;
      padding: .5em 1.5em;
      background-color: #eee;
      color: #369;
      text-decoration: none;
    }

    .submenu > li > a:hover {
      background-color: #fff;
    }
    
  </style>
</head>
<body>
  <header class="top-banner">
    <div class="top-banner-inner">
      <p>Find out what's going on at Wombat Coffee each month. Sign up for our newsletter:
        <button id="open">Sign up</button> <!-- 触发弹窗的按钮 -->
      </p>
    </div>
  </header>
  <!-- 模态框容器 -->
  <div class="modal" id="modal">
    <!-- 模态框后面遮挡网页内容的“蒙层” -->
    <div class="modal-backdrop"></div>
    <!-- 模态框内容 -->
    <div class="modal-body">
      <button class="modal-close" id="close">close</button>
      <h2>Wombat Newsletter</h2>
      <p>Sign up for our newsletter. No spam. We promise!
      </p>
      <form action="">
        <p>
          <label for="email">Email address:</label>
          <input type="text" name="email">
        </p>
        <p><button type="submit">Submit</button></p>
      </form>
    </div>
  </div>

  <div class="container">
    <nav>
      <div class="dropdown">
        <div class="dropdown-label">Main Menu</div>
        <div class="dropdown-menu">
          <ul class="submenu">
            <li><a href="/">Home</a></li>
            <li><a href="/coffees">Coffees</a></li>
            <li><a href="/brewers">Brewers</a></li>
            <li><a href="/specials">Specials</a></li>
            <li><a href="/about">About</a></li>
          </ul>
        </div>
      </div>
    </nav>

    <h1>Wombat Coffee Roasters</h1>
  </div>

  <script type="text/javascript">
    var button = document.getElementById('open');
    var close = document.getElementById('close');
    var modal = document.getElementById('modal');
    // 打开模态框
    button.addEventListener('click', function(event) {
      event.preventDefault();
      modal.style.display = 'block';
    });
    // 关闭模态框
    close.addEventListener('click', function(event) {
      event.preventDefault();
      modal.style.display = 'none';
    })
  </script>
</body>
</html>

在这里插入图片描述

控制定位元素的大小

定位一个元素时,不要求指定四个方向的值,可以只指定需要的方向值,然后用width和/或height来决定它的大小,也可以让元素本身来决定大小。

position: fixed;
top: 1em;
right: 1em;
width: 20%;

上面定位,将元素放在距离视口顶部和右边1em的位置,宽度为视口宽度的20%。它省略了bottom和height属性,元素的高度由自身的内容决定。例如,这可以用于将一个导航菜单固定到屏幕上。即使用户滚动网页内容,该元素的位置也不会改变。

因为固定元素从文档流中移除了,所以它不再影响页面其他元素的位置。别的元素会跟随正常文档流,就像固定元素不存在一样。也就是说它们通常会在固定元素下面排列,视觉上被遮挡。

绝对定位

固定定位让元素相对视口定位,此时视口被称作元素的包含块(containing block)​。

绝对定位的包含块不一样。绝对定位不是相对视口,而是相对最近的祖先定位元素。跟固定元素一样,属性top、right、bottom和left决定了元素的边缘在包含块里的位置。

让Close按钮绝对定位

为了让Close按钮绝对定位,将其放在模态框的右上角:

.modal-close {
  position: absolute;
  top: 0.3em;
  right: 0.3em;
  padding: 0.3em;
  cursor: pointer;
}

如果父元素未被定位,那么浏览器会沿着DOM树往上找它的祖父、曾祖父,直到找到一个定位元素,用它作为包含块。
如果祖先元素都没有定位,那么绝对定位的元素会基于初始包含块(initial containing block)来定位。初始包含块跟视口一样大,固定在网页的顶部。

定位伪元素

将Close按钮改成 x:

.modal-close {
  position: absolute;
  top: 0.3em;
  right: 0.3em;
  padding: 0.3em;
  cursor: pointer;

  font-size: 2em;
  height: 1em; /* 让按钮变成小方形,让元素里的文字溢出并隐藏 */
  width: 1em;
  text-indent: 10em; /* text-indent属性将文字推到右边,溢出元素 */
  overflow: hidden;
  border: 0;
}

.modal-close::after {
  position: absolute;
  line-height: 0.5;
  top: 0.2em;
  left: 0.1em;
  text-indent: 0; /* text-indent是继承属性,需要在伪类元素选择器上设为0,x便不会缩进 */
  content: "\00D7"; /*相比字母x,推荐用乘法符号的Unicode字符。它更对称,也更好看。HTML字符&times;可以显示为这个字符,但在CSS的content属性里,必须写成转义的Unicode数字:\00D7。*/
}

相对定位

相对定位不太好理解。当第一次给元素加上position: relative的时候,你通常看不到页面上有任何视觉改变。相对定位的元素以及它周围的所有元素,都还保持着原来的位置。

如果加上top、right、bottom和left属性,元素就会从原来的位置移走,但是不会改变它周围任何元素的位置。

跟固定或者绝对定位不一样,不能用top、right、bottom和left改变相对定位元素的大小。这些值只能让元素在上、下、左、右方向移动。可以用top或者bottom,但它们不能一起用(bottom会被忽略)​。同理,可以用left或right,但它们也不能一起用(right会被忽略)​。
更常见的用法是使用position: relative给它里面的绝对定位元素创建一个包含块。

创建一个下拉菜单

将下面代码添加到HTML中,放在

后面。这段代码包含了一个容器元素,之后我们会将它的内容居中,并让它跟顶部条的内容对齐。

<div class="container">
    <nav>
      <div class="dropdown">
        <div class="dropdown-label">Main Menu</div>
        <div class="dropdown-menu">
          <ul class="submenu">
            <li><a href="/">Home</a></li>
            <li><a href="/coffees">Coffees</a></li>
            <li><a href="/brewers">Brewers</a></li>
            <li><a href="/specials">Specials</a></li>
            <li><a href="/about">About</a></li>
          </ul>
        </div>
      </div>
    </nav>

    <h1>Wombat Coffee Roasters</h1>
  </div>

在这里插入图片描述

使用伪元素创建一个三角形

用边框画一个三角形当作向下箭头。这里用标签的::after伪元素来画三角形,然后使用绝对定位将它放到标签的右边。

/* 在标签的右边定位元素 */
.dropdown-label::after {
  content: "";
  position: absolute;
  right: 1em;
  top: 1em;
  border: 0.3em solid;
  border-color: black transparent transparent; /* 用上边框做一个向下的箭头 */
}

.dropdown:hover .dropdown-label::after {
  top: 0.7em;
  border-color: transparent transparent black; /* 鼠标悬停时,让箭头向上 */
}

在这里插入图片描述

伪元素因为没有内容,所以没有宽或高。用border-color简写属性设置上边框为黑色,左右和下面的边框为透明,构造一个向下的箭头。
打开菜单,箭头方向反转,朝向上面,表示菜单可以被关闭。微调top值(从1em到0.7em)​,让向上的箭头看起来跟向下的箭头处于相同的位置。