文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

纯CSS实现电梯导航!

2024-11-29 19:08

关注

我们经常会在博客、文档中看到类似这样的侧边导航目录,例如:

这种导航也被称为“电梯导航”(当然可能还有其他叫法,知道是这个交互就行)。它会随着内容的滚动而自动切换当前选中态,点击任意目录也会自动滚动到对应,就像这样。

通常要实现这样一个交互肯定少不了JS,常规的做法是监听滚动事件,也可以用IntersectionObserver监听元素的滚动位置状态,下面有一篇关于用IntersectionObserver的实现。

尝试使用JS IntersectionObserver让和导航联动:https://www.zhangxinxu.com/wordpress/2020/12/js-intersectionobserver-nav 。

大家可能也发现了,这个交互最大的特点就是滚动,是不是也可以联想到 CSS滚动驱动动画呢?经过一番尝试,发现纯 CSS也能完美实现,而且实现更加简单(不到10行),下面是我复刻的效果。

是不是非常神奇?CSS 还能实现这样的效果?一起看看吧!

一、CSS 滚动锚定

这个导航主要有两个交互:

第一条比较容易,我们可以直接用a标签的能力实现锚定跳转。假设HTML结构如下:



一、一

二、二

三、三

四、四

五、五

六、六

然后简单修饰一下。

body{
  padding: 0 15px;
}
h2{
  margin: 0;
  padding: .8em 0;
  scroll-margin: 20px;
}
nav{
  position: fixed;
  top: 15px;
  right: 15px;
  background: #fff;
  padding: 10px 0;
  border-radius: 4px;
  overflow: hidden;
}
nav>a{
  position: relative;
  display: block;
  line-height: 2;
  padding: 0 15px;
  font-size: 14px;
  color: #191919;
  text-decoration: none;
}
nav>a:hover{
  background-color: #d5d5d54a;
}
section{
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
section span{
  width: 30%;
  height: 100px;
  border-radius: 4px;
  background-color: #E4CCFF;
}

效果如下:

然后我们只需要给a标签添加href属性,页面相对应的地方指定相同的id,就像这样。


一、一

...

二、二

...

这样点击a标签会自动锚点到对应位置,效果如下:

这样就能跳转了,如果你觉得有点生硬,可以加入滚动动画。

body{
  
  scroll-behavior: smooth;
}

这样就平滑多了。

这样就实现了滚动锚定效果,还算比较容易。

下面来看如何实现滚动联动效果。

二、CSS 滚动驱动动画

我们可以想一下,如果是IntersectionObserver该如何做呢?没错,就是监听每一块区域的出现时机,然后改变导航的状态。

刚好CSS滚动驱动动画中的view-timeline可以实现类似的效果。它可以「监测到元素在可视区」的情况。

不过,单独依靠view-timeline还不行,因为默认情况下,CSS 滚动驱动作用范围只能影响到子元素,而我们的dom结构明显是分离的。



一、一

...

二、二

...

为了解决这个问题,我们需要用到 CSS 时间线范围,也就是 timeline-scope。

https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope

这里简单介绍一下,假设有这样一个结构。

这是两个元素,右边的是滚动容器,左边的是一个可以旋转的矩形。

我们想实现滚动右边区域时,左边矩形跟着旋转,如何实现呢?

可以给他们共同的父级,比如body定义一个timeline-scope。

body{
  timeline-scope: --myScroller;
}

然后,滚动容器的滚动和矩形的动画就可以通过这个变量关联起来了。

.scroller {
  overflow: scroll;
  scroll-timeline-name: --myScroller;
  background: deeppink;
}
.animation {
  animation: rotate-appear;
  animation-timeline: --myScroller;
}

效果如下:

这样就实现任意元素间的滚动联动。

回到这里,我们要做的事情其实很简单,给父级(body)定义多个timeline-scope,然后给内容区域和导航区域都绑定一个相同CSS变量,具体做法如下:


  
  
  

一、一

...

二、二

...

三、三

...

四、四

...

五、五

...

六、六

...

然后给内容区域添加view-timeline-name,导航标签添加 animation-timeline,让这两者关联起来,也就是内容滚动时,导航的动画跟着执行,这里的动画很简单,就是改变导航链接的文字颜色和边框颜色,关键实现如下:

.content{
  view-timeline-name: var(--s);
}
nav>a{
  
  animation: active;
  animation-timeline: var(--s);
}
@keyframes active {
  0%,100% {
    color: #6f00ff;
    border-color: #6f00ff;
  }
}

效果如下:

这样滚动联动效果基本就出来了,不过还是有些小问题,接着优化。

三、CSS 滚动视区范围

前面的实现其实还个小问题,右边的导航会同时选中多个。

很明显是因为左侧的内容同时出现了这两部分区域。

如果每一块内容高度更少,那同时选中的就更多了,就像这样。

而我们需要的肯定是同一时刻只选中一个导航,你可以自己定义规则,比如后面的优先于前面的。

那CSS该如何实现这样的效果呢?

其实,这里需要换一种思维,上面的实现之所以会同时出现多个选中,是因为视区范围太大,是整个屏幕,所以可以同时匹配到多个内容区域。

因此,我们可以手动的减少视区范围,一直减少成一条线,这样无论怎样滚动,都只会匹配一个区域。

在这里,我们可以通过view-timeline-inset来手动改变视区范围,默认是0。

比如我们希望以滚动区域中间为分割线,只要滚动到达这个点,就高亮当前导航,可以这样实现。

.content{
  view-timeline-name: var(--s);
  view-timeline-inset: 50%; 
}

为了方便演示,我在滚动区域中间加了一条红色的线,便于观察。

可以很清楚的发现,只要越过这条线,导航马上触发高亮选中。

当然你也可以自己调整这个临界线,比如下面的表示在距离滚动区域底部30%的地方做判断。

.content{
  view-timeline-name: var(--s);
  view-timeline-inset: 70% 30%; 
}

这样就实现了我们想要的效果了,你也可以访问以下在线链接查看实际效果(chrome 116+)。

四、兼容性和总结

看似这么多,其实核心代码就这几行。

body{
  timeline-scope: --t1,--t2,--t3,--t4,--t5,--t6;
}
.content{
  view-timeline-name: var(--s);
  view-timeline-inset: 50%;
}
nav>a{
  animation: active;
  animation-timeline: var(--s);
}
@keyframes active {
  0%,100% {
    color: #6f00ff;
    border-color: #6f00ff;
  }
}

包括在HTML中的几行自定义变量,是不是还不到 10 行?相比 JS实现,代码更简单,性能也更好,无需初始化,也不用等待 dom 加载,扩展性也强。

唯一的缺点可能是兼容性不足,由于依赖timeline-scope,所以必须Chrome 116+,完整兼容性如下:

下面总结一下

总的来说,CSS滚动驱动动画不愧是2023年度最强特性,可以做的事情太多了,很多 JS才能实现的交互都可以取代了,而且做的更好,至于兼容性,还是留给时间吧。

[1]CSS 电梯导航 (codepen.io): https://codepen.io/xboxyan/pen/zYVBEWq。

[2]CSS 电梯导航 (juejin.cn): https://code.juejin.cn/pen/7396195867155562508。

来源:前端侦探内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯