Skip to content

Search htmltool.io

Search animations, patterns and icons

Docs · Animations · v1.0.0

Animations

1,510 CSS animations, one file each. Link the one you need, add its class, and tune the timing with custom properties.

Link one animation

Every animation has its own minified stylesheet at css/animations/<slug>.min.css. The slug is the kebab-case name, so Slide In Up · Far · Spring becomes slide-in-up-far-spring.

index.html
<link rel="stylesheet" href="https://cdn.htmltool.io/animations/1.0.0/css/animations/fade-in-up.min.css">

<h1 class="da-fade-in-up">Hello</h1>

Prefer CSS imports? The same file works from a stylesheet:

styles.css
@import url("https://cdn.htmltool.io/animations/1.0.0/css/animations/fade-in-up.min.css");

Category bundles live at css/categories/<category>.min.css, for example:

https://cdn.htmltool.io/animations/1.0.0/css/categories/entrances.min.css
Never load the full bundle on production pages
css/devops-animations.min.css contains all 1,510 animations. It is handy for prototyping, but on a real page link only the animations you use, or one category at most.
Animation categories
CategorySlugCount
Entrancesentrances444
Exitsexits280
Attentionattention195
Loadersloaders118
Texttext95
Hoverhover103
Backgroundsbackgrounds63
3D3d44
Pathspaths72
Colorscolors58
Sequencessequences38

Class names

The class and the keyframes share one name: da-<slug>. Add the class and the animation plays once the stylesheet has loaded.

  • Hover animations (the Hover category and anything tagged hover) run on :hover, or while the element also has the da-active class.
  • Custom subjects such as loaders, 3D cards and text effects need their own markup. Copy it from the detail page or the html field in index.json. Part classes are namespaced da-<slug>__<part>.
spinner-ring.html
<link rel="stylesheet" href="https://cdn.htmltool.io/animations/1.0.0/css/animations/spinner-ring.min.css">

<div class="da-spinner-ring__ring da-spinner-ring"></div>

Timing with custom properties

Override timing per element, or on any ancestor to cover a whole section. The values from the gallery are the fallbacks.

Animation custom properties
PropertyAcceptsExample
--da-durationAny CSS time1.2s
--da-delayAny CSS time200ms
--da-easingAny timing functionease-out
--da-iterationsA number or infinite2
--da-directionnormal, reverse, alternate, alternate-reversealternate
--da-fill-modenone, forwards, backwards, bothboth
styles.css
.hero {
  --da-duration: 1.2s;
  --da-delay: 200ms;
  --da-easing: ease-out;
  --da-iterations: 2;
  --da-direction: alternate;
  --da-fill-mode: both;
}

SCSS, Stylus, Sass and Less

Each partial has the keyframes, a mixin and, by default, the class. Mixin arguments become the fallbacks of the --da-* properties. Preprocessors can't import over HTTP, so download the folder (or the whole version) and add it to your load paths.

styles.scss
// optional, must come first: keyframes + mixins only, no .da-* classes
@use "devops-animations/scss/config" with ($emit-classes: false);

@use "devops-animations/scss/animations/fade-in-up" as fade;
.card { @include fade.da-fade-in-up($duration: 1s, $delay: 100ms); }

The source files for one animation, if you want to vendor just that:

https://cdn.htmltool.io/animations/1.0.0/scss/animations/_fade-in-up.scss
https://cdn.htmltool.io/animations/1.0.0/styl/animations/fade-in-up.styl

ES module

animate(el, name, opts) plays an animation through the Web Animations API and returns the Animation, so you can await finished. Import the whole index, or a single animation to keep the download small.

main.js
import { animate } from "https://cdn.htmltool.io/animations/1.0.0/js/index.mjs";

const animation = animate(document.querySelector("h1"), "fade-in-up", { duration: 900, delay: "100ms" });
await animation.finished;

// one animation only (small)
import { animate as fadeInUp } from "https://cdn.htmltool.io/animations/1.0.0/js/animations/fade-in-up.mjs";
fadeInUp(element, { iterations: 2 });

Options: duration, delay (ms or a CSS time), iterations (a number or "infinite"), easing, direction, fill and ignoreReducedMotion. Types ship in js/index.d.ts; AnimationName is the union of every slug.

Classic script tag

index.html
<script src="https://cdn.htmltool.io/animations/1.0.0/js/devops-animations.min.js"></script>
<script>DevOpsAnimations.animate(document.body, "fade-in-up");</script>

Custom elements

Load the elements once and animate anything without writing CSS or JavaScript. Each element fetches only the animation it needs.

index.html
<script type="module" src="https://cdn.htmltool.io/animations/1.0.0/elements/index.mjs"></script>

<da-animate name="fade-in-up" trigger="visible" duration="600ms">
  <img src="hero.png" alt="">
</da-animate>

<da-sequence name="fade-in-up" stagger="80ms" trigger="visible">
  <div>One</div><div>Two</div><div>Three</div>
</da-sequence>

<da-loader type="spinner-ring" label="Loading results"></da-loader>
<da-text-effect effect="typewriter">Ship it.</da-text-effect>
Custom element attributes
AttributeElementsMeaning
nameallAnimation slug (the da- prefix is optional).
typeda-loaderLoader slug, or the start of one.
effectda-text-effectText effect slug, or the start of one.
triggerallload (default), visible, hover, click or manual.
threshold, repeatallVisibility ratio for visible; repeat replays each time it enters.
duration, delay, iterations, easing, direction, fillallTiming overrides.
staggerda-sequenceDelay between children (default 80ms).
ignore-reduced-motionallAnimate even when the visitor asks for reduced motion.

Methods: play(), pause(), cancel(), reverse() and finish(). Events da-start, da-end, da-cancel and da-error bubble.

Tailwind

Tailwind v4: import the theme file. Utilities are animate-da-<slug>, and only the keyframes you use are emitted.

app.css
@import "tailwindcss";
@import "https://cdn.htmltool.io/animations/1.0.0/tailwind/devops-animations.css";
/* or tailwind/categories/<category>.css, tailwind/animations/<slug>.css */

Tailwind entries carry the keyframes and timing. transform-origin and the part styles of custom subjects live in the plain CSS, so link that too for loaders and text effects.

Reduced motion

When a visitor has prefers-reduced-motion: reduce set, every da-* class plays a single 1 ms iteration, so elements land in their final state without moving. animate() jumps straight to the end (or leaves infinite animations still), and the custom elements do the same unless you add ignore-reduced-motion.

Note
You don't need to add your own media query. If you build a custom trigger in JavaScript, check matchMedia("(prefers-reduced-motion: reduce)") before replaying anything on a loop.

Full reference

The README covers CSS Modules, every file in the package and the full element API. Read the animations README(opens in a new tab). Every slug with its category, tags, timing and file paths is listed in index.json:

https://cdn.htmltool.io/animations/1.0.0/index.json