CSS View Transitions API跨页面过渡动画实现与降级方案

View Transitions API核心原理

CSS View Transitions API是浏览器原生提供的页面过渡动画方案,开发者无需手动计算元素位置和尺寸,浏览器自动捕获新旧页面状态并生成过渡动画。该API在文档层面工作,通过startViewTransition()方法触发,浏览器在调用瞬间截取当前DOM快照(旧状态),执行回调更新DOM后再次截取快照(新状态),然后对两个快照执行可配置的过渡动画。

View Transitions API最大的优势在于自动处理元素形态差异——位置、尺寸、圆角、透明度等属性变化均由浏览器补间动画完成,开发者只需标记哪些元素参与过渡,无需手动编写动画关键帧。

同文档内视图过渡的基本用法

同文档SPA导航的过渡实现非常简洁:

document.startViewTransition(async () => {  // 更新DOM到新状态  await updateContent(newPage);});

浏览器自动执行以下流程:截图当前状态 -> 执行回调更新DOM -> 截图新状态 -> 执行过渡动画。默认过渡效果是300ms的淡入淡出。

自定义过渡样式通过::view-transition-old和::view-transition-new伪元素控制:

::view-transition-old(root) {  animation: 300ms ease-out fade-out;}::view-transition-new(root) {  animation: 300ms ease-in fade-in;}@keyframes fade-out {  to { opacity: 0; }}@keyframes fade-in {  from { opacity: 0; }}

元素级共享过渡动画配置

共享过渡(Shared Element Transition)是View Transitions API最强大的特性,允许指定新旧页面中的对应元素执行变形动画而非简单的淡入淡出。通过view-transition-name属性为元素分配唯一标识:

.hero-image {  view-transition-name: hero;}::view-transition-old(hero) {  animation: 400ms ease-in-out both clip-old;}::view-transition-new(hero) {  animation: 400ms ease-in-out both clip-new;}

浏览器自动匹配新旧状态中view-transition-name相同的元素,生成从旧位置/尺寸到新位置/尺寸的补间动画。这在列表页到详情页的图片过渡、卡片展开动画等场景中效果极佳。

动态分配transition-name需要用JavaScript设置:

function switchPage(itemId) {  const item = document.querySelector(    `[data-id="${itemId}"]`  );  item.style.viewTransitionName = 'active-item';    document.startViewTransition(() => {    item.style.viewTransitionName = '';    updateContent(itemId);  });}

跨文档视图过渡(MPA场景)

跨文档视图过渡适用于多页面应用(MPA),浏览器在页面导航时自动捕获旧页面快照并在新页面中执行过渡。启用方式通过HTTP响应头或meta标签:

<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin"><meta name="view-transition" content="same-origin">

跨文档过渡的CSS同样使用::view-transition伪元素控制。浏览器在导航时自动执行截图和过渡,无需JavaScript参与。

降级方案与浏览器兼容性处理

View Transitions API目前Chrome 111+和Edge 111+已支持,Firefox和Safari尚未完全实现。生产环境必须做好降级:

function navigateWithTransition(updateCallback) {  if (!document.startViewTransition) {    // 浏览器不支持,直接更新DOM    updateCallback();    return;  }  document.startViewTransition(updateCallback);}

在CSS中也应使用@supports做样式降级:

/* 不支持View Transitions时使用普通过渡 */.page-enter {  opacity: 0;  transition: opacity 300ms ease;}@supports (view-transition-name: none) {  .page-enter {    opacity: 1;    transition: none;  }}

性能注意事项:参与过渡的DOM元素越少越好,大型列表或复杂布局的全局过渡可能导致帧率下降。view-transition-name应只分配给需要动画的关键元素,而非所有元素。过渡动画时长建议200ms~500ms,过短看不清效果,过长影响操作响应。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/cssviewtransitionsapi-kua-ye-mian-guo-du-dong-hua-shi-xian/

(0)
小编小编
上一篇 4小时前
下一篇 4小时前

相关推荐

CSS View Transitions API跨页面过渡动画实现与降级方案

View Transitions API如何改变页面过渡体验

单页应用(SPA)流行的一个重要原因是页面过渡动画的实现成本低——内容切换在同一个DOM上下文中完成。而多页应用(MPA)的页面跳转一直伴随着白屏闪烁问题。View Transitions API的出现,让MPA也能实现流畅的页面过渡动画,且无需JavaScript框架介入。Chrome 111+已支持该API,Firefox和Safari的兼容性也在快速推进。

SPA场景下的View Transitions

在SPA中使用View Transitions API非常简单,核心是一个document.startViewTransition()调用:

// SPA路由切换时触发过渡动画
async function navigateTo(url) {
  if (!document.startViewTransition) {
    updateDOM(url);
    return;
  }
  const transition = document.startViewTransition(async () => {
    await updateDOM(url);
  });
  await transition.ready;
  await transition.finished;
}

API的执行流程:1. 浏览器捕获当前页面快照(old state);2. 执行回调函数更新DOM;3. 浏览器捕获新页面快照(new state);4. 在新旧快照之间执行过渡动画。默认动画是300ms的交叉淡入淡出。

MPA跨页面过渡动画实现

MPA的View Transitions需要浏览器原生支持跨文档过渡。从Chrome 126开始支持@view-transition规则:

/* 在两个页面中都要声明 */
@view-transition {
  navigation: auto;
}

/* 自定义过渡动画时长 */
::view-transition-old(root) {
  animation: 200ms ease-out fade-out;
}
::view-transition-new(root) {
  animation: 200ms ease-in fade-in;
}

@keyframes fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

这段CSS在导航发生时自动触发过渡动画,无需任何JavaScript。navigation: auto表示浏览器在检测到同源页面导航时自动启动View Transition。

共享元素过渡动画

View Transitions API最强大的特性是共享元素过渡(Shared Element Transition)。当两个页面有相同语义的元素(如产品图片、标题),可以让该元素从旧位置平滑过渡到新位置,实现类似Flutter Hero动画的效果。

/* 列表页的产品卡片图片 */
.product-card img {
  view-transition-name: product-image-123;
}

/* 详情页的产品主图 */
.product-hero img {
  view-transition-name: product-image-123;
}

/* 过渡动画配置 */
::view-transition-old(product-image-123) {
  animation: 300ms ease-in-out both fade-out;
}
::view-transition-new(product-image-123) {
  animation: 300ms ease-in-out both fade-in;
}

::view-transition-group(product-image-123) {
  animation-duration: 300ms;
}

关键点:两个页面中view-transition-name相同的元素会自动配对,浏览器在它们之间计算位置和尺寸差异,生成平滑过渡动画。view-transition-name必须在整个页面中唯一,动态列表场景下需要用ID后缀保证唯一性。

React与Vue中的集成方案

React集成:

import { useTransition } from 'react';

function useViewTransition() {
  const [isPending, startTransition] = useTransition();
  const transitionTo = (updateFn) => {
    if (!document.startViewTransition) {
      startTransition(updateFn);
      return;
    }
    document.startViewTransition(() => {
      startTransition(updateFn);
    });
  };
  return { transitionTo, isPending };
}

// 使用
function ProductList() {
  const { transitionTo, isPending } = useViewTransition();
  const [selectedId, setSelectedId] = useState(null);
  const handleSelect = (id) => {
    transitionTo(() => setSelectedId(id));
  };
}

Vue 3集成:

// vue-router集成
const router = useRouter();

router.afterEach(async () => {
  if (!document.startViewTransition) return;
  await nextTick();
});

router.beforeEach(async (to, from) => {
  if (document.startViewTransition) {
    return new Promise((resolve) => {
      document.startViewTransition(async () => {
        resolve();
        await nextTick();
      });
    });
  }
});

浏览器兼容与降级方案

View Transitions API的浏览器支持情况:Chrome 111+、Edge 111+支持SPA模式;Chrome 126+、Edge 126+支持MPA跨文档模式;Firefox和Safari目前不支持(截至2026年中)。

降级方案采用渐进增强策略:

/* 基础样式:所有浏览器 */
.page-enter {
  opacity: 0;
}

/* 支持View Transitions的浏览器 */
@supports (view-transition-name: none) {
  .page-enter {
    opacity: 1;
  }
}

/* 不支持时的CSS动画降级 */
@supports not (view-transition-name: none) {
  .page-enter {
    animation: simple-fade-in 200ms ease-out;
  }
}

JavaScript端通过document.startViewTransition的存在性检测做功能降级。不支持时直接更新DOM,用户看到的是即时切换而非过渡动画,功能不受影响。

性能注意事项

View Transitions API内部使用captureStream()对页面进行截图,这个操作有性能开销。避免在过渡期间更新大量DOM节点(如长列表全量重渲染),否则截图和对比都会变慢。对于列表页到详情页的过渡,建议只对关键共享元素设置view-transition-name,其他元素走默认的root过渡即可。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/cssviewtransitionsapi-kua-ye-mian-guo-du-dong-hua-shi-xian/

(0)
小编小编
上一篇 5小时前
下一篇 5小时前

相关推荐