barba-js by freshtechbro/claudedesignskills
npx skills add https://github.com/freshtechbro/claudedesignskills --skill barba-js现代页面过渡库,用于在网站页面之间创建流畅、平滑的过渡效果。Barba.js 通过劫持导航并管理过渡过程(无需完全重新加载页面),使多页面网站具备类似单页面应用(SPA)的体验。
Barba.js 是一个轻量级(压缩后仅 7kb)的 JavaScript 库,它拦截页面间的导航,通过 AJAX 获取新内容,并在新旧容器之间平滑过渡。它减少了页面加载延迟和 HTTP 请求,同时保留了传统多页面架构的优势。
核心特性:
Barba.js 使用特定的 DOM 结构来管理过渡:
HTML 结构:
<body data-barba="wrapper">
<!-- 静态元素(页眉、导航栏)保持在容器外部 -->
<header>
<nav>
<a href="/">首页</a>
<a href="/about">关于</a>
</nav>
</header>
<!-- 动态内容放在容器内 -->
<main data-barba="container" data-barba-namespace="home">
<!-- 导航时此内容会改变 -->
<h1>首页</h1>
<p>将要过渡出去的内容...</p>
</main>
<!-- 容器外的静态页脚 -->
<footer>© 2025</footer>
</body>
三个关键元素:
包装器 (data-barba="wrapper")
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
容器 (data-barba="container")
命名空间 (data-barba-namespace="home")
Barba.js 为每次导航遵循精确的生命周期:
默认异步流程:
同步流程(使用 sync: true):
Barba 提供了 11 个生命周期钩子来控制过渡:
钩子执行顺序:
初始页面加载:
beforeOnce → once → afterOnce
每次导航:
before → beforeLeave → leave → afterLeave →
beforeEnter → enter → afterEnter → after
钩子类型:
barba.hooks.before())常见钩子用例:
beforeLeave - 重置滚动位置,准备动画leave - 当前页面动画退出afterLeave - 清理旧页面beforeEnter - 准备新页面(隐藏元素,设置初始状态)enter - 新页面动画进入afterEnter - 初始化页面脚本,分析跟踪视图是基于命名空间运行的特定页面逻辑容器:
barba.init({
views: [{
namespace: 'home',
beforeEnter() {
// 首页特定设置
console.log('进入首页');
},
afterEnter() {
// 初始化首页功能
initHomeSlider();
}
}, {
namespace: 'product',
beforeEnter() {
console.log('进入产品页面');
},
afterEnter() {
initProductGallery();
}
}]
});
安装:
npm install --save-dev @barba/core
# 或
yarn add @barba/core --dev
最小配置:
import barba from '@barba/core';
barba.init({
transitions: [{
name: 'default',
leave({ current }) {
// 淡出当前页面
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
// 淡入新页面
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});
经典的淡出、淡入过渡:
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
name: 'fade',
async leave({ current }) {
await gsap.to(current.container, {
opacity: 0,
duration: 0.5,
ease: 'power2.inOut'
});
},
async enter({ next }) {
// 初始不可见
gsap.set(next.container, { opacity: 0 });
// 淡入
await gsap.to(next.container, {
opacity: 1,
duration: 0.5,
ease: 'power2.inOut'
});
}
}]
});
页面间同时淡入淡出:
barba.init({
transitions: [{
name: 'crossfade',
sync: true, // 启用同步模式
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
}
}]
});
旧页面滑出,新页面滑入并重叠:
barba.init({
transitions: [{
name: 'slide',
sync: true,
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.7,
ease: 'power3.inOut'
});
},
enter({ next }) {
// 从右侧屏幕外开始
gsap.set(next.container, { x: '100%' });
// 从右侧滑入
return gsap.to(next.container, {
x: '0%',
duration: 0.7,
ease: 'power3.inOut'
});
}
}]
});
根据导航上下文定义不同的过渡:
barba.init({
transitions: [
// 从首页到任何页面:淡入淡出
{
name: 'from-home-fade',
from: { namespace: 'home' },
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
},
// 产品页到产品页:向左滑动
{
name: 'product-to-product',
from: { namespace: 'product' },
to: { namespace: 'product' },
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.6
});
},
enter({ next }) {
gsap.set(next.container, { x: '100%' });
return gsap.to(next.container, {
x: '0%',
duration: 0.6
});
}
},
// 默认回退
{
name: 'default',
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.3
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.3
});
}
}
]
});
使用 @barba/router 实现特定路由的过渡:
安装:
npm install --save-dev @barba/router
用法:
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
import barbaRouter from '@barba/router';
// 定义路由
barbaRouter.init({
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
{ path: '/products/:id', name: 'product' }, // 动态段
{ path: '/blog/:category/:slug', name: 'blog-post' }
]
});
barba.use(barbaRouter);
barba.use(barbaPrefetch); // 可选:悬停时预取
barba.init({
transitions: [{
name: 'product-transition',
to: { route: 'product' }, // 根据路由名称触发
leave({ current }) {
return gsap.to(current.container, {
scale: 0.95,
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
scale: 1.05,
opacity: 0,
duration: 0.5
});
}
}]
});
在页面获取期间显示加载状态:
barba.init({
transitions: [{
async leave({ current }) {
// 显示加载器
const loader = document.querySelector('.loader');
gsap.set(loader, { display: 'flex', opacity: 0 });
gsap.to(loader, { opacity: 1, duration: 0.3 });
// 淡出页面
await gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
async enter({ next }) {
// 隐藏加载器
const loader = document.querySelector('.loader');
await gsap.to(loader, { opacity: 0, duration: 0.3 });
gsap.set(loader, { display: 'none' });
// 淡入页面
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});
Barba.js 可与 GSAP 无缝协作实现动画:
基于时间线的过渡:
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
async leave({ current }) {
const tl = gsap.timeline();
tl.to(current.container.querySelector('h1'), {
y: -50,
opacity: 0,
duration: 0.3
})
.to(current.container.querySelector('.content'), {
y: -30,
opacity: 0,
duration: 0.3
}, '-=0.2')
.to(current.container, {
opacity: 0,
duration: 0.2
});
await tl.play();
},
async enter({ next }) {
const tl = gsap.timeline();
// 设置初始状态
gsap.set(next.container, { opacity: 0 });
gsap.set(next.container.querySelector('h1'), { y: 50, opacity: 0 });
gsap.set(next.container.querySelector('.content'), { y: 30, opacity: 0 });
tl.to(next.container, {
opacity: 1,
duration: 0.2
})
.to(next.container.querySelector('h1'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
})
.to(next.container.querySelector('.content'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
}, '-=0.3');
await tl.play();
}
}]
});
参考 gsap-scrolltrigger 技能以获取高级 GSAP 集成模式。
为每个页面初始化库或脚本:
barba.init({
views: [
{
namespace: 'home',
afterEnter() {
// 初始化首页功能
initHomepageSlider();
initParallaxEffects();
},
beforeLeave() {
// 清理
destroyHomepageSlider();
}
},
{
namespace: 'gallery',
afterEnter() {
initLightbox();
initMasonry();
},
beforeLeave() {
destroyLightbox();
}
}
]
});
在导航时跟踪页面浏览量:
barba.hooks.after(() => {
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: window.location.pathname
});
}
// 或使用数据层
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'pageview',
page: window.location.pathname
});
});
页面过渡后重新运行脚本:
barba.hooks.after(() => {
// 重新初始化第三方小部件
if (typeof twttr !== 'undefined') {
twttr.widgets.load(); // Twitter 小部件
}
if (typeof FB !== 'undefined') {
FB.XFBML.parse(); // Facebook 小部件
}
// 重新运行语法高亮
if (typeof Prism !== 'undefined') {
Prism.highlightAll();
}
});
使用 @barba/prefetch 在悬停时加载页面:
npm install --save-dev @barba/prefetch
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
barba.use(barbaPrefetch);
barba.init({
// 默认在链接悬停时触发预取
prefetch: {
root: null, // 观察所有链接
timeout: 3000 // 缓存超时时间(毫秒)
}
});
设置容器最小高度以防止内容跳动:
[data-barba="container"] {
min-height: 100vh;
/* 或使用视口高度减去页眉/页脚 */
min-height: calc(100vh - 80px - 60px);
}
使用 GPU 加速属性:
// ✅ 良好 - GPU 加速
gsap.to(element, {
opacity: 0,
x: -100,
scale: 0.9,
rotation: 45
});
// ❌ 避免 - 导致重排/重绘
gsap.to(element, {
width: '50%',
height: '300px',
top: '100px'
});
在 beforeLeave 或视图钩子中移除监听器:
barba.init({
views: [{
namespace: 'home',
afterEnter() {
// 添加监听器
this.clickHandler = () => console.log('点击了');
document.querySelector('.btn').addEventListener('click', this.clickHandler);
},
beforeLeave() {
// 移除监听器
document.querySelector('.btn').removeEventListener('click', this.clickHandler);
}
}]
});
推迟图片加载直到过渡完成后:
barba.init({
transitions: [{
async enter({ next }) {
// 先完成过渡
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
// 然后加载图片
const images = next.container.querySelectorAll('img[data-src]');
images.forEach(img => {
img.src = img.dataset.src;
img.removeAttribute('data-src');
});
}
}]
});
问题:过渡瞬间完成,不等待动画。
解决方案:始终返回 Promise 或使用 async/await:
// ❌ 错误 - 动画开始但不等待
leave({ current }) {
gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ 正确 - 返回 Promise
leave({ current }) {
return gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ 也正确 - async/await
async leave({ current }) {
await gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
问题:某些链接导致完全页面重新加载。
解决方案:Barba 会自动阻止内部链接的默认行为,但可能需要排除外部链接:
barba.init({
prevent: ({ href }) => {
// 允许外部链接
if (href.indexOf('http') > -1 && href.indexOf(window.location.host) === -1) {
return true;
}
return false;
}
});
问题:旧页面的 CSS 在过渡期间影响新页面布局。
解决方案:使用命名空间特定的 CSS 或重置样式:
/* 命名空间特定样式 */
[data-barba-namespace="home"] .hero {
background: blue;
}
[data-barba-namespace="about"] .hero {
background: red;
}
或在 beforeEnter 中重置:
beforeEnter({ next }) {
// 重置滚动位置
window.scrollTo(0, 0);
// 重置任何全局状态
document.body.classList.remove('menu-open');
}
问题:导航时页面标题和元标签不更新。
解决方案:使用 @barba/head 插件或手动更新:
npm install --save-dev @barba/head
import barba from '@barba/core';
import barbaHead from '@barba/head';
barba.use(barbaHead);
barba.init({
// Head 插件自动更新 <head> 标签
});
或手动:
barba.hooks.after(({ next }) => {
// 更新标题
document.title = next.html.querySelector('title').textContent;
// 更新元标签
const newMeta = next.html.querySelectorAll('meta');
newMeta.forEach(meta => {
const name = meta.getAttribute('name') || meta.getAttribute('property');
if (name) {
const existing = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`);
if (existing) {
existing.setAttribute('content', meta.getAttribute('content'));
}
}
});
});
问题:新页面在进入动画开始前闪现可见。
解决方案:在 CSS 或 beforeEnter 中设置初始不可见状态:
/* CSS 方法 */
[data-barba="container"] {
opacity: 0;
}
[data-barba="container"].is-visible {
opacity: 1;
}
// JavaScript 方法
beforeEnter({ next }) {
gsap.set(next.container, { opacity: 0 });
}
问题:同步过渡导致容器堆叠时布局偏移。
解决方案:在过渡期间绝对定位容器:
[data-barba="wrapper"] {
position: relative;
}
[data-barba="container"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
或在 JavaScript 中管理:
barba.init({
transitions: [{
sync: true,
beforeLeave({ current }) {
gsap.set(current.container, {
position: 'absolute',
top: 0,
left: 0,
width: '100%'
});
}
}]
});
此技能包含:
用于常见 Barba.js 任务的可执行工具:
transition_generator.py - 生成过渡样板代码project_setup.py - 初始化 Barba.js 项目结构详细文档:
api_reference.md - 完整的 Barba.js API(钩子、过渡、视图、路由)hooks_guide.md - 所有 11 个钩子及其执行顺序和用例gsap_integration.md - 用于 Barba 过渡的 GSAP 动画模式transition_patterns.md - 常见的过渡实现模板和入门项目:
starter_barba/ - 完整的 Barba.js + GSAP 入门模板examples/ - 真实世界的过渡实现每周安装数
88
仓库
GitHub 星标数
11
首次出现
2026年2月27日
安全审计
安装于
opencode88
kimi-cli86
claude-code86
github-copilot86
amp86
cline86
Modern page transition library for creating fluid, smooth transitions between website pages. Barba.js makes multi-page websites feel like Single Page Applications (SPAs) by hijacking navigation and managing transitions without full page reloads.
Barba.js is a lightweight (7kb minified and compressed) JavaScript library that intercepts navigation between pages, fetches new content via AJAX, and smoothly transitions between old and new containers. It reduces page load delays and HTTP requests while maintaining the benefits of traditional multi-page architecture.
Core Features :
Barba.js uses a specific DOM structure to manage transitions:
HTML Structure :
<body data-barba="wrapper">
<!-- Static elements (header, nav) stay outside container -->
<header>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<!-- Dynamic content goes in container -->
<main data-barba="container" data-barba-namespace="home">
<!-- This content changes on navigation -->
<h1>Home Page</h1>
<p>Content that will transition out...</p>
</main>
<!-- Static footer outside container -->
<footer>© 2025</footer>
</body>
Three Key Elements :
Wrapper (data-barba="wrapper")
Container (data-barba="container")
Namespace (data-barba-namespace="home")
Barba.js follows a precise lifecycle for each navigation:
Default Async Flow :
Sync Flow (with sync: true):
Barba provides 11 lifecycle hooks for controlling transitions:
Hook Execution Order :
Initial page load:
beforeOnce → once → afterOnce
Every navigation:
before → beforeLeave → leave → afterLeave →
beforeEnter → enter → afterEnter → after
Hook Types :
barba.hooks.before())Common Hook Use Cases :
beforeLeave - Reset scroll position, prepare animationsleave - Animate current page outafterLeave - Clean up old pagebeforeEnter - Prepare new page (hide elements, set initial states)enter - Animate new page inafterEnter - Initialize page scripts, analytics trackingViews are page-specific logic containers that run based on namespace:
barba.init({
views: [{
namespace: 'home',
beforeEnter() {
// Home-specific setup
console.log('Entering home page');
},
afterEnter() {
// Initialize home page features
initHomeSlider();
}
}, {
namespace: 'product',
beforeEnter() {
console.log('Entering product page');
},
afterEnter() {
initProductGallery();
}
}]
});
Installation :
npm install --save-dev @barba/core
# or
yarn add @barba/core --dev
Minimal Configuration :
import barba from '@barba/core';
barba.init({
transitions: [{
name: 'default',
leave({ current }) {
// Fade out current page
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
// Fade in new page
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});
Classic fade-out, fade-in transition:
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
name: 'fade',
async leave({ current }) {
await gsap.to(current.container, {
opacity: 0,
duration: 0.5,
ease: 'power2.inOut'
});
},
async enter({ next }) {
// Start invisible
gsap.set(next.container, { opacity: 0 });
// Fade in
await gsap.to(next.container, {
opacity: 1,
duration: 0.5,
ease: 'power2.inOut'
});
}
}]
});
Simultaneous fade between pages:
barba.init({
transitions: [{
name: 'crossfade',
sync: true, // Enable sync mode
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.8,
ease: 'power2.inOut'
});
}
}]
});
Slide old page out, new page in with overlap:
barba.init({
transitions: [{
name: 'slide',
sync: true,
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.7,
ease: 'power3.inOut'
});
},
enter({ next }) {
// Start off-screen right
gsap.set(next.container, { x: '100%' });
// Slide in from right
return gsap.to(next.container, {
x: '0%',
duration: 0.7,
ease: 'power3.inOut'
});
}
}]
});
Define different transitions based on navigation context:
barba.init({
transitions: [
// Home to any page: fade
{
name: 'from-home-fade',
from: { namespace: 'home' },
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
},
// Product to product: slide left
{
name: 'product-to-product',
from: { namespace: 'product' },
to: { namespace: 'product' },
leave({ current }) {
return gsap.to(current.container, {
x: '-100%',
duration: 0.6
});
},
enter({ next }) {
gsap.set(next.container, { x: '100%' });
return gsap.to(next.container, {
x: '0%',
duration: 0.6
});
}
},
// Default fallback
{
name: 'default',
leave({ current }) {
return gsap.to(current.container, {
opacity: 0,
duration: 0.3
});
},
enter({ next }) {
return gsap.from(next.container, {
opacity: 0,
duration: 0.3
});
}
}
]
});
Use @barba/router for route-specific transitions:
Installation :
npm install --save-dev @barba/router
Usage :
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
import barbaRouter from '@barba/router';
// Define routes
barbaRouter.init({
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
{ path: '/products/:id', name: 'product' }, // Dynamic segment
{ path: '/blog/:category/:slug', name: 'blog-post' }
]
});
barba.use(barbaRouter);
barba.use(barbaPrefetch); // Optional: prefetch on hover
barba.init({
transitions: [{
name: 'product-transition',
to: { route: 'product' }, // Trigger on route name
leave({ current }) {
return gsap.to(current.container, {
scale: 0.95,
opacity: 0,
duration: 0.5
});
},
enter({ next }) {
return gsap.from(next.container, {
scale: 1.05,
opacity: 0,
duration: 0.5
});
}
}]
});
Show loading state during page fetch:
barba.init({
transitions: [{
async leave({ current }) {
// Show loader
const loader = document.querySelector('.loader');
gsap.set(loader, { display: 'flex', opacity: 0 });
gsap.to(loader, { opacity: 1, duration: 0.3 });
// Fade out page
await gsap.to(current.container, {
opacity: 0,
duration: 0.5
});
},
async enter({ next }) {
// Hide loader
const loader = document.querySelector('.loader');
await gsap.to(loader, { opacity: 0, duration: 0.3 });
gsap.set(loader, { display: 'none' });
// Fade in page
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
}
}]
});
Barba.js works seamlessly with GSAP for animations:
Timeline-Based Transitions :
import barba from '@barba/core';
import gsap from 'gsap';
barba.init({
transitions: [{
async leave({ current }) {
const tl = gsap.timeline();
tl.to(current.container.querySelector('h1'), {
y: -50,
opacity: 0,
duration: 0.3
})
.to(current.container.querySelector('.content'), {
y: -30,
opacity: 0,
duration: 0.3
}, '-=0.2')
.to(current.container, {
opacity: 0,
duration: 0.2
});
await tl.play();
},
async enter({ next }) {
const tl = gsap.timeline();
// Set initial states
gsap.set(next.container, { opacity: 0 });
gsap.set(next.container.querySelector('h1'), { y: 50, opacity: 0 });
gsap.set(next.container.querySelector('.content'), { y: 30, opacity: 0 });
tl.to(next.container, {
opacity: 1,
duration: 0.2
})
.to(next.container.querySelector('h1'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
})
.to(next.container.querySelector('.content'), {
y: 0,
opacity: 1,
duration: 0.5,
ease: 'power3.out'
}, '-=0.3');
await tl.play();
}
}]
});
Reference gsap-scrolltrigger skill for advanced GSAP integration patterns.
Initialize libraries or scripts per page:
barba.init({
views: [
{
namespace: 'home',
afterEnter() {
// Initialize home page features
initHomepageSlider();
initParallaxEffects();
},
beforeLeave() {
// Clean up
destroyHomepageSlider();
}
},
{
namespace: 'gallery',
afterEnter() {
initLightbox();
initMasonry();
},
beforeLeave() {
destroyLightbox();
}
}
]
});
Track page views on navigation:
barba.hooks.after(() => {
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: window.location.pathname
});
}
// Or use data layer
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'pageview',
page: window.location.pathname
});
});
Re-run scripts after page transitions:
barba.hooks.after(() => {
// Re-initialize third-party widgets
if (typeof twttr !== 'undefined') {
twttr.widgets.load(); // Twitter widgets
}
if (typeof FB !== 'undefined') {
FB.XFBML.parse(); // Facebook widgets
}
// Re-run syntax highlighting
if (typeof Prism !== 'undefined') {
Prism.highlightAll();
}
});
Use @barba/prefetch to load pages on hover:
npm install --save-dev @barba/prefetch
import barba from '@barba/core';
import barbaPrefetch from '@barba/prefetch';
barba.use(barbaPrefetch);
barba.init({
// Prefetch fires on link hover by default
prefetch: {
root: null, // Observe all links
timeout: 3000 // Cache timeout in ms
}
});
Set container min-height to prevent content jump:
[data-barba="container"] {
min-height: 100vh;
/* Or use viewport height minus header/footer */
min-height: calc(100vh - 80px - 60px);
}
Use GPU-accelerated properties:
// ✅ Good - GPU accelerated
gsap.to(element, {
opacity: 0,
x: -100,
scale: 0.9,
rotation: 45
});
// ❌ Avoid - causes reflow/repaint
gsap.to(element, {
width: '50%',
height: '300px',
top: '100px'
});
Remove listeners in beforeLeave or view hooks:
barba.init({
views: [{
namespace: 'home',
afterEnter() {
// Add listeners
this.clickHandler = () => console.log('clicked');
document.querySelector('.btn').addEventListener('click', this.clickHandler);
},
beforeLeave() {
// Remove listeners
document.querySelector('.btn').removeEventListener('click', this.clickHandler);
}
}]
});
Defer image loading until after transition:
barba.init({
transitions: [{
async enter({ next }) {
// Complete transition first
await gsap.from(next.container, {
opacity: 0,
duration: 0.5
});
// Then load images
const images = next.container.querySelectorAll('img[data-src]');
images.forEach(img => {
img.src = img.dataset.src;
img.removeAttribute('data-src');
});
}
}]
});
Problem : Transitions complete instantly without waiting for animations.
Solution : Always return promises or use async/await:
// ❌ Wrong - animation starts but doesn't wait
leave({ current }) {
gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ Correct - returns promise
leave({ current }) {
return gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
// ✅ Also correct - async/await
async leave({ current }) {
await gsap.to(current.container, { opacity: 0, duration: 0.5 });
}
Problem : Some links cause full page reloads.
Solution : Barba automatically prevents default on internal links, but you may need to exclude external links:
barba.init({
prevent: ({ href }) => {
// Allow external links
if (href.indexOf('http') > -1 && href.indexOf(window.location.host) === -1) {
return true;
}
return false;
}
});
Problem : Old page CSS affects new page layout during transition.
Solution : Use namespace-specific CSS or reset styles:
/* Namespace-specific styles */
[data-barba-namespace="home"] .hero {
background: blue;
}
[data-barba-namespace="about"] .hero {
background: red;
}
Or reset in beforeEnter:
beforeEnter({ next }) {
// Reset scroll position
window.scrollTo(0, 0);
// Reset any global state
document.body.classList.remove('menu-open');
}
Problem : Page title and meta tags don't update on navigation.
Solution : Use @barba/head plugin or update manually:
npm install --save-dev @barba/head
import barba from '@barba/core';
import barbaHead from '@barba/head';
barba.use(barbaHead);
barba.init({
// Head plugin automatically updates <head> tags
});
Or manually:
barba.hooks.after(({ next }) => {
// Update title
document.title = next.html.querySelector('title').textContent;
// Update meta tags
const newMeta = next.html.querySelectorAll('meta');
newMeta.forEach(meta => {
const name = meta.getAttribute('name') || meta.getAttribute('property');
if (name) {
const existing = document.querySelector(`meta[name="${name}"], meta[property="${name}"]`);
if (existing) {
existing.setAttribute('content', meta.getAttribute('content'));
}
}
});
});
Problem : New page flashes visible before enter animation starts.
Solution : Set initial invisible state in CSS or beforeEnter:
/* CSS approach */
[data-barba="container"] {
opacity: 0;
}
[data-barba="container"].is-visible {
opacity: 1;
}
// JavaScript approach
beforeEnter({ next }) {
gsap.set(next.container, { opacity: 0 });
}
Problem : Sync transitions cause layout shift as containers stack.
Solution : Position containers absolutely during transition:
[data-barba="wrapper"] {
position: relative;
}
[data-barba="container"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
Or manage in JavaScript:
barba.init({
transitions: [{
sync: true,
beforeLeave({ current }) {
gsap.set(current.container, {
position: 'absolute',
top: 0,
left: 0,
width: '100%'
});
}
}]
});
This skill includes:
Executable utilities for common Barba.js tasks:
transition_generator.py - Generate transition boilerplate codeproject_setup.py - Initialize Barba.js project structureDetailed documentation:
api_reference.md - Complete Barba.js API (hooks, transitions, views, router)hooks_guide.md - All 11 hooks with execution order and use casesgsap_integration.md - GSAP animation patterns for Barba transitionstransition_patterns.md - Common transition implementationsTemplates and starter projects:
starter_barba/ - Complete Barba.js + GSAP starter templateexamples/ - Real-world transition implementationsWeekly Installs
88
Repository
GitHub Stars
11
First Seen
Feb 27, 2026
Security Audits
Gen Agent Trust HubPassSocketWarnSnykWarn
Installed on
opencode88
kimi-cli86
claude-code86
github-copilot86
amp86
cline86
网页可访问性(A11y)开发指南:实现WCAG合规、键盘导航与屏幕阅读器支持
12,600 周安装
社交媒体内容创作与管理技能:LinkedIn/X/Reddit/Discord 平台自动化工具
145 周安装
使用 bslib 构建现代化 Shiny 应用:Bootstrap 5 仪表盘与 UI 组件库
142 周安装
Python PDF处理全指南:合并拆分、文本表格提取、创建PDF文件
142 周安装
Mux视频平台开发指南:视频流、直播、播放器集成与AI工作流
83 周安装
Next.js App Router国际化方案:next-intl多语言路由配置指南
144 周安装
阿里云 AnalyticDB MySQL 数据库技能冒烟测试指南与自动化脚本
144 周安装