Jesse A. Green / notebook

impress.js User Guide

Generated June 2026 from impress/impress.js at c9f6c67

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.

impress.js is a presentation framework that turns ordinary HTML into a single, infinite canvas you can zoom, pan, and rotate through in 3D. Instead of a stack of flat slides, you place your content anywhere on a boundless space and let the browser fly the "camera" from one point to the next using CSS3 transforms and transitions. It was inspired by the idea behind prezi.com, and it uses no jQuery and no runtime dependencies — just modern browser features.

You author a presentation entirely in HTML and CSS. Each slide is a <div class="step"> positioned with data-* attributes (data-x, data-y, data-z, data-rotate, data-scale). One line of JavaScript — impress().init() — starts the show.

Note

impress.js is a framework you build presentations with, not an application you run. There is nothing to "launch." You write an HTML file, include the impress.js script, and open it in a browser.


Table of Contents

  1. Quick Start
  2. Requirements
  3. Installation
  4. Building Your First Presentation
  5. Positioning Slides (the data-* attributes)
  6. Presentation Settings (the root element)
  7. Navigating a Presentation (keyboard, mouse, touch)
  8. Styling with impress.js State Classes
  9. Plugin Catalog
  10. Extra Add-ons (Markdown, Mermaid, syntax highlighting)
  11. The JavaScript API
  12. Common Tasks (recipes)
  13. How It Works (concepts)
  14. Troubleshooting
  15. FAQ
  16. Reference

1. Quick Start

Create a file called index.html, paste this in, and open it in Chrome or Firefox. Use the arrow keys or spacebar to move between slides.

<!DOCTYPE html>
<html>
<head>
    <title>My first presentation</title>
</head>
<body class="impress-not-supported">
    <div id="impress">

        <div class="step" data-x="0" data-y="0">
            <h1>Hello, impress.js</h1>
        </div>

        <div class="step" data-x="1000" data-y="0" data-rotate="90">
            <h1>This slide is rotated 90&deg;</h1>
        </div>

        <div class="step" data-x="2000" data-y="0" data-scale="3">
            <h1>And this one is zoomed in</h1>
        </div>

    </div>

    <!-- Load impress.js, falling back to the CDN if no local copy exists -->
    <script src="js/impress.js"></script>
    <script>
        window.impress ||
        document.write('<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js"><\/script>');
    </script>
    <script>impress().init();</script>
</body>
</html>
A full-screen presentation opens on the first slide. Press the Right arrow or
Space to fly to the rotated slide, then again to zoom into the third.

Tip

That's the entire model: a #impress container, one <div class="step"> per slide positioned with data-* attributes, and impress().init(). Everything else in this guide builds on these three ideas.


2. Requirements

impress.js runs in the viewer's browser — there is no server, build step, or account required to present. The only requirement is a reasonably modern browser.

Feature used Why Browser support
CSS 3D Transforms The core 3D positioning/camera Modern Chrome, Firefox, Safari, Edge
CSS Transitions The animated movement between steps Modern Chrome, Firefox, Safari, Edge
dataset (DataSet API) Reads data-* attributes from your HTML Modern browsers
classList (ClassList API) Adds/removes state classes Modern browsers

Important

The typical and recommended use case is presenting from your own laptop with a browser version you have tested. If you embed an impress.js presentation in a public web page, some visitors on older browsers may see only the fallback message (see Section 8).

Note

impress.js deliberately uses no jQuery and no other JavaScript libraries, and does not polyfill older browsers. Recent Firefox and Chrome are known to work well; recent versions of other major browsers generally work too.


3. Installation

There are two ways to get impress.js into your presentation. Pick based on whether you'll have a reliable internet connection when you present.

Caution

If you are not certain you'll have WiFi during your talk, download a local copy (Method B). A CDN-only setup will fail to load with no network.

From a CDN (no download)

Include one <script> tag in your HTML. impress.js loads automatically — nothing to download.

<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js"></script>
<script>impress().init();</script>

Pinned version links:

Version jsDelivr URL
v2.0.0 https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js
v1.1.0 https://cdn.jsdelivr.net/gh/impress/impress.js@1.1.0/js/impress.js
latest source https://cdn.jsdelivr.net/gh/impress/impress.js/js/impress.js

Download a local copy

  1. Go to the GitHub Releases page and download the source as a .zip or .tar.
  2. Unzip it.
  3. Copy the js/ folder into your project directory.
  4. (Optional) Copy the css/ folder too, if you want the sample plugin styling in impress-common.css.
<script src="js/impress.js"></script>
<script>impress().init();</script>

Belt-and-suspenders (local + CDN fallback)

Use a local file but fall back to the CDN automatically if it's missing:

<script src="js/impress.js"></script>
<script>
    window.impress ||
    document.write('<script src="https://cdn.jsdelivr.net/gh/impress/impress.js@2.0.0/js/impress.js"><\/script>');
</script>
<script>impress().init();</script>

About impress-common.css

impress.js does not require any CSS file — it generates the positioning CSS it needs dynamically. However, the bundled css/impress-common.css provides sample styling that several plugins need to look right (the help popup, toolbar, progress bar, speaker-notes hiding, and the mouse-timeout cursor hiding). Link it if you use those plugins:

<link rel="stylesheet" href="./css/impress-common.css">

Note

impress.js is not currently published to npm. The package.json in the repo exists mainly to run the build and test tooling. Install it by downloading a release or linking the CDN, not via npm install.

Warning

The file you link in the browser is js/impress.js — a generated bundle that concatenates the core and all default plugins. The files under src/ are the authored source and are not meant to be linked individually in a presentation.


4. Building Your First Presentation

A presentation has three required pieces.

Put a class of impress-not-supported on the <body> and include a fallback block. If the browser can't run impress.js, the visitor sees this message instead of a broken page. impress.js removes the class automatically when it detects support.

<body class="impress-not-supported">
    <div class="fallback-message">
        <p>Your browser <b>doesn't support the features required</b> by impress.js,
           so you are presented with a simplified version of this presentation.</p>
        <p>For the best experience please use the latest
           <b>Chrome</b>, <b>Safari</b> or <b>Firefox</b> browser.</p>
    </div>
    ...
</body>

4.2 The root element

All presentation content lives inside a single root element, by default the one with id="impress". Anything outside it is not animated by impress.js.

<div id="impress">
    <!-- all your steps go here -->
</div>

4.3 The steps

Each slide is a <div class="step">. Give it an id if you want a friendly URL hash and easy navigation targets (otherwise impress.js auto-assigns step-1, step-2, …).

<div id="intro" class="step" data-x="0" data-y="0">
    <h1>Welcome</h1>
</div>

Warning

Do not apply your own CSS transform, position, width, or height directly to a .step element — impress.js controls those. If you need custom styling or layout, put a child <div> inside the step and style that instead.

<div class="step" data-x="1000" data-y="1000" data-scale="2">
    <div class="my-content">
        <h1>Powerful, yet still simple</h1>
    </div>
</div>

Tip

Because every step is wrapped in a zero-size box, you cannot use percentage widths/heights (width: 100%) for step content. Use pixel values that correspond to your target data-width/data-height (see Section 6).


5. Positioning Slides (the data-* attributes)

You place each step on the infinite canvas by setting data-* attributes. The values position the center of the step. All values are strings, so quote your numbers. Negative numbers are allowed everywhere.

Attribute Default What it does
data-x 0 X position (left ↔ right), in pixels
data-y 0 Y position (top ↔ bottom), in pixels
data-z 0 Z position (depth toward/away from camera), in pixels
data-scale 1 Size multiplier relative to other steps (e.g. 4 = 4× larger)
data-rotate 0 Clockwise rotation in degrees (alias for data-rotate-z)
data-rotate-x 0 Rotation around the X axis, in degrees
data-rotate-y 0 Rotation around the Y axis, in degrees
data-rotate-z 0 Rotation around the Z axis, in degrees
data-rotate-order xyz Order the X/Y/Z rotations are applied
data-transition-duration inherits root Per-step transition time in ms (overrides the global setting)

Examples

A step moved left and up:

<div class="step" data-x="-1000" data-y="-1500">
    <q>Aren't you just <b>bored</b> with slides-based presentations?</q>
</div>

A zoomed-in title:

<div id="title" class="step" data-x="0" data-y="0" data-scale="4">
    <h1>impress.js</h1>
</div>

A step pushed deep into the background on the Z axis:

<div id="tiny" class="step" data-x="2825" data-y="2325" data-z="-3000" data-rotate="300" data-scale="1">
    <p>and <b>tiny</b> ideas</p>
</div>

Full 3D rotation around multiple axes:

<div class="step" data-x="6200" data-y="4300" data-z="-100"
     data-rotate-x="-40" data-rotate-y="10" data-scale="2">
    <p>have you noticed it's in <b>3D</b>?</p>
</div>

Tip

data-rotate and data-rotate-z are exact aliases — both rotate around the Z axis (the one facing the viewer).

Note

data-rotate-order matters because each rotation is applied relative to the element's current orientation. The default xyz works for almost everything; change it only for advanced poses that the default order can't reach. See the bundled examples/3D-rotations/ demo.

Relative positioning (the rel plugin)

Typing absolute coordinates for dozens of slides gets tedious. The built-in rel plugin lets you position a step relative to the previous step, which means inserting or moving slides rarely forces you to re-do coordinates.

<!-- 1000px right and 500px up from the previous step -->
<div class="step" data-rel-x="1000" data-rel-y="500">...</div>

<!-- relative to a specific earlier step by id -->
<div class="step" data-rel-x="-1000" data-rel-y="750" data-rel-to="title">...</div>

You can express relative values as multiples of screen width/height with w/h units:

<div class="step" data-rel-x="1.5w" data-rel-y="1.5h">...</div>

See the rel plugin entry for the full attribute list and an important compatibility note.


6. Presentation Settings (the root element)

Global settings go as data-* attributes on the #impress root element. They define your target screen size — author your CSS as if the screen is exactly this size, and impress.js will scale the whole presentation up or down to fit whatever screen it's shown on.

Attribute Default Explanation
data-width 1920 Width of the target screen, in px. Content scales automatically on other sizes.
data-height 1080 Height of the target screen, in px.
data-max-scale 3 Maximum scale-up factor on larger screens.
data-min-scale 0 Minimum scale-down factor on smaller screens.
data-perspective 1000 3D perspective in px. Set to 0 to disable 3D effects.
data-transition-duration 1000 Default transition time between steps, in ms (1 s).
<div id="impress"
     data-transition-duration="1000"
     data-width="1024"
     data-height="768"
     data-max-scale="3"
     data-min-scale="0"
     data-perspective="1000">
    ...
</div>

Important

The default target resolution is HD (1920×1080). If your presentation was authored for the older 1024×768 default, set it explicitly or your layout will look off:

<div id="impress" data-width="1024" data-height="768" data-max-scale="1" data-min-scale="0">

Note

A data-max-scale of 1 will not enlarge content on screens bigger than your target size — it will only ever shrink. Use a value above 1 (the default is 3) if you want content to grow on big displays.


7. Navigating a Presentation (keyboard, mouse, touch)

These controls come from the built-in navigation, help, blackout, fullscreen, and impressConsole plugins, which are all included in js/impress.js by default.

Keyboard

Key Action
→ Right / ↓ Down / Space / Tab / Page Down Next step
← Left / ↑ Up / Page Up / Shift+Tab Previous step
H or ? Toggle the on-screen help popup
B or . Blackout — blank/unblank the screen
F5 Enter fullscreen (plugin)
Esc Exit fullscreen
P Open the speaker console (impressConsole)

Note

Tab moves to the next step on purpose. impress.js needs to control the Tab key because the browser's default Tab behavior (focusing links/buttons) can scroll the viewport and break the careful 3D positioning. Shift+Tab goes back.

Tip

Modifier combinations like Alt+Tab, Ctrl+…, and Cmd+… are ignored, so switching windows won't accidentally advance your slides.

Mouse

  • Click any non-active step to fly to it.
  • Click a link whose href is #some-step-id to navigate to that step.

Touch

The built-in touch plugin lets you swipe left/right to move between steps on touch devices. Transitions may look slightly different from the keyboard experience.

The help popup

To show the help overlay (and let viewers press H for it), add an empty div anywhere in your page:

<div id="impress-help"></div>

The popup appears for 7 seconds when the presentation loads, and toggles on H/?. Plugins automatically add their own keys to it (for example, the navigation plugin adds the "Left & Right → Previous & Next step" line).

Tip

Style the help popup yourself, or link impress-common.css which includes a ready-made style for #impress-help.


8. Styling with impress.js State Classes

impress.js adds CSS classes to your elements as the presentation runs. You hook into these classes to style slides and trigger per-slide animations.

Step state classes

Every step is always in exactly one of three states:

Class Applied to Meaning
.future Steps not visited yet Style or hide upcoming slides
.present The step at the center of the camera right now Trigger in-slide animations
.past Steps already visited Style or hide previous slides
.active The currently visible step (same as present, available for convenience) Highlight the current slide
/* Fade non-active steps */
.step {
    opacity: 0.3;
    transition: opacity 1s;
}
.step.active {
    opacity: 1;
}

/* Animate something only while its slide is centered */
.present .rotating {
    transform: rotate(-10deg);
    transition-delay: 0.25s;
}

The impress-on-* body class

When a step becomes active, impress.js adds a class to the <body> named after the step's id, e.g. impress-on-overview. This lets you style globally based on which slide is showing (something you can't do by matching upward from the step to the body):

.impress-on-overview .step {
    opacity: 1;
    cursor: pointer;
}
.impress-on-step-1 { background: LightBlue; }

The impress-not-supported / impress-supported classes

If the browser lacks required features, impress.js adds impress-not-supported to the <body>; otherwise it adds impress-supported. Author your fallback styles against .impress-not-supported:

.impress-not-supported .step {
    display: inline-block; /* show steps as a simple stacked list */
}

Tip

Add class="impress-not-supported" to the <body> yourself in the HTML. That way visitors with JavaScript disabled also get the fallback styling — impress.js will remove the class at runtime when it confirms support.


9. Plugin Catalog

Almost every feature beyond positioning is a plugin. All of the plugins below are default plugins — they are already bundled in js/impress.js, so you don't load them separately. Most do nothing until you opt in, usually by adding an HTML attribute, a specific <div>, or a CSS class.

Plugin How you enable it What it does
navigation automatic Keyboard + mouse navigation between steps
navigation-ui toolbar present Back/Forward buttons + a slide-picker dropdown
touch automatic Swipe gestures on touch devices
rel data-rel-* attributes Position steps relative to other steps
goto data-goto* attributes Non-linear jumps (out-links)
bookmark data-bookmark-key-list Non-linear jumps via global hotkeys (in-links)
skip class="skip" Skip a step during normal next/prev
stop class="stop" Stop next() from wrapping past this step
substep class="substep" Reveal bullet points one at a time
autoplay data-autoplay Auto-advance after a timeout
progress .impress-progressbar / .impress-progress divs Progress bar + slide counter
help #impress-help div On-screen keyboard help popup
blackout automatic (B/.) Blank the screen
fullscreen automatic (F5) Enter fullscreen
impressConsole automatic (P) Speaker console with notes + preview
mobile CSS you provide Hide far-away slides to save resources on phones
resize automatic Re-fit the presentation when the window resizes
mouse-timeout CSS you provide Add a body class after 3 s of mouse inactivity
toolbar #impress-toolbar div A shared GUI toolbar other plugins add widgets to
form automatic Make form fields usable inside slides
media data-media-* attributes Auto play/pause/stop audio & video per step
extras extra <script> tags Auto-initialize 3rd-party add-ons

Automatic. Listens for the keyboard and mouse events described in Section 7. No setup needed.

Provides Back, Forward, and a slide-selector dropdown. These controls appear inside the toolbar, so you must also enable the toolbar plugin (add a <div id="impress-toolbar"></div>). The dropdown labels each step by its title attribute, or its id if no title is set.

touch

Automatic. Enables swipe navigation on touch devices.

rel — Relative positioning

Position a step relative to the previous step (or to a named earlier step) instead of with absolute coordinates.

Supported step attributes:

data-rel-x   data-rel-y   data-rel-z   data-rel-to
data-rel-rotate-x   data-rel-rotate-y   data-rel-rotate-z
data-rel-position    data-rel-reset
  • Non-zero data-rel-* values are inherited from the previous step, so a deck where every slide shifts by the same amount needs the value set only once.
  • A relative value is ignored if the matching absolute value (data-x, etc.) is also set on the same step.
  • data-rel-to="some-id" references an earlier step (only previous steps, to avoid circular positioning).
  • Use w/h units for screen-relative offsets: data-rel-x="1.5w".
  • data-rel-position="relative" makes offsets relative to the previous slide's rotated frame, so you can build circles and complex layouts without manual trigonometry. It is inherited, so set it once on the first slide.
  • data-rel-reset resets all data-rel-* to zero for that step; data-rel-reset="all" also resets data-rotate-*.

Warning

Enabling rel introduces one backward-incompatible change: when a step omits data-x/data-y/data-z, the value is inherited from the previous step rather than defaulting to 0. If you have an older deck that relied on the old "missing means 0" behavior, add explicit data-z="0" (etc.) where needed, or remove the plugin. (This is the only compatibility caveat in the framework, and it exists precisely because relative positioning is so much more convenient.)

goto

A non-linear navigation plugin. It defines out-links on a step — where to jump when leaving it.

<!-- When leaving this step, always go to "step-5" -->
<div class="step" data-goto="step-5">

<!-- Different targets for next() vs prev() -->
<div class="step" data-goto-next="step-5" data-goto-prev="step-1">

<!-- Bind specific keys to specific destinations -->
<div class="step"
     data-goto-key-list="ArrowUp ArrowDown ArrowRight ArrowLeft"
     data-goto-next-list="step-4 step-3 step-2 step-5">

Key names follow the MDN KeyboardEvent key values.

bookmark

Like goto, but defines in-links — global hotkeys that jump to a step from anywhere.

<div id="agenda" class="step" data-bookmark-key-list="Digit1 KeyA 1 2 3 a b c">
  • An id is required on the step.
  • Assigning the same key to multiple steps cycles among them.

Warning

It's up to you to avoid keys already reserved by other plugins (H, B, P, ?, etc.).

skip

Add class="skip" to a step to skip it during normal next()/prev() navigation. You can still reach it directly (e.g. via a URL hash or goto()).

<div class="step skip">This won't appear in the normal flow</div>

stop

Add class="stop" to a step to prevent next() from advancing past it — handy on a final slide so the deck doesn't wrap back to the start.

<div class="step stop">Last slide — stays put</div>

substep

Reveal parts of a slide one at a time, like PowerPoint bullet animations. Give child elements class="substep"; next()/prev() will reveal/hide them before moving on to the next step.

<style>
    .substep { opacity: 0; }
    .substep.substep-visible { opacity: 1; transition: opacity 1s; }
</style>

<div class="step">
    <h1>Fruits</h1>
    <p class="substep">Orange</p>
    <p class="substep">Apple</p>
</div>
  • Control order with data-substep-order="N" (integers, ascending; unordered substeps reveal last).
  • The plugin adds substep-visible to revealed substeps and substep-active to the most recent one — you supply the CSS to show/hide them.
  • goto() ignores substeps and jumps straight to the target step.

autoplay

Auto-advance the presentation after a timeout. Enable it globally on the root, then override per step.

<div id="impress" data-autoplay="5">         <!-- 5 s default -->
    <div class="step" data-autoplay="0">...</div>   <!-- never auto-advance -->
    <div class="step">...</div>                     <!-- uses global 5 s -->
    <div class="step" data-autoplay="10">...</div>  <!-- 10 s -->
</div>

The value is the wait time in seconds; 0 disables auto-advance on that step. You can also trigger autoplay via a URL parameter: append ?impress-autoplay=5 to the page URL.

progress

Shows a progress bar and/or a slide counter. Add the divs where you want them:

<div class="impress-progressbar"><div></div></div>
<div class="impress-progress"></div>

Style them yourself, or link impress-common.css for the sample styling.

help

Shows the keyboard-shortcut popup. Add <div id="impress-help"></div> to your page (see Section 7).

blackout

Automatic. Press B or . to blank the screen (and again to restore it) — useful to draw attention away from the slides.

fullscreen

Automatic. Press F5 to enter fullscreen, Esc to leave.

Note

impress.js works fine with your browser's normal fullscreen (usually F11). The fullscreen plugin is mainly useful when combined with the impressConsole plugin.

impressConsole

Press P to open a speaker console in a separate window: current slide, preview of the next slide, your speaker notes, and navigation.

Add notes inside any step with a notes div:

<div class="step">
    Visible slide content
    <div class="notes">Speaker notes — only shown in the console.</div>
</div>

Hide notes from the actual presentation with CSS:

.notes { display: none; }

mobile

Detects mobile OSes and adds a body.impress-mobile class, plus div.next/div.prev classes to the steps adjacent to the current one. Combined with your CSS, this lets you hide all but the current/next/previous slides to save resources on phones.

body.impress-mobile .step { display: none; }
body.impress-mobile .step.active,
body.impress-mobile .step.present,
body.impress-mobile .step.next,
body.impress-mobile .step.prev { display: block; }

resize

Automatic. Re-fits the presentation when the browser window changes size. No configuration.

mouse-timeout

After 3 seconds of mouse inactivity, adds body.impress-mouse-timeout; removes it on the next move, click, or touch. Use it to hide UI (or the cursor itself) until the mouse moves:

body.impress-mouse-timeout { cursor: none; }
body.impress-mouse-timeout div#impress-toolbar { display: none; }

toolbar

A shared on-screen toolbar that other plugins (like navigation-ui) hang their widgets on. Enable it by adding:

<div id="impress-toolbar"></div>

Style it yourself; impress-common.css includes a sample position (bottom-right). Combine with mouse-timeout to auto-hide it.

form

Automatic. Improves the use of <input>, <textarea>, <button>, etc. inside slides: it stops keypresses in form fields from triggering navigation (so typing "P" in a text box won't open the console), and de-focuses fields when you leave a step.

Note

The form plugin notes that Tab navigation between form fields is not currently possible, because the navigation plugin must fully control the Tab key. This is a known limitation flagged in the plugin itself.

media

Auto play/pause/stop <audio> and <video> based on which step is showing. Set attributes on a step (inherited by media inside it) or on individual media elements:

Attribute Effect
data-media-autoplay="true" Start the media when its step is entered
data-media-autostop="true" Stop and reset media when leaving the step
data-media-autopause="true" Pause (keep position) when leaving the step
<div class="step" data-media-autoplay="true" data-media-autopause="true">
    <video src="demo.mp4" controls></video>
</div>

The plugin also toggles body classes while media plays/pauses (e.g. body.impress-media-video-playing) so you can dim the background.

Tip

To auto-advance when a clip finishes: <video onended="impress().next()">.

extras

Automatically initializes any 3rd-party "extra add-ons" you've included (see the next section). If you haven't added any, it does nothing.


10. Extra Add-ons (Markdown, Mermaid, syntax highlighting)

Beyond the default plugins, impress.js can use extra add-ons — 3rd-party plugins collected in the separate impress-extras repository. They are not part of impress.js core and are not active by default; you must include each one with its own <script> tag. The built-in extras plugin then auto-initializes them.

To get the extras when cloning:

git clone --recursive https://github.com/impress/impress.js.git

Typical add-ons and how you'd reference them:

<head>
    <!-- e.g. syntax highlighting and diagram styling -->
    <link rel="stylesheet" href="../../extras/highlight/styles/github.css">
    <link rel="stylesheet" href="../../extras/mermaid/mermaid.forest.css">
</head>

The plugins README documents one extra-specific attribute: for the Markdown add-on you can choose a dialect with data-markdown-dialect="...".

Note

Because extras live in a submodule, a plain (non---recursive) checkout will not include them. They're optional — your presentation works without any of them.


11. The JavaScript API

For most presentations you never write JavaScript beyond impress().init(). The API is there for custom controls, integrations, and programmatic navigation.

impress( [id] )

A factory that returns the presentation's API object. Pass the root element's id; omit it to use the default "impress".

var api = impress();          // uses #impress
var api2 = impress("root");   // uses #root

API methods

Method Description
.init() Initialize and start the presentation. Call once.
.next() Go to the next step (in document order).
.prev() Go to the previous step.
.goto(target [, duration]) Go to a step by index (number), id (string), or element. Optional transition duration in ms.
.tear() Reset the DOM to its pre-init() state ("unload" impress.js).
var api = impress();
api.init();
api.goto(7);          // by index
api.goto("overview"); // by id
api.next();

Note

Only one impress.js instance per document is supported in practice.

Events

impress.js fires custom DOM events on the root element. Listen with addEventListener.

Event Fired when
impress:init The presentation has finished initializing. event.detail.api gives you the API.
impress:stepenter A step has finished transitioning in. event.target is the step.
impress:stepleave A step is being left. event.detail.next is the incoming step.
impress:steprefresh A step is (re)drawn, e.g. after a resize.
var root = document.getElementById("impress");

root.addEventListener("impress:stepenter", function (event) {
    console.log("Entered step:", event.target.id);
});

root.addEventListener("impress:stepleave", function (event) {
    console.log("Leaving", event.target.id, "for", event.detail.next.id);
});

impress().init();

Tip

The impress:stepenter/impress:stepleave events are the supported way to run your own code (analytics, animations, syncing) as the audience moves through the deck.


12. Common Tasks (recipes)

Make a simple, PowerPoint-style linear deck

Use the classic-slides approach: lay steps out in a row and rely on the default next/prev navigation. The bundled examples/classic-slides/ demo is a ready-made template.

<div id="impress" data-width="1024" data-height="768" data-max-scale="1">
    <div class="step" data-x="0">Slide 1</div>
    <div class="step" data-x="1024">Slide 2</div>
    <div class="step" data-x="2048">Slide 3</div>
</div>

Reveal bullets one at a time

See the substep plugin — add class="substep" to each bullet and supply show/hide CSS.

Add speaker notes and use the presenter console

Add <div class="notes">…</div> inside steps, hide them with .notes { display:none }, and press P while presenting. See impressConsole.

Auto-run a kiosk presentation

Enable autoplay on the root (data-autoplay="10") and combine with the stop plugin if you don't want it to loop.

Jump to any slide from a menu

Give steps ids and link to them; the navigation plugin intercepts href="#step-id" clicks:

<a href="#summary">Skip to summary</a>
...
<div id="summary" class="step" data-x="...">...</div>

Show a progress bar

Add the progress divs and (optionally) link impress-common.css.

Reload a presentation after editing the DOM

Call impress().tear(), modify your steps, then impress().init() again. impress.js re-reads the data-* attributes on each transition, so you can also change coordinates dynamically and have them apply on the next goto().


13. How It Works (concepts)

You don't need this section to use impress.js, but it clarifies the mental model.

One canvas, many steps. All your steps live on a single, boundless canvas. impress.js doesn't move the slides — it moves the camera. When you go to a step, impress.js computes the inverse of that step's position/rotation/scale and applies it to the canvas, so the chosen step ends up centered and upright in front of the viewer.

Two animated elements. impress.js wraps your steps in a canvas element inside the root. The root handles scaling (zoom), and the canvas handles translation and rotation. They animate with slightly different delays so zooming in/out looks natural.

Window scaling. Your data-width/data-height define a target size. impress.js measures the real window and scales everything to fit (bounded by data-min-scale/data-max-scale), which is why one deck looks right on a laptop and a projector.

State as CSS classes. Navigation is expressed as classes (.future/.present/.past/.active, impress-on-*) so all visual behavior is yours to define in CSS.

Plugins via events. Most plugins simply listen for impress:init, impress:stepenter, or impress:stepleave and use the public API. Pre-init plugins (like rel) run before init to rewrite attributes; pre-stepleave plugins (like goto, skip, stop, substep) run before a transition and can redirect or cancel it.

The URL hash. impress.js keeps the location hash in sync (#/step-id) so you can deep-link to and reload on a specific slide.


14. Troubleshooting

Error: presentation shows the "browser doesn't support" fallback message

Cause: The browser lacks CSS 3D Transforms, CSS Transitions, the DataSet API, or the ClassList API — or you're viewing in a very old browser. Solution: Use a current version of Chrome, Firefox, Safari, or Edge. Prevention: Test on the exact browser/version you'll present with; present from your own laptop when possible.

My slides are all stacked on top of each other

Cause: Steps have no positioning attributes, so they all sit at 0,0. Solution: Give each step distinct data-x/data-y (and optionally data-z, data-rotate, data-scale) values. Prevention: Remember that quotes are required (data-x="1000"), since attribute values are strings.

Nothing happens / impress is not defined

Cause: The js/impress.js script didn't load (wrong path or no network for the CDN), or impress().init() ran before the script loaded. Solution: Check the script src path; use the local+CDN fallback snippet; ensure impress().init() runs after the impress.js <script> tag. Prevention: Download a local copy if you might present without WiFi.

My custom CSS on .step (size/transform) is ignored or breaks layout

Cause: impress.js controls position, transform, width, and height on step elements. Solution: Wrap your content in a child <div> and style that instead of the .step div. Prevention: Treat .step as a positioning container only; never set its transform/size directly.

Percentage widths/heights don't work inside a step

Cause: Each step is wrapped in a zero-size box, so % units resolve to zero. Solution: Use pixel values that match your data-width/data-height target.

After upgrading, slide positions shifted

Cause: The rel plugin changed the default for missing data-x/data-y/data-z from 0 to "inherit from previous step." Solution: Add explicit data-z="0" (and data-x/data-y as needed) to the affected steps, or remove the rel plugin. Prevention: When authoring against a build that includes rel, set coordinates explicitly where you mean zero.

Typing in a form field triggers navigation (e.g. opens the console)

Cause: Without the form plugin, keypresses in fields bubble up to the navigation/console plugins. Solution: The default build already includes the form plugin; make sure you're using js/impress.js, not a custom build that omitted it.

The presentation re-fits with a slight delay after resizing the window

Cause: The resize transition is set to a fixed duration. Solution: This is expected behavior; the presentation re-scales after the window settles.

Speaker notes appear on the actual slides

Cause: You added <div class="notes"> but didn't hide it. Solution: Add .notes { display: none; } to your CSS (the notes still show in the P console).

3D-positioned content isn't clickable

Cause: Elements pushed back on the Z axis can fall "behind" the body element in some browsers (notably Chrome). Solution: Use the pointer-events workaround from impress-common.css, which makes everything except #impress non-clickable so clicks reach your steps.

A rotated slide ends up in an unexpected orientation

Cause: Multiple-axis rotations are order-dependent and the default xyz order can't reach every pose. Solution: Set data-rotate-order (e.g. "zyx") on that step; see the examples/3D-rotations/ demo.


15. FAQ

Q: Do I need Node.js or npm to make a presentation? No. You only need a browser and a text editor. Node/npm are required solely if you want to build impress.js from source or run its tests.

Q: Can I install it with npm install impress.js? Not currently — impress.js isn't published to npm. Download a release or use the jsDelivr CDN.

Q: Which file do I include — src/impress.js or js/impress.js? js/impress.js. It's the generated bundle of the core plus all default plugins. src/impress.js is just the core, without plugins.

Q: Do I have to use impress-common.css? No. impress.js generates the positioning CSS it needs. impress-common.css only adds sample styling for plugins like help, toolbar, and progress.

Q: How many slides can a presentation have? There's no fixed limit. On low-powered/mobile devices, very 3D-heavy decks can get sluggish — the mobile plugin helps by hiding far-away slides.

Q: Can I have more than one impress.js presentation on a single page? The code technically supports multiple roots, but in practice one instance per document is what's supported and recommended.

Q: How do I deep-link to a specific slide? Give the step an id and link to #/step-id (or #step-id). The URL hash stays in sync as you navigate, so reloading returns to the same slide.

Q: Can I auto-advance slides for a kiosk? Yes — use the autoplay plugin (data-autoplay="N" seconds), optionally with ?impress-autoplay=N in the URL.

Q: How do I add presenter notes? Put <div class="notes">…</div> inside a step, hide it with CSS, and press P to open the speaker console.

Q: Will it work when embedded in a public web page? It can, but visitors on older/unsupported browsers may see only the fallback message. impress.js is designed primarily for presenting from your own (tested) browser.

Q: Is there a visual editor? There's a sibling project, Impressionist, a 3D GUI editor for building impress.js presentations.

Q: Where can I see a full-featured example? The repo's index.html is the official, heavily-commented demo. The examples/ folder has more demos (classic-slides, cube, 3D-rotations, 3D-positions, 2D-navigation, markdown).


16. Reference

Root element attributes

Attribute Default Purpose
data-width 1920 Target screen width (px)
data-height 1080 Target screen height (px)
data-max-scale 3 Max scale factor
data-min-scale 0 Min scale factor
data-perspective 1000 3D perspective (px); 0 disables 3D
data-transition-duration 1000 Default transition time (ms)
data-autoplay — Global auto-advance time (seconds), via autoplay plugin

Step element attributes (core)

Attribute Default Purpose
data-x / data-y / data-z 0 Position of step center (px)
data-scale 1 Size multiplier
data-rotate / data-rotate-z 0 Z-axis rotation (deg)
data-rotate-x / data-rotate-y 0 X/Y-axis rotation (deg)
data-rotate-order xyz Rotation application order
data-transition-duration inherits root Per-step transition time (ms)

Plugin-specific step attributes & classes (selected)

Attribute / class Plugin Purpose
data-rel-x/y/z, data-rel-to, data-rel-rotate-*, data-rel-position, data-rel-reset rel Relative positioning
data-goto, data-goto-next, data-goto-prev, data-goto-key-list, data-goto-next-list goto Out-link jumps
data-bookmark-key-list bookmark In-link hotkeys
data-autoplay autoplay Per-step auto-advance (seconds; 0 = off)
data-substep-order + class="substep" substep Ordered bullet reveals
data-media-autoplay/autostop/autopause media Per-step media control
class="skip" skip Skip in normal navigation
class="stop" stop Block next() past this step
class="notes" impressConsole Speaker notes

CSS classes impress.js applies

Class Applied to Meaning
.future / .present / .past steps Visit state
.active step Currently centered step
.impress-on-{id} <body> Active step's id
.impress-supported / .impress-not-supported <body> Feature-support state
.impress-enabled / .impress-disabled <body> Init state
.impress-mobile <body> Mobile device detected (mobile plugin)
.impress-mouse-timeout <body> Mouse idle >3 s (mouse-timeout plugin)
.substep / .substep-visible / .substep-active substep elements Reveal state

Keyboard shortcuts

Key Action
Right / Down / Space / Tab / Page Down Next
Left / Up / Page Up / Shift+Tab Previous
H or ? Toggle help
B or . Blackout
F5 / Esc Fullscreen / exit
P Speaker console

JavaScript API

Call Purpose
impress([id]) Get the API for a root element
.init() Start the presentation
.next() / .prev() Navigate sequentially
.goto(idx | id | el [, ms]) Navigate to a specific step
.tear() Reset the DOM
impress.supported Boolean: browser support check

Events

impress:init, impress:stepenter, impress:stepleave, impress:steprefresh (all on the root element).