Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
CSS

Create Smooth Page Transitions with CSS View Transitions API (No JavaScript)

- 01.02.26 | 01.02.26 - ErcanOPAK

Page navigation feels jarring? The new CSS View Transitions API creates native app-like transitions without a single line of JavaScript.

The Basic Setup:

/* Enable view transitions for all navigations */
@view-transition {
  navigation: auto;
}

/* Customize the transition */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.3s;
  animation-timing-function: ease-in-out;
}

/* Fade effect */
::view-transition-old(root) {
  animation-name: fade-out;
}

::view-transition-new(root) {
  animation-name: fade-in;
}

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

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

How It Works:
When the user navigates to a new page:
1. Browser captures a screenshot of the current page
2. Loads the new page in the background
3. Captures a screenshot of the new page
4. Animates between the two screenshots

All this happens automatically with just the CSS above. No JavaScript event listeners, no DOM manipulation, no library dependencies.

Advanced – Element-Specific Transitions:

/* Tag specific elements to transition smoothly */
.product-image {
  view-transition-name: product-hero;
}

.price-badge {
  view-transition-name: price-info;
}

/* Animate them differently */
::view-transition-old(product-hero),
::view-transition-new(product-hero) {
  animation-duration: 0.5s;
  height: 100%;
  object-fit: cover;
}

::view-transition-old(price-info) {
  animation: slide-out-right 0.3s ease-out;
}

::view-transition-new(price-info) {
  animation: slide-in-left 0.3s ease-out;
}

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

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

Real-World Example – E-Commerce Product Pages:

/* Product listing page */
.product-card img {
  view-transition-name: var(--product-id);
  /* Each product gets unique transition name */
}

/* Product detail page */
.hero-image {
  view-transition-name: var(--product-id);
  /* Same name = smooth morph from thumbnail to full size */
}

When users click a product thumbnail, it smoothly expands into the hero image on the detail page. No JavaScript libraries, no complex state management.

Why This Matters:
Before View Transitions API:
• React Router: +40KB bundle
• Framer Motion: +60KB bundle
• Custom JavaScript: 100+ lines of code
• Performance overhead from JS parsing and execution

With View Transitions API:
• 0KB JavaScript
• Native browser optimization
• Hardware-accelerated animations
• 20 lines of CSS

Browser Support (as of 2024):
✅ Chrome 111+
✅ Edge 111+
✅ Opera 97+
⚠️ Firefox: Behind flag
⚠️ Safari: In development

Graceful Degradation:

@supports (view-transition-name: none) {
  /* View Transitions supported */
  @view-transition { navigation: auto; }
}

@supports not (view-transition-name: none) {
  /* Fallback for unsupported browsers */
  * { transition: opacity 0.2s; }
}

In unsupported browsers, pages just load normally. No broken experience, no errors.

Related posts:

CSS Layout Breaks on Mobile Only

How to add some content to the right side of CardHeader on Bootstrap

The aspect-ratio property

Post Views: 3

Post navigation

Fix Windows 11 Slow Boot by Cleaning Up Startup Items (PowerShell Method)
Use HTML Dialog Element for Accessible Modals (Forget JavaScript Libraries)

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

February 2026
M T W T F S S
 1
2345678
9101112131415
16171819202122
232425262728  
« Jan    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (934)
  • How to add default value for Entity Framework migrations for DateTime and Bool (830)
  • Get the First and Last Word from a String or Sentence in SQL (822)
  • How to select distinct rows in a datatable in C# (799)
  • How to make theater mode the default for Youtube (708)
  • Add Constraint to SQL Table to ensure email contains @ (572)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (552)
  • Average of all values in a column that are not zero in SQL (517)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (473)
  • Find numbers with more than two decimal places in SQL (436)

Recent Posts

  • C#: Use init Accessor to Create Immutable Objects Without Constructor Boilerplate
  • C#: Use Index and Range Operators for Cleaner Array Slicing
  • C#: Use Null-Coalescing Assignment to Simplify Lazy Initialization
  • SQL: Use CHAR Instead of VARCHAR for Fixed-Length Columns to Save Space
  • SQL: Use CROSS APPLY Instead of Subqueries for Better Performance
  • .NET Core: Use Required Modifier to Force Property Initialization
  • .NET Core: Use Global Using Directives to Avoid Repeating Imports
  • Git: Use git restore to Unstage Files Without Losing Changes
  • Git: Use git bisect to Find Which Commit Introduced a Bug
  • AJAX: Use Fetch with Signal to Cancel Requests When User Navigates Away

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (934)
  • How to add default value for Entity Framework migrations for DateTime and Bool (830)
  • Get the First and Last Word from a String or Sentence in SQL (822)
  • How to select distinct rows in a datatable in C# (799)
  • How to make theater mode the default for Youtube (708)

Recent Posts

  • C#: Use init Accessor to Create Immutable Objects Without Constructor Boilerplate
  • C#: Use Index and Range Operators for Cleaner Array Slicing
  • C#: Use Null-Coalescing Assignment to Simplify Lazy Initialization
  • SQL: Use CHAR Instead of VARCHAR for Fixed-Length Columns to Save Space
  • SQL: Use CROSS APPLY Instead of Subqueries for Better Performance

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com