TL;DR: The View Transitions API brings buttery-smooth page transitions directly to the browser - no framework, no JavaScript library needed. Just CSS and a few lines of JS. Here's how it works and why you should start using it today.

🤔 What Are View Transitions Anyway?

You know the feeling. You click a link and - bam - the page jumps. No transition, no fading, just a hard cut. Feels like 2005. Native apps do this better: screens glide into each other, images morph from one view to the next.

That's exactly the problem the View Transitions API solves. It gives you the ability to create animated transitions between different states of your page - natively in the browser. No Angular, no React, no Framer Motion. Just the platform.

MDN: View Transitions API - Web APIs

😩 The Problem: Page Navigation Feels Broken

Let's be honest: Multi-Page Applications (MPAs) always feel a bit... janky compared to native apps. Every page change is a complete rebuild. The browser loads HTML, parses CSS, re-renders everything. The result? A white flash, a jump, a break in the flow.

Single-Page Applications (SPAs) solved this with client-side routing - but at a high cost: JavaScript bundles, framework dependencies, complexity. The View Transitions API offers a middle ground.

🚀 Same-Document Transitions with document.startViewTransition()

The easiest entry point: transitions within a single page. Think tabs or an image gallery. Instead of just swapping content, you can animate the change.

function switchTab(newContent) {
  // Check if the API is available
  if (!document.startViewTransition) {
    updateDOM(newContent);
    return;
  }

  // Start a view transition
  document.startViewTransition(() => {
    updateDOM(newContent);
  });
}

function updateDOM(content) {
  document.querySelector('.tab-content').textContent = content;
}

That's it. Seriously. The browser now automatically creates a crossfade between the old and new state. You don't have to do anything else. The browser takes snapshots of both states and animates between them.

🌍 Cross-Document Transitions with @view-transition

Now it gets really exciting. Since Chrome 126, you can animate transitions between different pages - without any JavaScript! All you need is a CSS rule:

@view-transition {
  navigation: auto;
}

Yes, that's all. Add this to your stylesheet and every page navigation within the same origin gets an automatic smooth crossfade. Not a single line of JavaScript required.

Important: Both pages (the old and new one) need this rule in their CSS. Best practice is to put it in your global stylesheet.

🎯 view-transition-name: Target Specific Elements

The real wow effect comes when you link individual elements across pages. Imagine a product list: you click on a thumbnail and it morphs into the large image on the detail page.

/* On the list page */
.product-card img {
  view-transition-name: product-hero;
}

/* On the detail page */
.product-detail img {
  view-transition-name: product-hero;
}

Same name = the browser knows these elements belong together. It automatically calculates position, size, and animates between them. The result looks like a native app.

Important: Each view-transition-name must be unique on a page. Two elements with the same name on the same page? That breaks the transition.

🎨 ::view-transition Pseudo-Elements for Custom Animations

During a transition, the browser generates a pseudo-element tree that you can style with CSS:

/* Customize the entire transition */
::view-transition-old(root) {
  animation-duration: 0.3s;
}

::view-transition-new(root) {
  animation-duration: 0.3s;
}

/* Animate specific elements differently */
::view-transition-old(product-hero) {
  animation: slide-out 0.4s ease-in;
}

::view-transition-new(product-hero) {
  animation: slide-in 0.4s ease-out;
}

The pseudo-elements are:

  • ::view-transition - the root container
  • ::view-transition-group(name) - groups old and new snapshots
  • ::view-transition-image-pair(name) - contains old and new views
  • ::view-transition-old(name) - snapshot of the old state
  • ::view-transition-new(name) - snapshot of the new state

Here's a complete example for an image gallery with smooth transitions:

/* Basic setup */
@view-transition {
  navigation: auto;
}

/* Thumbnail on the overview page */
.gallery-grid img {
  view-transition-name: var(--transition-name);
  object-fit: cover;
  border-radius: 8px;
}

/* Large image on the detail page */
.gallery-detail img {
  view-transition-name: var(--transition-name);
  width: 100%;
  max-height: 80vh;
  object-fit: contain;
}
// Dynamically assign unique names
document.querySelectorAll('.gallery-grid img').forEach((img, i) => {
  img.style.setProperty('--transition-name', `gallery-img-${i}`);
});

Each image gets its own transition name. When you click on an image, it seamlessly morphs into the detail view.

Mutation Observer: The invisible force in the background of your website 🕵️

🔀 Tab Switching with View Transitions

View Transitions also make sense within a single page. Here's a tab example:

const tabs = document.querySelectorAll('.tab-button');
const content = document.querySelector('.tab-content');

tabs.forEach(tab => {
  tab.addEventListener('click', async () => {
    const newContent = await fetchTabContent(tab.dataset.tab);

    if (!document.startViewTransition) {
      content.textContent = newContent;
      return;
    }

    const transition = document.startViewTransition(() => {
      content.textContent = newContent;
    });

    // Optional: wait for the transition to finish
    await transition.finished;
    console.log('Transition complete!');
  });
});
.tab-content {
  view-transition-name: tab-panel;
}

::view-transition-old(tab-panel) {
  animation: fade-and-slide-out 0.25s ease-in;
}

::view-transition-new(tab-panel) {
  animation: fade-and-slide-in 0.25s ease-out;
}

@keyframes fade-and-slide-out {
  to {
    opacity: 0;
    transform: translateX(-20px);
  }
}

@keyframes fade-and-slide-in {
  from {
    opacity: 0;
    transform: translateX(20px);
  }
}

✨ Custom Effects with @keyframes

You can completely replace the default crossfade animation. How about a slide effect for page navigation?

/* Slide transition for page changes */
@keyframes slide-to-left {
  to {
    transform: translateX(-100%);
  }
}

@keyframes slide-from-right {
  from {
    transform: translateX(100%);
  }
}

::view-transition-old(root) {
  animation: slide-to-left 0.4s ease-in-out;
}

::view-transition-new(root) {
  animation: slide-from-right 0.4s ease-in-out;
}

/* Or a cool scale effect */
@keyframes scale-down {
  to {
    transform: scale(0.9);
    opacity: 0;
  }
}

@keyframes scale-up {
  from {
    transform: scale(1.1);
    opacity: 0;
  }
}

::view-transition-old(root) {
  animation: scale-down 0.3s ease-in;
}

::view-transition-new(root) {
  animation: scale-up 0.3s ease-out;
}

You can even respect prefers-reduced-motion:

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0.01s;
  }
}
Chrome Developers: View Transitions API

🛡️ Progressive Enhancement: Feature Detection

View Transitions are the perfect example of progressive enhancement. Browsers that don't support it? They just get the normal page change - no errors, no fallback code needed.

// JavaScript Feature Detection
if (document.startViewTransition) {
  // Use View Transitions
  document.startViewTransition(() => updateContent());
} else {
  // Fallback: just update
  updateContent();
}

// Or as a utility function
function withTransition(callback) {
  if (!document.startViewTransition) {
    callback();
    return Promise.resolve();
  }
  return document.startViewTransition(callback).finished;
}
/* CSS Feature Detection */
@supports (view-transition-name: test) {
  .animated-element {
    view-transition-name: my-element;
  }
}

That's the beauty of it: there's no breaking change. Either the browser supports it - and it looks great. Or it doesn't - and everything works as before.

🌐 Browser Support

Here's the current status (March 2026):

BrowserSame-DocumentCross-Document
Chrome / EdgeFrom 111From 126
SafariFrom 18From 18
FirefoxFrom 133From 133 (behind flag)
OperaFrom 97From 112

Same-document transitions are now supported by all modern browsers. Cross-document transitions are stable in Chrome/Edge and Safari, with Firefox catching up.

⚔️ View Transitions vs. Framework Solutions

How do View Transitions stack up against framework animations?

CriteriaView Transitions APIFramework Solutions
Bundle Size0 KB (native)5-50 KB (Framer Motion, Angular Animations)
SetupMinimal (CSS + little JS)Framework-specific, often complex
Cross-PageNatively supportedOnly within the SPA
PerformanceBrowser-optimized, compositor threadJavaScript-based, main thread
Learning CurveLow (CSS + simple API)High (framework-specific)
Browser SupportGrowing, not yet 100%Everywhere (polyfills included)
FlexibilityGood for standard transitionsVery high, complex animations

Sure, Framer Motion or Angular Animations offer more control over complex animation sequences. But for the vast majority of page transitions, the View Transitions API is the better choice: less code, better performance, and it even works without JavaScript for cross-document transitions.

jQuery Is Dead: Why You Should Remove It from Your Projects Immediately 🚀

💡 Conclusion

The View Transitions API is a genuine game-changer. It closes the gap between web and native apps - with minimal complexity. A few lines of CSS, optionally a bit of JavaScript, and your site suddenly feels like a native app.

The best part: it's progressive enhancement in its purest form. You add it, and those who can use it get a better experience. Everyone else notices no difference.

So: try it out. Add @view-transition { navigation: auto; } to your stylesheet and see what happens. You'll be surprised how much a simple crossfade can do.

Artikel teilen:Share article:

Discover more articles

View Transitions API: Smooth Page Transitions ohne Framework ✨
Previous article

View Transitions API: Smooth Page Transitions ohne Framework ✨

TL;DR: Die View Transitions API bringt butterweiche Seitenuebergaenge direkt in den Browser - ganz ohne Framework, ganz ohne JavaScript-Bibliothek. Einfach CSS und ein paar Zeilen JS. Hier erfaehrst du, wie das funktioniert und warum du es sofort ausprobieren solltest. 🤔 Was sind View Transitions ueberhaupt? Kennst du das? Du klickst

6 min read 13. Mai 2026
CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯
Similar article

CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯

TL;DR: CSS :has() is the long-awaited parent selector – you can finally style parent elements based on their children. No more JavaScript hacks, no workarounds, just pure CSS. And yes, it works in all modern browsers. 🤔 Why CSS Never Had a Parent Selector If you've been writing CSS

4 min read 27. Apr. 2026
Container Queries in CSS: The End of Media Queries? 📦
Similar article

Container Queries in CSS: The End of Media Queries? 📦

Container Queries put an end to viewport chaos! 📦 How to make your components truly responsive – and why Media Queries are not dead yet.

5 min read 14. März 2026
Angular and TailwindCSS: Utility-First CSS Meets Components 🎨
Similar article

Angular and TailwindCSS: Utility-First CSS Meets Components 🎨

Angular and TailwindCSS are a powerful duo. Here's how to set up Tailwind in your Angular project and use utility-first CSS effectively.

4 min read 13. März 2026
Tailwind CSS vs. Vanilla CSS – When Is Which Worth It? ⚖️
Similar article

Tailwind CSS vs. Vanilla CSS – When Is Which Worth It? ⚖️

Tailwind CSS or Vanilla CSS? ⚖️ I will show you when each approach is actually worth it – with real examples and honest pros and cons!

5 min read 11. März 2026