startViewTransition

小白也能懂的 startViewTransition:一行代码实现丝滑页面过渡

作为前端小白,你是不是也想给页面加个炫酷的过渡动画,却被复杂的 CSS 动画、JS 定时器搞得头大?今天就给大家介绍一个浏览器原生的 "懒人神器"------startViewTransition,一行核心代码就能实现专业级的视图过渡效果,零基础也能上手!

一、startViewTransition 是什么?

简单说,startViewTransition是浏览器自带的视图过渡 API,专门用来处理 "页面内容变化时的过渡动画"(比如点击按钮切换内容、路由跳转、数据刷新)。它把复杂的动画逻辑封装好了,我们只需要告诉它 "什么时候触发过渡""要改什么内容",剩下的交给浏览器就行。

核心特点:

  • 原生 API,不用装任何依赖;
  • 代码极少,新手易上手;
  • 过渡效果丝滑,兼容性(Chrome/Edge 111+、Safari 17+)满足大部分场景。

二、最简案例:点击按钮切换内容

先看效果:点击按钮,盒子从红色变成蓝色,宽度从 100px 变 200px,过程有自然的过渡动画。

1. 完整代码(直接复制就能跑)

预览

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>startViewTransition小白案例</title>
  <style>
    /* 基础样式:给盒子加过渡的基础配置 */
    #box {
      width: 100px;
      height: 100px;
      background: red;
      /* 关键:让样式变化能被过渡捕获(可省略,API会自动处理,但加了更稳) */
      transition: all 0.5s ease;
    }
    button {
      margin-top: 20px;
      padding: 8px 16px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div id="box"></div>
  <button id="btn">点击切换样式</button>

  <script>
    // 1. 获取元素
    const box = document.getElementById('box');
    const btn = document.getElementById('btn');

    // 2. 点击按钮触发过渡
    btn.addEventListener('click', () => {
      // 核心代码:调用startViewTransition
      document.startViewTransition(() => {
        // 这里写你要修改的DOM内容/样式
        box.style.width = '200px';
        box.style.background = 'blue';
      });
    });
  </script>
</body>
</html>

2. 代码解释

  • document.startViewTransition():调用过渡 API,括号里传一个函数
  • 函数内部:写你要修改的 DOM 操作(比如改样式、改文本、删加元素);
  • API 会自动捕获 "修改前的 DOM 状态" 和 "修改后的 DOM 状态",然后生成过渡动画。

运行后点击按钮,你会看到盒子不是 "瞬间变化",而是有 0.5 秒的渐变过渡 ------ 这就是startViewTransition的魔力!

三、进阶一点:路由 / 页面切换场景

实际开发中,我们常需要 "点击导航切换页面内容",用这个 API 也能轻松实现。

案例(模拟路由切换)

预览

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>页面内容切换过渡</title>
  <style>
    .page {
      width: 300px;
      height: 200px;
      display: none; /* 默认隐藏所有页面 */
      padding: 20px;
      box-sizing: border-box;
    }
    .page.active {
      display: block;
    }
    .nav {
      margin-bottom: 10px;
    }
    .nav button {
      margin-right: 10px;
    }
  </style>
</head>
<body>
  <div class="nav">
    <button data-page="page1">页面1</button>
    <button data-page="page2">页面2</button>
  </div>
  <div id="page1" class="page active">我是页面1的内容</div>
  <div id="page2" class="page">我是页面2的内容</div>

  <script>
    // 获取所有导航按钮
    const navBtns = document.querySelectorAll('.nav button');
    // 给每个按钮加点击事件
    navBtns.forEach(btn => {
      btn.addEventListener('click', () => {
        // 要切换的目标页面ID
        const targetPage = btn.dataset.page;
        // 核心:调用过渡API
        document.startViewTransition(() => {
          // 隐藏所有页面
          document.querySelectorAll('.page').forEach(page => {
            page.classList.remove('active');
          });
          // 显示目标页面
          document.getElementById(targetPage).classList.add('active');
        });
      });
    });
  </script>
</body>

这个案例中,点击 "页面 1 / 页面 2",内容切换会有原生的淡入淡出过渡,不用自己写关键帧动画!

主题切换

element-plus 官网的主题切换效果

vue 复制代码
<template>
  <vab-icon
    class="dark"
    :icon="mode === 'dark' ? 'moon' : 'sun'"
    @click="toggleDark"
  />
</template>

<script lang="ts" setup>
defineOptions({
  name: 'ThemeSwitcher',
})
const toggleDark = async (event: MouseEvent) => {
  if (typeof document.startViewTransition === 'function') {
    const x = event.clientX
    const y = event.clientY
    const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y))
    let isDark: boolean
    const transition = document.startViewTransition(() => {
      const root = document.documentElement
      isDark = root.classList.contains('dark')
      root.classList.remove(isDark ? 'dark' : 'light')
      root.classList.add(isDark ? 'light' : 'dark')
    })
    await transition.ready.then(() => {
      const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]
      document.documentElement.animate(
        {
          clipPath: isDark ? [...clipPath].reverse() : clipPath,
        },
        {
          duration: 600,
          fill:'both',
          easing: 'ease-in',
          pseudoElement: isDark ? '::view-transition-old(root)' : '::view-transition-new(root)',
        }
      )
    })
  }
 }
</script>

<style lang="scss">
::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
  animation: none;
}

::view-transition-old(root) {
  z-index: 999;
}

::view-transition-new(root) {
  z-index: 1;
}

.dark {
  &::view-transition-old(root) {
    z-index: 1;
  }

  &::view-transition-new(root) {
    z-index: 999;
  }
}

.dark {
  position: relative;
  margin-left: var(--el-margin);
  cursor: pointer;
  transition: var(--el-transition);
}
</style>

四、常见小配置:fill: 'both'(小白必知)

有时候过渡动画结束后,样式会 "回退",这时候可以加个配置:

javascript

运行

arduino 复制代码
document.startViewTransition(() => {
  // 你的DOM修改逻辑
  box.style.width = '200px';
}, {
  fill: 'both' // 关键:让动画前后都保留最终样式
});

fill: 'both'的通俗理解:

  • 动画开始前:提前应用最终样式(不会有 "延迟空白");
  • 动画结束后:保留最终样式(不会回退到初始状态);
  • 简单说就是 "动画前后都生效",避免样式闪回。

五、注意事项

  1. 兼容性:目前仅现代浏览器支持(Chrome/Edge/Safari 新版),低版本浏览器会 "无过渡但功能正常",不影响使用;
  2. 只能捕获 DOM 变化:函数内部必须是真实的 DOM 修改(比如改样式、增删元素),异步操作要包在里面;
  3. 不要嵌套调用:一个过渡没结束前,不要触发下一个,否则会卡顿。

总结

  1. startViewTransition是浏览器原生 API,专门做视图过渡,不用写复杂动画;
  2. 核心用法:document.startViewTransition(() => { 你的DOM修改逻辑 })
  3. fill: 'both'能解决样式回退问题

这个 API 可以说是前端的 "动画神器",不用懂复杂的 CSS 动画原理,一行核心代码就能实现丝滑过渡,赶紧复制案例试试吧!

相关推荐
负责的蛋挞10 小时前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农12 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_9437823513 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq13 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net
吠品13 小时前
LangChain 里 tool_call_id 为空?一次 MCP 工具集成的排查记录
前端
微信开发api-视频号协议13 小时前
企业微信二次开发中的文件系统设计:媒体资源、临时文件与业务附件
前端·微信·企业微信·媒体·ipad·微信开放平台
柒和远方13 小时前
Phase 7.4 学习博客:为什么多 API 项目需要 Swagger / OpenAPI
前端·后端·架构
张龙68713 小时前
拼多多开放平台对接踩坑实录:从 CLIENT_ID 配置到 MD5 签名算法的完整填坑指南
前端
GuWenyue13 小时前
提示词彻底过时?一套上下文工程方案,3步让LLM落地生产,代码直接复用
前端·javascript·人工智能