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.jsscript, and open it in a browser.
Table of Contents
- Quick Start
- Requirements
- Installation
- Building Your First Presentation
- Positioning Slides (the data-* attributes)
- Presentation Settings (the root element)
- Navigating a Presentation (keyboard, mouse, touch)
- Styling with impress.js State Classes
- Plugin Catalog
- Extra Add-ons (Markdown, Mermaid, syntax highlighting)
- The JavaScript API
- Common Tasks (recipes)
- How It Works (concepts)
- Troubleshooting
- FAQ
- 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°</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
#impresscontainer, one<div class="step">per slide positioned withdata-*attributes, andimpress().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
- Go to the GitHub Releases page and download the source as a
.zipor.tar. - Unzip it.
- Copy the
js/folder into your project directory. - (Optional) Copy the
css/folder too, if you want the sample plugin styling inimpress-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.jsonin the repo exists mainly to run the build and test tooling. Install it by downloading a release or linking the CDN, not vianpm 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 undersrc/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.
4.1 The fallback message (recommended)
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, orheightdirectly to a.stepelement — 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 targetdata-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-rotateanddata-rotate-zare exact aliases — both rotate around the Z axis (the one facing the viewer).
Note
data-rotate-ordermatters because each rotation is applied relative to the element's current orientation. The defaultxyzworks for almost everything; change it only for advanced poses that the default order can't reach. See the bundledexamples/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-scaleof1will not enlarge content on screens bigger than your target size — it will only ever shrink. Use a value above1(the default is3) 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
hrefis#some-step-idto 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.csswhich 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 |
navigation
Automatic. Listens for the keyboard and mouse events described in Section 7. No setup needed.
navigation-ui
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/hunits 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-resetresets alldata-rel-*to zero for that step;data-rel-reset="all"also resetsdata-rotate-*.
Warning
Enabling
relintroduces one backward-incompatible change: when a step omitsdata-x/data-y/data-z, the value is inherited from the previous step rather than defaulting to0. If you have an older deck that relied on the old "missing means 0" behavior, add explicitdata-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
idis 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-visibleto revealed substeps andsubstep-activeto 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:stepleaveevents 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).