Enable native cross-document page transitions and smooth shared element animations without JavaScript routing libraries using the CSS @view-transition at-rule and view-transition-name.
Traditional multi-page websites can cause abrupt layout flashes during page navigation. With CSS View Transitions Level 2, modern browsers can animate page transitions across same-origin HTML navigations natively.
1. Enable Cross-Document Transitions
Add the @view-transition at-rule to your global stylesheet to opt into cross-document transition rendering:
@view-transition {
navigation: auto;
}
2. Connect Shared Elements Across Pages
Assign a matching view-transition-name to elements that persist across pages, such as active navigation indicators or profile avatars:
<!-- Shared active navigation indicator -->
<span class="active-indicator" style="view-transition-name: active-nav-indicator;"></span>
<!-- Shared profile picture between pages -->
<img src="/avatar.jpg" alt="Profile" style="view-transition-name: profile-avatar;">
Page 1 (/): Start
┌───────────────────────────────────────────────────────────┐
│ Home Services Projects Open Source Tips Resume │
│ ━━━━ │
└───────────────────────────────────────────────────────────┘
↓
Mid-Transition (Shared Element Morph):
┌───────────────────────────────────────────────────────────┐
│ Home Services Projects Open Source Tips Resume │
│ ━━━━━━ │
└───────────────────────────────────────────────────────────┘
↓
Page 2 (/projects): Complete
┌───────────────────────────────────────────────────────────┐
│ Home Services Projects Open Source Tips Resume │
│ ━━━━━━━━ │
└───────────────────────────────────────────────────────────┘
3. Customize Group Timing and Prevent Ghosting
By default, the browser animates element geometry while cross-fading old and new snapshots. For solid elements like indicator lines or avatars, you can disable the opacity cross-fade so the element physically glides and morphs to its new position:
/* Target the shared element transition group */
::view-transition-group(active-nav-indicator),
::view-transition-group(profile-avatar) {
animation-duration: 480ms;
animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
z-index: 1000;
}
/* Prevent cross-fade opacity for clean sliding */
::view-transition-old(active-nav-indicator),
::view-transition-new(active-nav-indicator) {
animation: none;
mix-blend-mode: normal;
height: 100%;
}
/* Respect user motion preferences */
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root),
::view-transition-group(active-nav-indicator),
::view-transition-group(profile-avatar) {
animation: none !important;
}
}
Practical Takeaways
- Delivers smooth page morphing on standard multi-page static sites and Laravel Blade templates.
- Requires zero client-side routing libraries or Single Page Application (SPA) frameworks.
- Functions as progressive enhancement: browsers without View Transition Level 2 support perform standard instant page navigations.
Related Tips
View all tips →Prevent Navigation Layout Shifts and Flickering in Web Applications
Fix common navigation bar layout shifts, scrollbar jumps, font width shifts, and theme switcher flickering with clean CSS and HTML patterns.
Use CSS Container Queries for Modular Component Layouts
Use CSS Container Queries (@container) to adjust component layouts based on parent container width rather than viewport size.