粘性定位(sticky positioning)

基本含义

粘性定位是相对定位和固定定位的结合体:正常状况下,元素会随着页面滚动,当到达屏幕的特定位置时(设置值),若是用户继续滚动,它就会“锁定”在这个位置。javascript

例子

<!doctype html>
<head>
  <style>
    body {
      font-family: Helvetica, Arial, sans-serif;
      min-height: 200vh;
      margin: 0;
    }

    button {
      padding: .5em .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;
    }

    .modal {
      display: none;
    }

    .modal-backdrop {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background-color: rgba(0, 0, 0, 0.5);
      z-index: 1;
    }

    .modal-body {
      position: fixed;
      top: 3em;
      bottom: 3em;
      right: 20%;
      left: 20%;
      padding: 2em 3em;
      background-color: white;
      overflow: auto;
      z-index: 2;
    }

    .modal-close {
      position: absolute;
      top: 0;
      right: 0;
      padding: 0.3em;
      font-size: 2em;
      height: 1.5em;
      width: 1.5em;
      cursor: pointer;
      border: 0;
    }
    .modal-close::before {
      display: block;
      content: '\00D7';
    }

    .sr-only {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
    }

    .container {
      display: flex;
      width: 80%;
      max-width: 1000px;
      margin: 1em auto;
      min-height: 100vh;
    }

    .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-top: 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;
    }

    .col-main {
      flex: 1 80%;
    }

    .col-sidebar {
      flex: 20%;
    }

    .affix {
      position: sticky;
      top: 1em;
    }

  </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">
        <span class="sr-only">close</span>
      </button>
      <h2>Wombat Newsletter</h2>
      <p>Sign up for our monthly newsletter. No spam.
         We promise!</p>
      <form>
        <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">
  <main class="col-main">
    <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 us</a></li>
          </ul>
        </div>
      </div>
    </nav>
    <h1>Wombat Coffee Roasters</h1>
  </main>

  <aside class="col-sidebar">
    <div class="affix">
      <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 us</a></li>
      </ul>
    </div>
  </aside>
</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


(侧边栏固定在一个位置)java

注意点

1. 由于粘性元素永远不会超出父元素的范围,因此本例中affix不会超出col-sidebar的范围。当滚动页面的时候,col-sidebar会一直正常滚动,可是affix会在滚动到特定位置时停下来。若是继续滚动得足够远,粘性元素还会恢复滚动。这种状况只在父元素的底边到达粘性元素的底边时发生。
2. Safari须要加上浏览器前缀(position: -webkit-sticky)