Skip to content

Add Page Transitions feature #363

@georgeolaru

Description

@georgeolaru

Summary

Add an optional page transitions system to Anima, porting the cinematic border-expand animation from the Pile theme. When enabled, internal navigation uses AJAX page loading with a smooth 4-sided border overlay animation (with centered site logo) instead of full page reloads.

Visual Effect

The exact animation from Pile's AjaxLoading.js and loadingAnimation.js, preserved with identical timing, easing, and sequencing:

Page Leave (link clicked)

  1. Border expands inward from all 4 sides (0.6s, Quart.easeInOut)
  2. Nav menu closes, old content fades out (concurrent)
  3. Logo fades in at center of the border overlay

Content Swap (during animation)

  • Barba.js fetches new page via XHR
  • Content injected into data-barba="container"
  • Scroll to top, body classes updated from new page

Page Enter (new page revealed)

  1. Border collapses outward to edges (0.6s, Quart.easeInOut)
  2. Hero content fades in (0.4s, staggered -0.4s overlap)
  3. Hero background scales 1.2→1 (0.4s, staggered)

Total perceived transition: ~1.1s

Initial Page Load

Also plays the Pile-style loading animation: logo fill → background scale → border collapse → hero fade-in. Creates a cinematic "opening curtain" on first visit.

Technology

  • Barba.js v2 — AJAX navigation (successor to Pile's Barba v1). ~7KB gzipped, modern ES modules, built-in cache and prefetch.
  • GSAP — Animation engine (core + ScrollToPlugin). Required to faithfully reproduce Pile's precise easing and timeline orchestration.
  • Both bundled as npm dependencies, tree-shaken, imported only in the page-transitions entry point.

Architecture

Files

src/js/page-transitions.js                    — New webpack entry point
src/js/components/page-transitions/            — JS modules
  ├── index.js                                 — Init/destroy, Barba setup
  ├── transitions.js                           — GSAP timeline definitions (ported from Pile)
  ├── loading-animation.js                     — Initial page load animation
  └── utils.js                                 — Body class sync, admin bar fix, script reinit
src/scss/components/_page-transitions.scss     — Overlay styles + keyframes
inc/integrations/page-transitions.php          — PHP: markup, enqueue, config, exclusions

Zero-footprint when disabled

  • Toggle: Style Manager layout option (enable_page_transitions, default: off)
  • When off: no JS loaded, no CSS loaded, no overlay markup in DOM — identical to the feature not existing
  • When on: PHP outputs border overlay in wp_footer, conditionally enqueues the JS entry point, passes config via wp_localize_script()

Webpack entry point

New entry in webpack.config.js:

'./dist/js/page-transitions': './src/js/page-transitions.js'
'./dist/js/page-transitions.min': './src/js/page-transitions.js'

Loaded independently from scripts.js — only when feature is enabled.

Overlay markup (in wp_footer)

<div class="c-page-transition-border js-page-transition-border"
     style="border-color: var(--sm-current-accent-color); background: var(--sm-current-accent-color);">
  <div class="border-logo-bgscale">
    <div class="border-logo-background">
      <div class="border-logo-fill"></div>
      <div class="logo">{custom-logo}</div>
    </div>
  </div>
  <div class="border-logo">{custom-logo}</div>
</div>

Barba container (wraps page content)

<div data-barba="wrapper">
  <div data-barba="container" data-barba-namespace="<?php echo get_post_type(); ?>">
    <!-- existing page content -->
  </div>
</div>

Configuration

Style Manager toggle

Added in inc/integrations/style-manager/layout.php alongside existing layout options:

  • Field: enable_page_transitions
  • Type: checkbox
  • Label: "Enable page transitions"
  • Default: off (disabled)

Border color

Uses var(--sm-current-accent-color) from Style Manager — always matches the site's palette automatically.

Logo

Uses the WordPress custom-logo (get_custom_logo() / get_theme_mod('custom_logo')). No additional settings needed.

Link Exclusions

All internal links get AJAX navigation except:

Pattern Reason
External links (different hostname) Not same-origin
# anchors Same-page navigation
.pdf, .doc, .zip, .jpg, etc. File downloads
wp-admin, wp-login Admin pages
WooCommerce cart & checkout URLs Transactional pages (need full reload)
?add-to-cart=, ?remove_item Cart actions
Links with target="_blank" New window intent

Exclusions passed to JS via wp_localize_script(), filterable via anima_page_transitions_excluded_urls PHP filter.

WordPress Integration

After each AJAX page load, the system must:

  1. Sync body classes — Parse new page HTML, extract body classes, apply to current DOM
  2. Update admin bar — Fix Edit and Customize links to point to the new page
  3. Update document title — Extract <title> from new page HTML
  4. Re-initialize JS components — Navbar, hero, search overlay, comments area (Anima's existing components)
  5. Re-trigger WooCommerce — Cart widget updates, product gallery init
  6. Fire analytics — Push pageview event for Google Analytics / GTM
  7. Load page-specific assets — Scripts/styles enqueued only on certain pages

Reference

  • Pile theme source: /Users/georgeolaru/Local Sites/barba/app/public/wp-content/themes/pile
  • Key Pile files: assets/js/modules/AjaxLoading.js, assets/js/modules/loadingAnimation.js, assets/scss/components/_loading.scss
  • Barba.js v2 docs: https://barba.js.org/
  • GSAP docs: https://gsap.com/docs/v3/

Sub-issues

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions