纯CSS技术实现Scroll Indicator滚动指示器效果

目录
文章目录隐藏
  1. JavaScript 实现
  2. 我想到的更好的实现
  3. 原理说明
  4. 网友的方法也不错
  5. 结束语

最近在读阮一峰老师的的《ECMAScript 6 入门》,发现每个章节的页面顶部都有一个类似进度条的东西,这是个什么东东,好奇心强的我上网查了一下,这个东西叫 Scroll Indicator。

Scroll Indicator:滚动指示器。是 Web 中常见的一种效果。用户滚动垂直滚动内容时,页面顶部有一个类似进度条的效果,当内容滚动到页面最低端,进度条效果填满整个进度条。通俗来说,就是当前可视区域距离页面顶部的占比,感觉描述得有点绕,还是录制一个动效图,用图来说明这种效果,毕竟一图胜过千言万语:

纯 CSS 技术实现 Scroll Indicator 滚动指示器效果

JavaScript 实现

在还没有捞源码之前,自己先大致想了一下实现思路:

  • 页面加载完成之后,获取到页面文档高度(DH)、当前可视区域高度(VH)、可视区域距离页面顶部的高度 scrollTop(TH);
  • (DH-VH)就是需要滚动的值;
  • 监听页面 scroll 事件,(TH/(DH-VH))*100%,便是当前的占比;
  • 当然,需要考虑节流、防抖。推荐阅读《第 6 题:什么是防抖和节流 有什么区别 如何实现

HTML 代码:

<body>
  <div class="scroll-indicator j-scroll-indicator"></div>
</body>

css 代码:

body {
  margin: 0;
  paddingL 0;
  height: 5000px;
}

.scroll-indicator {
  position: fixed;
  height: 8px;
  top: 0;
  left: 0;
  background: #369;
}

核心代码:

(function() {
      var dh = $(document).height();
      var vh = $(window).height();
      var sHeight = dh - vh;
      $(window).scroll(function () {  
        var perc = $(window).scrollTop() / (dh - vh);
        $('.j-scroll-indicator').css({width: perc * 100 + '%'});
  });  
}());

效果如下:

纯 CSS 技术实现 Scroll Indicator 滚动指示器效果

然后去捞了一下阮老师 es6 官网的源码:

(function() {
      var $w = $(window);
      var $prog2 = $('.progress-indicator-2');
      var wh = $w.height();
      var h = $('body').height();
      var sHeight = h - wh;
      $w.on('scroll', function() {
        window.requestAnimationFrame(function(){
          var perc = Math.max(0, Math.min(1, $w.scrollTop() / sHeight));
          updateProgress(perc);
        });
      });

      function updateProgress(perc) {
        $prog2.css({width: perc * 100 + '%'});
        ditto.save_progress && store.set('page-progress', perc);
      }

    }());

不出所料,做法是一样的。

然后,就开始瞎琢磨,之前用 css 搞过瀑布流,那可以用 css 搞滚动指示器吗?

答案当然是可以的。

css 搞滚动指示器

我想到的更好的实现

我想到的这个技术实现区别就在于对角线性渐变不是写在 body 标签上的,而是一个普通的 div 元素上。

具体操作如下:

1、在标签内插入指示器元素:

<div class="indicator"></div>

2、粘贴如下所示的 CSS 代码:

body {
    position: relative;
}
.indicator {
    position: absolute;
    top: 0; right: 0; left: 0; bottom: 0;
    background: linear-gradient(to right top, teal 50%, transparent 50%) no-repeat;
    background-size: 100% calc(100% - 100vh);
    z-index: 1;
    pointer-events: none;
    mix-blend-mode: darken;
}
.indicator::after {
    content: '';
    position: fixed;
    top: 5px; bottom: 0; right: 0; left: 0;
    background: #fff;
    z-index: 1;
}

一个更好的 CSS 滚动指示器效果就实现了

原理说明

传统 CSS 滚动指示器为了防止对角渐变(也就是滚动进度条)的覆盖页面上的元素内容,因此写在了最底层的 body 元素上,这就导致如果 body 元素内的普通元素内容有背景色,或者背景图之类的,就会覆盖进度条,产生致命缺陷。

我的优化方法是把对角渐变(也就是滚动进度条)连同里面的白色覆盖层写在了普通元素的上面,这样避开被覆盖的致命缺陷。但是这样实现带来另外一个问题,页面的内容都被白色图层覆盖了,那页面内容岂不是都看不见了?不要担心,有 CSS 声明可以让白色的图层变成透明,那就是 mix-blend-mode:darken,也就是 darken 混合模式。darken 混合模式的混合方式很好理解,两个颜色进行混合,哪个颜色深就使用哪个颜色?

要知道所有的颜色里面最浅的就是白色,于是我们只要把我们的白色覆盖层的混合模式设置为 darken,那必然最终呈现出来的颜色一定是覆盖层下面元素内容的颜色,换句话说我们的白色透明覆盖层变透明了。

CSS 滚动指示器
CSS 滚动指示器要想效果良好,需要注意两点:

  1. 进度条的颜色尽量取深色,因为本身包含 darken 混合模式,如果颜色过浅,很容易被底部的内容颜色给混合。
  2. CSS 滚动指示器需要在页面滚动高度超过一屏的时候才出现。原因有两方面:一是如果滚动高度过小,没有必要使用滚动指示器;二是滚动指示器本质上是一个渐变,如果滚动高度不足,则进度条的边缘会过于倾斜而导致显示效果不完美。

CSS 滚动指示器

网友的方法也不错

使用 CSS 来实现滚动指示器,难点在于:如何实时去获取当前可视区域在文档流中的位置。

上述问题,如何去考虑呢?我们从分解滚动指示器的动作中来找答案:

  • 黑色表色进度条
  • 红色表示文档高度
  • 绿、蓝、橙表示视窗滚动

CSS 来实现滚动指示器

也就是说:(TH/(DH-VH))公式中的 TH 可以不用知道,只需要 DH-VH 的高度,即直角三角形的高度便 OK。

现在问题转化为:如何求出 VH,这时候该 vh 这个长度单位登场了,vh 是基于视窗单位的排版计量。vh 可以获取当前视窗的高度。嗯,现在看来,应该是可以一写了。

HTML 代码:

<body>
    <div class="main">
        <h1>滚动鼠标</h1>
    </div>
</body>

CSS 代码:

.main {
   margin: 0;
   padding: 0;
   display: block;
   height: 30000px;
   text-align: center;
   line-height: 100px;
}

body {
   margin: 0;
   padding: 0;
   background: linear-gradient(to right top, #369 50%, #fff 50%);
   background-size: 100% calc(100% - 99vh);
}

body:before {
   content: '';
   position: fixed;
   top: 4px;
   bottom: 0;
   width: 100%;
   z-index: -1;
   background: #fff;
}

大致实现是没有问题的,但是有下面几个缺点:

  • 文档内容太少(高度太小)的话,进度条呈箭头形,不美观(可考虑加毛玻璃效果来弱化)
  • background-size:100%calc(100%-99vh);中的 99vh 是相对值,若是视窗高度比较小,进度条会填不满进度条槽(可考虑加 min-height 来弱化)

纯 CSS 实现 Scroll Indicator(滚动指示器)

结束语

其实这只是非常牛逼的渐变非常小的一个技巧,更多精彩 CSS 技术文章敬请关注码云笔记,持续更细。

好了,本文到此结束,希望对你有帮助,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » 纯CSS技术实现Scroll Indicator滚动指示器效果

发表回复