Barba.js Page Transition — Free Container-Swap Transition Snippet

Barba.js Page Transition · Animations · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Real Barba hook API
once/leave/enter match production usage exactly.
Namespace attributes
data-barba-namespace ready for per-pair transitions.
In-page adaptation
Two containers stand in for two fetched pages.
Fade + slide transition
Directional motion signals navigation, not a fade.
Promise-based hooks
leave/enter return promises Barba awaits.
Active link state
Nav highlights the current container's link.
No extra animation library
Transitions run on plain CSS transitions.
Sandbox-safe
Runs standalone without a server or router.

About this UI Snippet

Barba.js Page Transition — Leave/Enter Hooks on In-Page Containers

Screenshot of the Barba.js Page Transition snippet rendered live

Barba.js is built for real multi-page sites: it intercepts link clicks, fetches the next page's HTML over the network, and swaps a [data-barba="container"] element while running leave/enter transition hooks around the swap — that's how you get an animated crossfade between two actual URLs without a full page reload. A live sandbox like this one is a single HTML document with no server to fetch other pages from, so this snippet adapts Barba's exact hook shape — once, leave, enter, wrapped in a transitions array passed to barba.init() — onto two containers that already both live in the page, toggled by hidden instead of fetched over the network.

What's real Barba and what's adapted

barba.init({ transitions: [...] }), the once/leave/enter hook names, and the data-barba="wrapper" / data-barba="container" / data-barba-namespace markup are exactly how Barba is used in production. What's adapted is the navigation trigger: production Barba listens for clicks on any internal link and performs a real fetch, whereas this sandbox has no second page to fetch, so a small click handler toggles which container is visible and drives the same before/after transition timing Barba's hooks expect. If you drop this into a real multi-page site, you'd delete the click handler and toggling logic and let barba.init() manage navigation itself — the hook functions themselves barely change.

Why namespaces matter

Each container carries data-barba-namespace (home, work). In production this lets you register different transitions for different page-type pairs — a subtle crossfade between two blog posts, a bigger slide between the home page and a case study — by checking namespace inside the hook or by scoping transitions with from/to namespace filters. This snippet keeps a single transition for both, but the namespace attributes are there so extending it to per-pair transitions is a small addition, not a rewrite.

The fade-slide itself

leave animates the current container's opacity to 0 and nudges it up 24px; enter starts the next container 24px below its resting position at opacity 0 and animates it in. Because both are plain CSS transitions driven from JS (no external animation library needed beyond Barba itself), the pattern generalizes to a scale, blur, or clip-path transition just by changing what the hook functions set.

Where this differs from a scroll or hover effect

This is a navigation transition, not a scroll-triggered one — compare it to Swup page transition, which solves the identical problem with a different library and a hooks-object API instead of a transitions array. For animating elements as they scroll into view rather than on navigation, see scroll reveal grid.

Customizing it

Add more containers and namespaces, swap the fade-slide for a curtain wipe or shared-element morph, or add a loading bar during leave for slower page swaps. In a real deployment, remove the click-interception shim entirely — Barba's own link listener and fetch pipeline replace it outright.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to guess which parts of this file are real Barba.js and which are the sandbox workaround. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to point out exactly where barba.init()'s once/leave/enter hooks are genuinely doing the transition work versus where the click handler is standing in for Barba's own fetch-based router, and what would need to change to run this against real second and third pages instead of two in-page containers. The same assistant can help you extend it — asking how to register a different transition for a specific pair of data-barba-namespace values, or how to add a loading indicator during the leave phase for slower real-world page fetches. It's also useful for comparing approaches: ask it to explain the tradeoffs between Barba's transitions-array API and Swup's hooks-emitter API for the same navigation-transition problem. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a page transition demo using Barba.js's real hook API (load barba.umd.js from a CDN), adapted to run inside a single HTML document with no server-side routing.

Requirements:
- A data-barba="wrapper" element containing a small nav with two links and two data-barba="container" elements (each with its own data-barba-namespace), where the second container starts hidden.
- Call barba.init() with a transitions array containing one transition object that defines once, leave, and enter hook functions using Barba's real hook names and signatures — leave receives the current container reference, enter receives the next container reference.
- Since there is no second page to fetch in a single-document sandbox, implement navigation yourself: intercept clicks on the nav links, determine which container should become visible, and manually invoke the same before/after animation timing that leave and enter perform, using the hidden attribute or a visibility toggle to swap which container is shown — but keep the leave and enter functions themselves written exactly as they would be used in a real Barba multi-page setup (returning promises that resolve after their CSS transition completes).
- The transition itself should combine an opacity fade with a vertical slide, so leaving content moves and fades one direction while entering content moves and fades in from the opposite direction, using plain CSS transitions driven by inline style changes from JavaScript (no additional animation library beyond Barba).
- Update the active nav link's styling to reflect whichever container is currently showing.
- In code comments, clearly mark which parts of the implementation are genuine Barba.js hook usage versus the click-interception shim that exists only because this is a single-page sandbox without real page-to-page navigation.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Add the Barba.js CDNInclude barba.umd.js from the CDN panel.
  2. 2
    Paste HTML, CSS, and JSA nav and two containers render, one hidden.
  3. 3
    Click "Work"The home container fades/slides out.
  4. 4
    Watch the swapThe work container fades/slides in with its own copy.
  5. 5
    Click back to "Home"The transition reverses direction cleanly.
  6. 6
    Adapt for productionRemove the click shim; let barba.init() own navigation.

Real-world uses

Common Use Cases

Multi-page site transitions
Prototype the hook logic before wiring real fetches.
Portfolio case studies
Transition between project "pages" smoothly.
Agency sites
Pair with parallax hero landing sections.
Comparing transition libraries
See it beside Swup page transition.
Learning Barba.js
Read real hook code without a build step.
Design reviews
Demo a transition concept before backend wiring.

Got questions?

Frequently Asked Questions

Barba.js is genuinely initialized via barba.init({ transitions: [...] }) with the real once, leave, and enter hook functions running exactly as they would in production. What's adapted is only the trigger: because this sandbox has no second URL to fetch, a small click handler toggles which of the two existing containers is visible and calls the same before/after sequence Barba's hooks expect, rather than Barba's own fetch-based router doing it.

You would delete the click-interception code and the hidden-toggling logic entirely. Barba's own link listener would intercept clicks on internal links, fetch the destination page's HTML, extract its [data-barba="container"], and run the same leave/enter transition hooks around swapping it in — the transition functions themselves are already written in the exact shape Barba expects, so they carry over unchanged.

It labels each container with a page type so you can scope different transitions to different navigation pairs — for example a quick crossfade between two blog posts but a larger slide from the home page to a case study. This demo only registers one transition for both namespaces, but the attributes are already in place so adding namespace-specific transitions is additive, not a restructure.

Barba awaits whatever leave and enter return before considering the transition complete and moving to the next step (running enter after leave resolves, or considering navigation finished after enter resolves). Returning a promise that resolves after a setTimeout matching the CSS transition duration is the standard pattern for wrapping CSS-driven animation in Barba's hook lifecycle.

Barba and Swup solve the same problem — animated transitions between page loads — with different APIs: Barba uses a transitions array of hook objects passed to init, while Swup exposes a hooks event emitter (swup.hooks.on("visit:start", ...)) and CSS class toggling driven by data-swup-* attributes. See the companion Swup page transition snippet for the same in-page adaptation built on that API instead.