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 动画原理,一行核心代码就能实现丝滑过渡,赶紧复制案例试试吧!

相关推荐
写代码的【黑咖啡】2 小时前
Python Web 开发新宠:FastAPI 全面指南
前端·python·fastapi
凉_橙2 小时前
gitlab CICD
前端
wangfpp2 小时前
性能优化,请先停手:为什么我劝你别上来就搞优化?
前端·javascript·面试
踩着两条虫2 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之构建配置与Vite集成
前端·vue.js·ai编程
凉_橙2 小时前
前端项目与node项目部署记录
前端
踩着两条虫2 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十):CLI与工具链之自定义构建插件
前端·vue.js·ai编程
用户26994872593702 小时前
使用命令获取figma节点树JSON文件
前端
三小河2 小时前
JavaScript 稀疏数组:成因、坑点与解决方案
前端
HelloReader2 小时前
创建第一个 Qt Quick 应用从零到窗口弹出(四)
前端