Migration

Migrate from AOS

Ghost Reveal is a maintained scroll-reveal library, and it is how you leave AOS. Delete aos.css and aos.js, load one script, and keep your data-aos markup and AOS.init() call.

  • Markup stays. Names, durations, delays, easings, offsets, and anchor placements you already set on an element keep working.
  • Delete aos.css. Leaving it in place hides elements. Ghost Reveal never adds the aos-animate class that stylesheet waits for.
  • The default motion is newer. One init call restores the AOS timing and distance when you want that look back.
On this page

Why move off AOS #

AOS 2.3.4 was the last release, in October 2018. It needs aos.css and depends on lodash packages. Ghost Reveal is the scroll-reveal library to move to: about 2 KB, no stylesheet, and no dependencies. If you want a maintained AOS alternative, you do not have to rewrite the page.

  • No rewrite. data-aos animation names and AOS.init() stay. You swap two files, not your templates.
  • Content stays visible if JavaScript never runs. Ghost Reveal ships no CSS. Delete aos.css, or it can leave elements at opacity: 0.
  • Match the old motion, or take the newer one. One init call restores the AOS timing and distance. Otherwise you get a 16px blur-fade over 700ms.

Swap the files #

Remove the AOS stylesheet and script. Add the Ghost Reveal script-tag build. It sets window.AOS when that name is free, so the call you already have keeps working. Remove aos.js first. If another script already owns window.AOS, Ghost Reveal leaves that name alone.

Before (AOS)

AOS
<link rel="stylesheet" href="https://unpkg.com/aos@2.3.4/dist/aos.css">
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
<script>AOS.init();</script>

<div data-aos="fade-up" data-aos-duration="800">…</div>

After (Ghost Reveal)

Ghost Reveal
<script src="https://unpkg.com/ghost-reveal@0.2/dist/ghost-reveal.umd.min.js"></script>
<script>AOS.init();</script>

<div data-aos="fade-up" data-aos-duration="800">…</div>
  1. Delete the aos.css link and the aos.js script, including any copy you bundled yourself.

  2. Add the script above at the end of <body>, where aos.js was. To drop the inline call, put data-auto defer on the script tag instead of AOS.init().

  3. Leave every data-aos attribute. Options you pass to AOS.init() that Ghost Reveal understands still apply. Options it does not understand are ignored. They do not throw.

  4. Search your CSS for opacity: 0, visibility: hidden, .aos-init, and .aos-animate. Remove rules that only hid elements until AOS ran.

Do not keep aos.css. That file sets opacity: 0 on [data-aos] and reveals them only after an aos-animate class is added. Ghost Reveal never adds that class, so the old stylesheet would leave elements invisible.

What you keep #

These names work unchanged on the script-tag build.

Attributes #

  • data-aos with the animation names below
  • data-aos-duration, data-aos-delay, data-aos-easing, data-aos-offset, data-aos-once, and data-aos-anchor-placement

Each of those also has a data-reveal-* spelling. When both are set on one element, data-reveal-* wins. data-reveal-stagger is extra, and it has no data-aos form. Put it on the parent. A value of 80 is the step in milliseconds. An empty value uses 80.

A value you set on the element beats the default and beats AOS.init({ … }). data-aos-duration="800" is still 800ms.

Animation names #

fade, fade-up, fade-down, fade-left, fade-right, zoom-in, zoom-out, zoom-in-up, zoom-in-down, zoom-in-left, zoom-in-right, zoom-out-up, zoom-out-down, zoom-out-left, zoom-out-right, slide-up, slide-down, slide-left, slide-right, flip-up, flip-down, flip-left, flip-right.

fade-up still means the element moves up into place. It starts lower. Try a name on the playground before you commit to it. The preview uses the keyframes that ship.

JavaScript #

  • AOS.init(), AOS.refresh(), AOS.refreshHard(), and AOS.destroy()
  • The same object is window.GhostReveal. refreshHard is refresh: it picks up new elements and re-reads attributes.
  • AOS easing names, registered for you in this build: back, sine, quad, cubic, and quart, each as ease-in-, ease-out-, and ease-in-out-. ease-out-cubic is one of them.

CSS easing keywords such as ease and ease-in-out work as written. A name Ghost Reveal does not know falls back to linear.

Defaults that change #

Anything you already set on an element stays. What changes is the value used when you set nothing. Ghost Reveal's own default is a 16px blur-fade on an expo-out curve, over 700ms. Slides fade as they move. AOS did not blur, traveled farther, and replayed when you scrolled back.

AOS 2.3 defaults next to Ghost Reveal, and the init value that matches AOS
SettingAOS 2.3Ghost RevealTo match AOS
oncefalsetrueonce: false
offset12060offset: 120
duration400700duration: 400
easingeasecubic-bezier(.16,1,.3,1)easing: 'ease'
Travel100px16pxdistance: 100
blurnone4pxblur: 0
Already on screenanimatedshown as-isinitial: true

Anchor placement still defaults to top-bottom. Delay still defaults to 0. Travel in that table is the fade and directed-zoom distance. Slides still move by their own size. They also fade, which AOS slides did not.

Match the AOS look #

Pass this once. Per-element data-aos-* values still override it.

Match the AOS look
AOS.init({ blur: 0, duration: 400, easing: 'ease', distance: 100, offset: 120, once: false });

Above the fold #

Elements already visible when init() runs are shown as they are, so the first screen does not animate or shift. AOS animated them. Pass initial: true when you want that. Start the script after the HTML is parsed: end of <body>, or defer. If init() runs in <head> before the body exists, the first screen animates too, because those elements look newly added.

Scrolling back up #

AOS's default once: false replayed elements, and mirror could animate them back out. Ghost Reveal's default plays once. With once: false, an element resets the moment it is fully off screen. There is no mirrored exit. For motion that follows the scroll position in both directions, add data-reveal-scrub on the element. That mode is experimental. It uses the browser's own scroll timeline where that exists, and falls back to a normal reveal otherwise. The scrub section has the support notes.

Classes and events #

There is no aos-init class and no aos-animate class, and no inline style is written. The waiting state is a held animation, cancelled when the element reveals, so nothing is left behind. Listen for reveal:in and reveal:out instead. Both bubble, so a listener on document is enough. reveal:out fires when a once: false element resets.

Events
document.addEventListener('reveal:in', (event) => {
  console.log(event.target);
});

What does not carry over #

Read this before you switch. If the page depends on one of these, it needs a small change. Everything else can stay.

  • mirror. There is no reverse animation. once: false resets instantly off screen. data-reveal-scrub is the reversible option.
  • startEvent. Call init() when you are ready, or use data-auto on the script tag.
  • throttleDelay and debounceDelay. Ghost Reveal uses IntersectionObserver, not a scroll listener, so those knobs do not apply.
  • useClassNames, animatedClassName, and CSS aimed at .aos-animate or .aos-init. Use reveal:in and reveal:out.
  • data-aos-anchor. The trigger is the element itself. A different anchor element is not read.
  • data-aos-id. Use a normal id.
  • disable: 'phone' and disable: 'tablet'. Use 'mobile' (under 768px) or a function. disable is checked again on refresh().
  • Placements that end in -top (top-top, center-top, bottom-top) behave like the same word ending in -bottom. These still work as themselves: top-bottom, center-bottom, bottom-bottom, top-center, center-center, bottom-center.
  • Diagonal fades: fade-up-right, fade-up-left, fade-down-right, and fade-down-left. The last direction is the one that plays, so fade-up-right runs as fade-right. Pick fade-up or fade-right.

npm, modules, and frameworks #

Uninstall aos and install ghost-reveal. The core module leaves the AOS easing names out (310 bytes gzipped). Register them before init() when your markup uses names such as ease-out-cubic. The script-tag build already includes them, so this step is only for modules.

Terminal
npm uninstall aos
npm install ghost-reveal
Register AOS easings
import { init, easings } from 'ghost-reveal';
import aosEasings from 'ghost-reveal/aos-easings';

Object.assign(easings, aosEasings);
init();

When you do not use those names, import { init } from 'ghost-reveal' and init() are enough. ease and other CSS easing keywords need no add-on.

In React, Vue, Svelte, and the other frameworks, keep calling init once on the client, the way you called AOS.init() in useEffect, onMounted, or a client plugin. init() does nothing when there is no document, so a server render can import the module. The DOM is watched by default, which covers route changes. Return destroy() from the effect when the component that starts it can unmount. The framework guides have a recipe for each setup, including WordPress.

In JSX, data-aos="fade-up" is unchanged. A bare data-reveal becomes the string "true", which still means the default animation.

After you switch #

  • Elements appear and never move. They may already be on screen (initial defaults to false), or the device may have reduced motion turned on. Scroll to something lower on the page. Reduced motion shows content immediately, and Ghost Reveal follows that setting if it changes while the page is open.
  • Elements stay invisible. aos.css is still loading, or your CSS sets opacity: 0. Remove both. Ghost Reveal hides an element only after it has started. If the script never runs, the page stays readable.
  • The first screen animates or flashes. init() ran before the body existed. Move the script to the end of <body> or add defer.
  • One name looks wrong. Check the diagonal fades and the *-top placements in the list above.
  • New content never reveals. Elements added later are found automatically. If you add data-aos to a node that was already on the page, call AOS.refresh().

The docs list every attribute and option. The short AOS note there points back here.

Questions about leaving AOS #

These are the questions people ask when they search for a way to migrate from AOS. The sections above have the steps.

How do I migrate from AOS to Ghost Reveal? #

Remove aos.css and aos.js, add the Ghost Reveal script, and keep AOS.init(). The file swap is the whole migration for most pages. Your data-aos attributes stay.

Is Ghost Reveal an AOS alternative? #

Yes, for scroll reveals. It is maintained, about 2 KB, and it has no CSS file and no dependencies. AOS 2.3.4 last shipped in October 2018. The same data-aos names run, so this is a file swap rather than a rewrite.

Can I keep data-aos and AOS.init()? #

Yes. The script-tag build sets window.AOS when that name is free. What you keep lists the attributes, animation names, and easing curves that carry over.

Should I leave aos.css in place? #

No. That stylesheet hides [data-aos] until an aos-animate class is added. Ghost Reveal never adds that class, so the old CSS would leave elements invisible.

Can the animation still look like AOS? #

Yes. Pass blur: 0, duration: 400, easing: 'ease', distance: 100, offset: 120, and once: false to AOS.init(). Copy the match snippet. A data-aos-* value on the element still wins.

What AOS features will not come along? #

mirror, a different anchor element, disable: 'phone' or 'tablet', and diagonal fades such as fade-up-right. Read the full list before you switch. Everything else can stay.