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 theaos-animateclass that stylesheet waits for. - The default motion is newer. One
initcall 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-aosanimation names andAOS.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 atopacity: 0. - Match the old motion, or take the newer one. One
initcall 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)
<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)
<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>Delete the
aos.csslink and theaos.jsscript, including any copy you bundled yourself.Add the script above at the end of
<body>, whereaos.jswas. To drop the inline call, putdata-auto deferon the script tag instead ofAOS.init().Leave every
data-aosattribute. Options you pass toAOS.init()that Ghost Reveal understands still apply. Options it does not understand are ignored. They do not throw.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-aoswith the animation names belowdata-aos-duration,data-aos-delay,data-aos-easing,data-aos-offset,data-aos-once, anddata-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(), andAOS.destroy()- The same object is
window.GhostReveal.refreshHardisrefresh: 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-, andease-in-out-.ease-out-cubicis 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.
| Setting | AOS 2.3 | Ghost Reveal | To match AOS |
|---|---|---|---|
once | false | true | once: false |
offset | 120 | 60 | offset: 120 |
duration | 400 | 700 | duration: 400 |
| easing | ease | cubic-bezier(.16,1,.3,1) | easing: 'ease' |
| Travel | 100px | 16px | distance: 100 |
blur | none | 4px | blur: 0 |
| Already on screen | animated | shown as-is | initial: 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.
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.
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: falseresets instantly off screen.data-reveal-scrubis the reversible option.startEvent. Callinit()when you are ready, or usedata-autoon the script tag.throttleDelayanddebounceDelay. Ghost Reveal uses IntersectionObserver, not a scroll listener, so those knobs do not apply.useClassNames,animatedClassName, and CSS aimed at.aos-animateor.aos-init. Usereveal:inandreveal:out.data-aos-anchor. The trigger is the element itself. A different anchor element is not read.data-aos-id. Use a normalid.disable: 'phone'anddisable: 'tablet'. Use'mobile'(under 768px) or a function.disableis checked again onrefresh().- 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, andfade-down-left. The last direction is the one that plays, sofade-up-rightruns asfade-right. Pickfade-uporfade-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.
npm uninstall aos
npm install ghost-revealimport { 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 (
initialdefaults 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.cssis still loading, or your CSS setsopacity: 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 adddefer. - One name looks wrong. Check the diagonal fades and the
*-topplacements in the list above. - New content never reveals. Elements added later are found automatically. If you add
data-aosto a node that was already on the page, callAOS.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.