Skip to content
back

Reveal

Import Reveal from @waaark/luge, register it with luge.addPlugin('reveal', Reveal), then call luge.init(). See Getting started for a complete setup.

Reveals elements when they get in or out the viewport.

Usage

<div class="my-element" data-lg-reveal></div>
<div class="my-element" data-lg-reveal="fade"></div>
<div class="my-element" data-lg-reveal="my-reveal"></div>

You can use built-in animations or create your own ones.

When multiple elements get in the viewport at the same time, their reveal animations will be staggered with a 0.1 second delay (see attributes).

Built-in animations

  • fade|fade-to-top|fade-to-right|fade-to-bottom|fade-to-left|fade-x|fade-y
  • fade-rotate|fade-rotate-to-top|fade-rotate-to-right|fade-rotate-to-bottom|fade-rotate-to-left|fade-rotate-x|fade-rotate-y
  • fade-scale|fade-scale-to-top|fade-scale-to-right|fade-scale-to-bottom|fade-scale-to-left|fade-scale-x|fade-scale-y
  • scale|scale-to-top|scale-to-right|scale-to-bottom|scale-to-left|scale-x|scale-y
  • slide|slide-to-top|slide-to-right|slide-to-bottom|slide-to-left|slide-x|slide-y
  • layer-to-top | layer-to-right | layer-to-bottom | layer-to-left

Custom animations

The revealed element gets a .lg-reveal and a.lg-reveal—[reveal name] CSS classes when initiated. It also gets .is-in, .is-out, .is-out-top, .is-out-bottom CSS classes when it gets in or out the viewport.

You can use these to create the reveal animation in CSS:

.lg-reveal--my-reveal {
  opacity: 0;
  transition: opacity 0.3s linear, transform 0.3s ease-in-out;

  &.is-out-bottom {
    transform: translate3d(0, 10px, 0);
  }
  &.is-out-top {
    transform: translate3d(0, -10px, 0);
  }
  &.is-in {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

Or you can use a third-party JS animation library:

// Add a callback function
luge.reveal.add('in', 'myReveal', (element) => {
  // When the element gets in viewport
  gsap.to(element, { opacity: 1, duration: 0.4 })
})
luge.reveal.add('out', 'myReveal', (element) => {
  // When the element gets out of viewport
  gsap.to(element, { opacity: 0, duration: 0.4 })
})
// Or attach the function to the element onrevealin and onrevealout properties
document.querySelector('.my-element').onrevealin = function () { gsap.to(this, { opacity: 1, duration: 0.4 }) }
document.querySelector('.my-element').onrevealout = function () { gsap.to(this, { opacity: 0, duration: 0.4 }) }

Staggered reveals

You can set up staggered reveal animations on children elements to reveal them with a staggered start time:

<div class="my-parent" data-lg-reveal="fade" data-lg-reveal-stagger="0.1">
  <div class="my-child"></div>
  <div class="my-child"></div>
  <div class="my-child"></div>
</div>

When the parent element gets in the viewport, each child will be revealed with the fadeanimation and a 0.1 second delay.

You can also use different reveal animations for each child:

<div class="my-parent" data-lg-reveal data-lg-reveal-stagger="0.1">
  <div class="my-child" data-lg-reveal="fade"></div>
  <div class="my-child" data-lg-reveal="fade-to-left"></div>
  <div class="my-child" data-lg-reveal="fade-to-right"></div>
</div>

Manual reveals

Sometimes it can be useful to trigger reveal animations manually, to group them in a larger animation sequence. You can do so by adding the data-lg-reveal-manual attribute to the element.

Reveal animation can then be triggered manually:

// Reveal in animation
document.querySelector('.my-element').luge.reveal.in()
// Reveal out animation
document.querySelector('.my-element').luge.reveal.out()

Attributes

AttributeTypeDefaultDescription
data-lg-revealStringunsetThe reveal animation name. Set it to one of the built-in animations name or create your own one.
data-lg-reveal-disableStringunsetDisable this element on desktop, tablet, mobile, or handheld. Requires the Browser plugin.
data-lg-reveal-multipleBooleanfalseWhether the element should be revealed in and out when it gets back in or out of the viewport.
data-lg-reveal-staggerNumberdisabled when absentEnables child staggering. Its value is the interval in seconds; an empty attribute uses reveal.stagger (default 0.1). Without this attribute, the element itself is revealed.
data-lg-reveal-delayNumber0The delay (in second) before the reveal animation starts when the element gets in the viewport.
data-lg-reveal-manualBooleanfalseDisable automated reveal on scroll and enable manual triggering.

Callback behavior

Set luge.settings({ reveal: { threshold: 0.15, stagger: 0.1 } }) before initialization to change the automatic progress threshold and spacing between elements in a reveal batch. The threshold is a fraction of the element’s scroll progress, not an IntersectionObserver visibility ratio.

data-lg-reveal-manual skips automatic scroll observation. Call element.luge.reveal.in() and .out() after initialization. Both dispatch reveal events and invoke custom callbacks. data-lg-reveal-delay is in seconds. Named callbacks take precedence over element onrevealin / onrevealout handlers.

Within an automatic reveal batch, element delays accumulate along with the global stagger. A staggered group’s children start at intervals relative to their parent’s reveal. Page cleanup cancels pending reveal delays and remaining child callbacks, so they cannot run on a departed page. Custom callbacks remain responsible for cancelling animations or timers they start themselves.

The element emits non-bubbling revealin and revealout events. Reveal callbacks do not receive a done argument and do not hold the lifecycle until their animations finish. Manual .in() and .out() calls act immediately on that element; they do not apply automatic delays or run the staggered-child scheduling path.

Try it

Open the full demo