更简单的scrollytelling实现,基于position: sticky

本文介绍了一种利用CSS的position:sticky属性简化Scrollytelling技术的方法,通过该方法可以减少JavaScript的使用,提高网页性能及维护效率。文章详细解释了sticky定位的工作原理,并通过实例展示了如何结合enter-view库实现平滑的滚动效果。

基于position: sticky 以及 enter-view 库,可以实现非常简单的scrollytelling.


Easier scrollytelling with position sticky



We’ve written a lot about scrollytelling here at The Pudding. We’ve covered everything from a library comparison, to responsive best practices, to a deep-dive into Scrollama. But there is always room for improvement. One of the biggest implementation pains with scrollytelling is the sticky graphic pattern, whereby the graphic scrolls into view, becomes “stuck” for a duration of steps, then exits and “unsticks” when the steps conclude.

This post will focus on the easiest solution we’ve come up with yet: offloading the sticky complexity to CSS, using position: sticky.

Why use Sticky?

The short version: when using the sticky graphic pattern, you need a bunch of JavaScript to handle the stuck state, dimensions, etc.. With this approach, that is all done with (minimal) CSS. This means less bugs, less maintenance, and more happiness.

What is Sticky?

Sticky positioning is the unapologetic love child of position: relative and position: fixed (in which said love child grows up to do bigger and better things while still retaining the lessons of its parents). An element with a position: sticky declaration remains static in the document until a certain threshold is reached, and then it becomes fixed once scrolled to that threshold. A threshold is defined by any directional declaration such as: top: 0;, which becomes fixed once the element reaches the top edge of its parent.

A sticky element is always relatively positioned to its parent (much like position: absolute;). This means that these elements will stick and unstick only within the bounds of its parent element, not the viewport (making our job easier); it also means that the thresholds are marked by the edges of the parent. The great thing about this constraint is that you can control the overlap (or lack thereof) of multiple stuck elements.

In Action

And now for the good stuff. The first example here uses the classic side-by-side approach. Scroll on.

Bar is 10%

Bar is 90%

Bar is 50%

The second example uses the text overlay approach. Keep on scrolling!

Bar is 10%

Bar is 90%

Bar is 50%

The sticky graphic is entirely handled by CSS, while the only thing done in JavaScript is handling the step triggers. We chose to use enter-view.js here because it has an incredibly simple interface, super lightweight, and Russell wrote it . However, any trigger library will work, be it Waypoints, Scrollama, or another library.

The Code

Below is the core HTML, CSS and JavaScript that makes this work, excluding the code for aesthetics. You can view the full code for these examples on codepen, or github for the the full article.

<div class='scrolly'>

        <!-- sticky graphic -->
        <figure class='sticky'>
                <!-- chart stuff in here -->
        </figure>

        <!-- step text -->
        <article>
                <div class='step' data-index='0'>
                        <p>Step text</p>
                </div>
                <!-- ...more steps -->
        </article>

</div>
article {
  position: relative;
}
figure.sticky {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
}
enterView({
        selector: stepSel.nodes(),
        offset: 0.5,
        enter: el => {
                const index = +d3.select(el).attr('data-index');
                updateChart(index);
        },
        exit: el => {
                let index = +d3.select(el).attr('data-index');
                index = Math.max(0, index - 1);
                updateChart(index);
        }
});

Wrap Up

You can still implement this behavior in JavaScript, but position: sticky has a few core benefits which give it the upper hand when it comes to development. Scroll listeners in JavaScript aren’t always the best solution: they can inhibit performance and are sometimes quite janky. Depending on the speed of scroll and the device someone is using, the listener might fall out-of-sync and need to catch up with a scroll, causing an element to jump into place instead of displaying a smooth locking behavior. Beyond performance concerns, it’s much simpler to write two lines of CSS than a bunch of JavaScript.

But is it well-supported? Yes it is! Apart from a few minor bugs with thead and tr elements, it’s good-to-go across the latest versions of all major browsers. IE doesn’t support this feature (ugh, of course...), but there are a few polyfills and companions out there with loose support for certain directional thresholds. If polyfills aren’t your jam or the ones available just aren’t cutting it, you can always… do nothing! The beauty of position: sticky is that it has built-in graceful degradation; if a browser doesn’t support it, the element will stay static in the source order it was added. And if you want to get extra fancy, you can use a feature query @supports (position: sticky) and implement a fallback layout. 

实现浏览器对 `position: sticky` 的兼容,以下是一个示例代码,该示例考虑了不同浏览器的特性和需求: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> /* 为需要兼容的浏览器添加私有前缀 */ .sticky-element { position: -webkit-sticky; /* 兼容webkit内核浏览器,如旧版Safari */ position: sticky; top: 20px; /* 当元素距离视口顶部 20px 时触发固定 */ background-color: lightblue; padding: 10px; z-index: 1; } /* 父容器样式 */ .parent-container { height: 400px; /* 设置高度 */ overflow-y: auto; /* 允许滚动 */ border: 1px solid #ccc; padding: 20px; } </style> </head> <body> <div class="parent-container"> <div class="sticky-element"> 这是一个使用 position: sticky 的粘性元素 </div> <p>这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。</p> <p>这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。</p> <p>这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。这里是一些占位文本。</p> </div> </body> </html> ``` ### 代码解释 1. **私有前缀**:为 `position: sticky` 添加了 `-webkit-` 私有前缀,以兼容使用 webkit 内核的浏览器,如旧版 Safari [^3]。 2. **触发阈值**:使用 `top: 20px` 定义了元素触发固定的阈值,即当元素距离视口顶部 20px 时,元素将固定在该位置 [^2]。 3. **父容器样式**:设置了父容器的高度和 `overflow-y: auto`,允许容器内部内容滚动 [^4]。 ### 兼容性说明 - IOS 家族(SAFARI && IOS SAFARI)和 Firefox 较早开始就支持 `position: sticky`。 - Chrome 53 - 55 需要启用实验性网络平台功能。添加 `-webkit-` 前缀可以兼容使用 webkit 内核的浏览器 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值