粥粥
网页编程

跳转要软,但我没上 PJAX:Noline 的页转场是两层的

阅读 8 约 4 分钟 暂无评论

我对博客跳转的要求就一句话:不接受白屏硬切。但也不想为了这一句话上一套 PJAX——那玩意儿会顺带把前进后退、地址栏、浏览器自己的滚动恢复、评论锚点定位和搜索引擎抓到的链接形态全都搅一遍,为了一个视觉过渡付这个价不值当。

所以 Noline 的页转场是两层的:能走原生就走原生,走不了就退回自己写的那套。

第一层:跨文档视图过渡

主路径是浏览器原生的 cross-document View Transition,也就是 CSS 里那三条 ::view-transition-old/root、::view-transition-new/root、::view-transition-group(root) 的 at-rule。它跟同文档那套不是一回事:跨文档时旧页不是被 JS 换掉的,是浏览器把两份文档的画面接在一起做过渡,所以顶栏(连头像一起)能整块跨页连续——不重建、不重新解码,看起来就是同一块从来没变过。

它有一个硬前提:两份文档必须同源且共享一个浏览器进程,而这要求页面发 Cross-Origin-Opener-Policy: same-origin 把头断开。主题在 themeInit 里自己发这条头,不需要你去 nginx 配。

发不出去(被上游缓存或者服务器配置吃掉)、或者浏览器根本不认这条 at-rule(Firefox 目前只支持同文档那套),就自动退回第二层。整个判断在浏览器里做,服务端不需要知道访问者用什么。

第二层:淡出 + 进度条 + 就绪再揭示

退路那套的逻辑很朴素:点链接 → 当前页淡出、顶部起一条进度条 → 新页文档 ready → 内容揭示。旧页在新页画出来之前原样挂着,所以慢接口、冷缓存的时候你看到的是一条走到一半的进度条,不是一片白。

这一层也没有 PJAX:跳转仍然是浏览器真的去请求一个新文档,地址栏、前进后退、右键新标签打开、滚动位置恢复,全是浏览器自己的行为。

反馈本身也有两层

1.33.0 把「跳转期间该看见什么」拆成了两层,后台「页面转场样式」里三选一,默认两者都要:

顶部细条:3px 粗,品牌渐变打底,上面叠一层 45° 斜纹,靠推进 background-position 让它流动——不是拿 background-size 抖,也不是换颜色。加载完成时先把宽度补到 100%,再淡掉。这条是主题自己的,不是抄的。

全屏遮罩:整屏盖成卡片底色,中间是站点头像轻轻呼吸,没配头像就用名字首字母块。这一张是照着 blog.zhheo.com 那套做的,我逐屏看过它的实现。两个决定是我自己改的:

  • 遮罩只在旧页还挂着这段时间出现,新页一画出来就撤。所以快页面根本不会闪出头像,只有真需要等的页面才给你看。
  • 材质是实底卡片色,不是玻璃。iOS 那套液态玻璃我在别的地方做完又全撤了;判断标准就一条——身后有没有内容穿过。整屏遮罩身后没有内容,那它就该是一块实色,磨砂只是浪费性能。

顶部细条的可见态

全屏遮罩的可见态

三条实现上的硬约束

这三条都是踩过才知道的:

  1. #noline-progress 和 #noline-splash 必须是 .topbar 的兄弟节点,不能塞在顶栏里面。顶栏有 backdrop-filter,它会给自己所有 position: fixed 的后代造一个新的 containing block——进度条放进顶栏里,fixed 就变成相对顶栏定位,宽度跟着顶栏走,怎么调都不对。
  2. 可见态一律由 JS 挂 class,CSS 里默认是隐藏的。这样 main.js 因为任何原因没跑起来,最坏结果是「没有过渡」,而不是「一块遮罩把整站盖住」。
  3. 遮罩自己带一个 4 秒定时器。正常情况下新页就绪那一刻撤掉;万一 reveal() 因为脚本报错没被调用,定时器会自己把遮罩撤了。宁可没有动画,不能让人对着一个盖住全屏的头像不知所措。

另外 prefers-reduced-motion: reduce 的时候遮罩直接 display: none,打印样式里两层都隐藏。CSS 那个 * 重置管不到 ::view-transition-*,所以降动效这件事在 CSS 和 JS 里各写了一遍。

怎么验的

可见态只活几百毫秒,正常截图截不到;而无头 Chrome 那套截图脚本默认带 --force-prefers-reduced-motion,会把它们整个关掉。做法是把静态夹具拷一份,往 </body> 前注一段带 !important 的样式,把 JS 才挂得上的那个状态钉死,再交给 Chrome 出图——上面那两张就是这么来的,不是设计稿。

一句话总结

跳转要软,靠的是「旧页在新页画出来之前不许消失」这一条纪律,不是靠某个库。原生能用就用原生,用不了就自己那两层,两层都不想要就选一个——都摆在后台那个下拉里,选 bar 就只剩一条会流动的细条,选 splash 就只剩那张遮罩。

粥粥

种一棵树,等它长大

转载请注明出处

不知道看什么?

随机去往一篇

评论 0

添加新评论

还没有评论,来抢沙发