Slide-element - A ~700 byte Promise-based library for animating elements with dynamic heights open & closed. Basically, a modern variant of jQuery's slideUp(), slideDown(), and slideToggle().

Overview

slide-element

Bundle Size

A tiny, accessible, Promise-based, jQuery-reminiscent library for sliding elements with dynamic heights open & closed.

To see it in action, check out the following demos:

Why?

Using JavaScript to animate an element open and closed hasn't traditionally been a straightforward task, especially if it contains dynamically sized content. You could go with something like jQuery's slideToggle(), but that path would require you to take on a lot more code than necessary. Another option is using CSS to change the max-height value of an element, but this approach is filled with arbitrariness and difficult to pull off well when you're not sure how much content you'll be animating over.

This library gets the job done using the Web Animations API, and it doesn't require elements to have fixed heights. Instead, element heights are calculated based on their contents, and then the appropriate values are applied to trigger a smooth, native transition. The animations themselves are powered by the same mechanics used within CSS transitions, making it one of the best ways to pull it off in terms of performance.

It's small, smooth, and focuses on doing one job well: sliding stuff open and closed.

Installation

Run npm install slide-element, or use a CDN like unpkg.

Setup

Make sure your target element is set to display: none;.

Usage

Toggling Elements

Use the toggle function to slide an element open & closed based on its current state.

import { toggle } from "slide-element";

document.getElementById("button").addEventListener("click", (e) => {
  toggle(document.getElementById("box"));
});

Sliding Elements Down

Use the down function to slide an element open.

import { down } from "slide-element";

document.getElementById("button").addEventListener("click", (e) => {
  down(document.getElementById("boxToSlideOpen"));
});

Sliding Elements Up

Use the up function to slide an element closed, and then set its display property to none.

import { up } from "slide-element";

document.getElementById("button").addEventListener("click", (e) => {
  up(document.getElementById("boxToSlideClosed"));
});

Everything's a Promise

Each of the functions provided return promises, so you can easily wait to perform an action after an animation is complete. The resolved value will indicate if the element has just been opened (true), closed (false), or the result of an animation that interruped another (see more below).

import { toggle } from "slide-element";

document.getElementById("button").addEventListener("click", (e) => {
  toggle(document.getElementById("someElement")).then((isOpen: boolean | null) => {
    console.log("Toggling is done!");
  });
});

Interrupting In-Progress Animations

Depending on your settings, some users may be able to repeatedly trigger a new before a previous one has been allowed to finish, which will cause the in-progress animation instantly finish before the new one can begin.

When this occurs, the isOpen Promise that resolves after the animation is complete will return null for each animation that was triggered in interruption of the first. The initial animation, however will still resolve to the correct value. For example, pretend the following animation is clicked rapidly three times in a row.

import { toggle } from "slide-element";

document.getElementById("button").addEventListener("click", (e) => {
  toggle(document.getElementById("someElement")).then((isOpen: boolean | null) => {
    console.log(isOpen);
  });
});

When the animation has been allowed to complete, the following values will be logged -- two null values for the interrupting animations, and one boolean for the initial (and now complete) one. The point here is that it may be necessary to explicitly check for a non-null value when using the resolved "open" state.

true
null
null

Animating Boxes with Padding

If the element you're animating has any padding set to it, be sure to also apply box-sizing: border-box as well. If you don't, the resulting animation will be weird and jumpy.

<div id="myTarget" style="padding: 1rem; box-sizing: border-box; display: none;">
  My contents!
</div>

Customizing the Animation

By default, slide-element uses the following transition property values:

Property Value
duration (in milliseconds) 250
easing (choose one) ease

You can override these by passing an object as the seceond parameter of any method:

up(document.getElementById("element"), {
  duration: 500,
  easing: "ease-in-out",
});

Customizing the Opened display Value

Out of the box, slide-element will set your opened element to display: block;. If you'd like to customize this, pass a display value as an option:

down(document.getElementById("element"), {
  display: "flex"
});

Usage w/o a Bundler

If you'd like to use slide-element directly in the browser via CDN, simply load the code, and then reference the function you'd like to use on the global SlideElement object:

<script src="./path/to/slide-element.js"></script>
<script>
  document.getElementById('someElement').addEventListener('click', (e) => {
    SlideElement.toggle(document.getElementById("someBox"));
});
</script>

API

// Toggle an element based on current state.
toggle(element: HTMLElement, options?: object): Promise<boolean>

// Slide an element down.
up(element: HTMLElement, options?: object): Promise<boolean>

// Slide an element down.
down(element: HTMLElement, options?: object): Promise<boolean>
Param Type Description
node Node A single HTML node to be slid open or closed
options object Options to customize sliding animation.

Accessibility

This library will respect the prefers-reduced-motion setting on a user's machine. When it's set to reduce, the sliding animation will be forced to a duration of 0, making the respective elements open and close instantly.

Additionally, it's highly recommended that you toggle the aria-expanded attribute on any element (like a button) that's responsible for triggering an animation. This can be done by adding a single line of code that fires afters an animation is complete:

document.getElementById('someButton').addEventListener('click', (e) => {
    toggle(document.getElementById('thing2')).then((opened) => {

      <!-- Set the appropriate `aria-expanded` value based on the state of the container. -->
      e.target.setAttribute("aria-expanded", opened);
    });
  });

Show Off Your Use Case

I love to see examples of how you're using the stuff I build. If you're comfortable, please send it my way!

Comments
  • It doesn't slide, it only shows/hides the element

    It doesn't slide, it only shows/hides the element

    I just checked the landing page (https://alexmacarthur.github.io/slide-element/) and it doesn't work? It just shows or hides the target element, no slide effect applied. Tested on Chtome and Firefox on Windows 10, latest versions.

    opened by LuBreGit 9
  • Height issue

    Height issue

    Proposed Feature or Bug

    When the content inside wrapper is updated and height is changed, the height is not updated. I think it would be better to add height: auto, once the wrapper is fully open. And upon closing update the height again?

    opened by lubomirblazekcz 6
  • Feature: allow the `overflow` property to be given by the user

    Feature: allow the `overflow` property to be given by the user

    Proposed Feature or Bug

    This would be similar to the display property (which is block by default, but can be overriden by the user using the options).

    In practice it would useful to be able to specify overflow: hidden to avoid having that temporary scrollbar while the element is being shown (which causes a unpleasant jump in the text at the beginning / end of the animation).

    opened by paulovieira 5
  • temporarily set overflow to hidden instead of auto

    temporarily set overflow to hidden instead of auto

    Description of Proposed Changes

    As discussed in https://github.com/alexmacarthur/slide-element/issues/29 setting the overflow value to "auto" during the animation causes a scrollbar to appear for the duration of the animation which seems to be counter to this library's goal.

    Related Issue (if applicable)

    https://github.com/alexmacarthur/slide-element/issues/29

    Testing Steps

    Animate a large element with this library at a slow speed and you will see a scrollbar appear on the edge of the element as it animates. After applying this patch that scrollbar should no longer appear.

    opened by darvanen 3
  • set default display

    set default display

    https://github.com/alexmacarthur/slide-element/blob/master/src/index.ts#L95

    It needs to get default display value before set display.

    // get default display
    const defaultDisplay = window.getComputedStyle && window.getComputedStyle(element).display || 'block'
    
    setDisplay(defaultDisplay)
    
    opened by Rabbitzzc 3
  • Handle reduced motion

    Handle reduced motion

    This library currently doesn't respect reduced motion requests, thus throwing animations to people who explicitly requested to not get any (e.g. due to motion sickness).

    It would be good if it could disable itself.

    opened by Arteneko 2
  • Ensure callback fires only after animation is finished.

    Ensure callback fires only after animation is finished.

    Description of Proposed Changes

    Due to poor Promise handling, the callback function passed to slide-element was firing without waiting for animations to fully complete.

    opened by alexmacarthur 1
  • Fix accessibility

    Fix accessibility

    Description of Proposed Changes

    No longer sets aria-expanded on the element that's sliding open or closed, since it's supposed to be used on the element that triggered the animation:

    https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded

    Related Issue (if applicable)

    #24

    opened by alexmacarthur 1
  • Overflow bug

    Overflow bug

    Description of Proposed Changes

    When particular items (like pre tags) were contained within an element sliding open & closed, Safari allowed the contents to bleed out of the container on animation.

    This is fixed by explicitly setting an overflow property when an animation is executed.

    opened by alexmacarthur 1
  • Enable fluid height and other improvements

    Enable fluid height and other improvements

    Description of Proposed Changes

    • Adds support for dynamic height + padding values (thx, @lubomirblazekcz!)
    • Removes window variable height caching (and simplifies some other related bits of code as a result).

    Related Issue (if applicable)

    #19

    opened by alexmacarthur 1
  • Support for dynamic heights and paddings

    Support for dynamic heights and paddings

    Description of Proposed Changes

    Hey @alexmacarthur I've resolved the problems when height is dynamicly changed, I've changed fill from forwards to backwards, this way the style properties will reset upon animation, so there are no more problems with height. Also added new option cache, if someone expect the height to change in the future it should be disabled. To be honest caching the height isn't the best approach, height can change anytime, eg. responsive design. Maybe you should reconsider if not to remove the caching instead?

    I've also resolved the gotha with the padding as bonus https://github.com/alexmacarthur/slide-element#gotchas but the box-sizing: border-box must be use for this to work.

    Related Issue (if applicable)

    #19

    Testing Steps

    Didn't add tests or changed the version, leaving that up to you :)

    opened by lubomirblazekcz 1
Releases(v2.3.1)
  • v2.3.1(Dec 11, 2022)

  • v2.3.0(Jun 29, 2022)

    Introduces an overflow option that can be used to customize the value applied to an element during an animation. Ex:

    down(document.getElementById("element"), {
      overflow: "auto"
    });
    
    Source code(tar.gz)
    Source code(zip)
  • v2.2.7(Jun 29, 2022)

  • v2.2.6(Jan 27, 2022)

  • v2.2.3(Nov 15, 2021)

    When particular contents (like pre tags) were contained within a sliding element, Safari saw an issue where the contents would bleed outside of the element during animation.

    This was fixed by explicitly setting the overflow value to auto during an animation.

    Source code(tar.gz)
    Source code(zip)
  • v2.2.2(Nov 14, 2021)

    • allows for dynamic height values (useful in cases where items within the element are inserted, removed, or resized between animations).
    • allows for elements to have their padding values animated
    Source code(tar.gz)
    Source code(zip)
  • v2.2.1(Oct 5, 2021)

    Changes the library from using a Map() to store expanded height values, in favor of a WeakMap, for an ultra-small performance optimization.

    Source code(tar.gz)
    Source code(zip)
  • v2.2.0(Jul 13, 2021)

  • v2.1.0(Jul 11, 2021)

    • Addresses a bug that would occur when a user would rapidly trigger an animation without letting an in-progress one finish.
    • Respects prefers-reduced-motion setting on a user's machine.
    Source code(tar.gz)
    Source code(zip)
  • v2.0.1(Jul 8, 2021)

    For some contents, if the overflow wasn't set to hidden while animating, the contents were bleeding outside of the box. This change explicitly sets the correct overflow value to prevent this from happening.

    Source code(tar.gz)
    Source code(zip)
  • v2.0.0(Jul 8, 2021)

  • v1.1.2(Jun 13, 2021)

    Made some small tweaks to shave off even more bytes:

    • Remove unnecessary async/await code.
    • Switch to a different looping mechanism somewhere.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Jun 11, 2021)

  • v1.1.0(May 30, 2021)

    Two improvements were made:

    • event handling was slimmed down a bit, cutting a few more bytes out of the package.
    • A custom display value can now be passed, which will be applied when an element has been slid open.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Apr 29, 2021)

  • v1.0.1(Apr 29, 2021)

    It's possible to have multiple instances on a page that had different settings. With the way the library was configured, state changes in one of those instances could have impacted others. This release more appropriate scopes each instance, preventing potential problems.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Apr 27, 2021)

  • v0.2.1(Nov 9, 2020)

  • v0.2.0(Nov 9, 2020)

    In the Promise that's returned when the utility slides open or closed, the state of the element is indicated by the resolved boolean.

    Ex:

    toggle(document.getElementById('thing')).then(isOpened => {
        console.log(isOpened); // true or false
    });
    
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1(Nov 9, 2020)

Owner
Alex MacArthur
Most exceptional Enneagram #3.
Alex MacArthur
It's a presentation framework based on the power of CSS3 transforms and transitions in modern browsers and inspired by the idea behind prezi.com.

impress.js It's a presentation framework based on the power of CSS3 transforms and transitions in modern browsers and inspired by the idea behind prez

impress.js 37k Jan 2, 2023
Javascript library to create physics-based animations

Dynamics.js Dynamics.js is a JavaScript library to create physics-based animations To see some demos, check out dynamicsjs.com. Usage Download: GitHub

Michael Villar 7.5k Jan 6, 2023
Create scroll-based animation without JavaScript

Trigger JS Create scroll-based animation without JavaScript. Sometimes we want to update the CSS style of an HTML element based on the scroll position

Trigger JS 1.1k Jan 4, 2023
Javascript and SVG odometer effect library with motion blur

SVG library for transitioning numbers with motion blur JavaScript odometer or slot machine effect library for smoothly transitioning numbers with moti

Mike Skowronek 793 Dec 27, 2022
🐿 Super easy and lightweight(<3kb) JavaScript animation library

Overview AniX - A super easy and lightweight javascript animation library. AniX is a lightweight and easy-to-use animation library with excellent perf

anonymous namespace 256 Sep 19, 2022
:dizzy: TransitionEnd is an agnostic and cross-browser library to work with transitionend event.

TransitionEnd TransitionEnd is an agnostic and cross-browser library to work with event transitionend. Browser Support 1.0+ ✔ 4.0+ ✔ 10+ ✔ 10.5 ✔ 3.2+

Evandro Leopoldino Gonçalves 95 Dec 21, 2022
Slickscroll - A Lightweight JavaScript library for quick and painless momentum & parallax scrolling effects.

Slickscroll is a JavaScript library that makes momentum & parallax scrolling quick and painless View Demo: slickscroll.musabhassan.com Momentum Scroll

Musab Hassan 33 Dec 28, 2022
Animate Plus is a JavaScript animation library focusing on performance and authoring flexibility

Animate Plus Animate Plus is a JavaScript animation library focusing on performance and authoring flexibility. It aims to deliver a steady 60 FPS and

Benjamin De Cock 5.9k Jan 2, 2023
🍿 A cross-browser library of CSS animations. As easy to use as an easy thing.

Animate.css If you need the old docs - v3.x.x and under - you can find it here. Just-add-water CSS animation Installation Install with npm: npm instal

Animate.css 76.7k Dec 30, 2022
A lightweight JavaScript library for creating particles

particles.js A lightweight JavaScript library for creating particles. Demo / Generator Configure, export, and share your particles.js configuration on

Vincent Garreau 26.7k Jan 8, 2023
GreenSock's GSAP JavaScript animation library (including Draggable).

GSAP (GreenSock Animation Platform) Professional-grade animation for the modern web GSAP is a robust JavaScript toolset that turns developers into ani

GreenSock 15.5k Jan 8, 2023
Animation library that mimics CSS keyframes when scrolling.

Why Motus ? Motus allows developers to create beatuful animations that simulate css keyframes and are applied when the user scrolls. Features Node & B

Alexandru Cambose 580 Dec 30, 2022
GreenSock's GSAP JavaScript animation library (including Draggable).

GSAP (GreenSock Animation Platform) Professional-grade animation for the modern web GSAP is a robust JavaScript toolset that turns developers into ani

GreenSock 15.4k Jan 5, 2023
🍿 A cross-browser library of CSS animations. As easy to use as an easy thing.

Animate.css If you need the old docs - v3.x.x and under - you can find it here. Just-add-water CSS animation Installation Install with npm: npm instal

Animate.css 76.7k Jan 4, 2023
A library to add a virtual Trackball to your DOM

Trackball.js - 3D Trackballs for your Website Trackball.js is a small JavaScript library on top of Quaternion.js to enable free 3D rotation of element

Robert Eisele 34 Nov 27, 2022
Theatre.js is an animation library for high-fidelity motion graphics.

Theatre.js is an animation library for high-fidelity motion graphics. It is designed to help you express detailed animation, enabling you to create intricate movement, and convey nuance.

Aria 8.6k Jan 3, 2023
simple JavaScript library to animate texts

Animated Texts Hi, this library is a simple javascript text animator Properties force type: number default: 300 start_delay_time type: number default:

Cristóvão 4 Jan 11, 2022
Tiny ANSI terminal coloring library

felt-pen Tiny ANSI terminal coloring library Benchmarks Calling chalk 1,192,251 ops/sec cli-color 130,947 ops/sec ansi-colors 683

nin-jin 15 Aug 7, 2022
Nebula is a lightweight (1kb compressed) JavaScript library that creates beautiful universe animations.

Nebula is a lightweight JavaScript library for creating beautiful universe animations. Including configurable Stars, Nebulas, Comets, Planets and Suns. Compatible with SSR

Florian DE LA COMBLE 34 Nov 25, 2022