精通 CSS 之 position: sticky

482 阅读2分钟

写前端的你,肯定用过 position: absoluteposition: relative,但是你八成概率没有用过 position: sticky,这是一个跟滚动相关的布局,当靠近可滚动区域边界的时候,可使得设置 stick 的元素粘在那里,有点类似于 position: fixed 的效果,所以叫做粘滞定位

我给大家直接看下效果就明白了:

这种炫酷的效果,如果不是亲眼所见,还真不知道如何实现!其实代码非常容易,首先 HTML 结构很清晰:

<div class="app">
  <h1>Animals by Alphabet</h1>
  <div class="container">
    <div class="heading">A</div>
    <div>Aardvark</div>
    <div>Alligator</div>
    <div>Antelope</div>
    <div class="heading">B</div>
    <div>Baboon</div>
    <div>Bat</div>
    <div>Blue Bird</div>
    <div class="heading">C</div>
    <div>Cat</div>
    <div>Camel</div>
    <div>Chicken</div>
    <div>Chipmunk</div>
    <div class="heading">D</div>
    <div>Dog</div>
    <div>Donkey</div>
    <div>Dave</div>
    <div>Duck</div>
  </div>
</div>

其次 CSS 代码也很简单:

.app {
  overflow: auto;
  height: 250px;
  border: 5px solid black;
}

.heading {
  background: #ccc;
  height: 50px;
  line-height: 50px;
  margin-top: 10px;
  font-size: 30px;
  padding-left: 10px;
  position: sticky;
  top: 0px;
}

上面展示的是垂直方向的效果,其实水平方向也是可以的,例如:

HTML 结构:

<sidescroller>
  <div class="item">
    <div class="description"><span>Clear Beach</span></div>
    <img src="https://gedd.ski/img/sticky/beach.jpg">
  </div>
  <div class="item">
    <div class="description"><span>Gummy Bears Yay!</span></div>
    <img src="https://gedd.ski/img/sticky/gummy.jpg">
  </div>
  <div class="item">
    <div class="description"><span>Kids</span></div>
    <img src="https://gedd.ski/img/sticky/kids.jpg">
  </div>
  <div class="item">
    <div class="description"><span>Wolf Pup</span></div>
    <img src="https://gedd.ski/img/sticky/pup.jpg">
  </div>
  <div class="item">
    <div class="description"><span>Old Dude</span></div>
    <img src="https://gedd.ski/img/sticky/oldman.jpg">
  </div>
</sidescroller>

CSS 样式:

sidescroller {
  display: flex;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  background: #000;
}

.item {
  display: flex;
}

.description {
  max-width: 40px;
  height: 300px;
  position: sticky;
  left: 0;
}

.description span {
  display: inline-block;
  background: rgba(0, 0, 0, .5);
  width: 300px;
  height: 40px;
  transform: rotate(-90deg) translateX(-300px);
  transform-origin: left top 0;
  padding-top: 11px;
  text-align: center;
  text-transform: uppercase;
  color: #fff;
  font-size: 14px;
}

img {
  max-height: 300px;
}

观察仔细的小伙伴可能发现了细微的区别:

在垂直滚动的示例中,下面的元素覆盖上面的元素。在水平滚动的示例中,右边的元素并没有覆盖左边的元素,而是将其推离。

把细节稍微放大一下,大家仔细看:

造成这种的区别的原因就是,如果设置 sticky 的 DOM 元素是同级关系(sibling),那么就会覆盖。如果是非同级关系,而是嵌套在另外一个元素当中,则会被推出。