
Driver.js is a lightweight yet powerful JavaScript library to create an animated, interactive, user-friendly visual guide for any web elements.
Features:
- With or without animations.
- With or without background overlay.
- Highlights web elements when the guide is active.
- Popover style step-by-step guide.
Basic usage:
1. Installation.
# Yarn $ yarn add driver.js # NPM $ npm install driver.js --save
2. Import Driver.js.
<link rel="stylesheet" href="/path/to/dist/driver.min.css"> <script src="/path/to/dist/driver.min.js"></script>
// OR as an ES module
import { driver } from "driver.js";
import "driver.js/dist/driver.css";3. Create a new Driver instance, and we’re ready to go.
// required if using UMD mode const driver = window.driver.js.driver; // initialize driver.js const driverObj = driver();
4. Highlight a specific element within the document.
driverObj..highlight({
element: "#element",
popover: {
title: "Popover Title",
description: "Description"
}
});5. Create a step-by-step guided tour.
const driverObj = driver({
showProgress: true,
steps: [
{
element: '#element 1',
popover: {
title: 'Step 1',
description: 'Description 1',
side: "left",
align: 'start'
}},
{
element: '#element 2',
popover: {
title: 'Step 2',
description: 'Description 2',
side: "right",
align: 'start'
}},
// ...
]
});
// start the guide
driverObj.start();6. Add Hints to guided tours.
import { hints } from "driver.js/hints";
import "driver.js/dist/hints.css";const productHints = hints({
// Array of hints, documented below.
hints: [{
// Selector, element, or a function returning one. A hint whose element
// is missing is skipped and picked up again on the next show().
element: "#export-btn",
// Stable identity, used by open/dismiss/restore and in the hooks.
// Defaults to the hint's index.
id: "export",
// Where the beacon sits on the element's box, and how it looks.
beacon: { side: "top", align: "end", animate: true, className: "" },
popover: {
title: "Export your data",
description: "Download this report as CSV or PDF.",
side: "bottom",
align: "start",
popoverClass: "my-theme",
// The dismiss button; hide it for popovers you dismiss programmatically.
showButton: true,
buttonText: "Got it",
// Overrides the instance-level onButtonClick for this hint.
onButtonClick: (element, hint, { config, hints }) => {},
onPopoverRender: (popover, { hint, hints }) => {},
},
// Hint-level hooks, taking precedence over the global ones.
onOpen: (element, hint, opts) => {},
onDismiss: (element, hint, opts) => {},
// Anything you want to carry along; available wherever the hint is.
data: {},
}],
// Defaults applied to every hint's beacon; a hint's own values win.
beacon: { side: "top", align: "end", animate: true, className: "" },
// Text of the dismiss button. Defaults to "Got it".
buttonText: "Got it",
// Class and offset for the hint popovers, same meaning as in tours.
popoverClass: "my-theme",
popoverOffset: 10,
// Dim the page while a hint is open. Off by default.
overlay: false,
overlayColor: "#000",
overlayOpacity: 0.7,
// Called when a hint popover is opened / a hint is dismissed.
onOpen: (element, hint, { config, hints }) => {},
onDismiss: (element, hint, { config, hints }) => {},
// Runs instead of dismissing when the button is clicked, like a
// tour's onNextClick takes over the default advance. Call
// hints.dismiss(hint.id) yourself to also remove the hint.
onButtonClick: (element, hint, { config, hints }) => {},
});
productHints.show();// mount the beacons
productHints.show();
// remove beacons and listeners; show() brings them back
productHints.hide();
// open a hint's popover programmatically
productHints.open("export");
// close the open popover, keeping its beacon
productHints.close();
// dismiss a hint, firing onDismiss
productHints.dismiss("export");
// bring a dismissed hint back
productHints.restore("export");
// replace the hints; resets dismissals
productHints.setHints([...]);
// the configured hints
productHints.getHints();
// the hint whose popover is open, if any
productHints.getActive();
// whether the beacons are currently shown
productHints.isVisible();
// reposition after layout changes
productHints.refresh();7. All possible options for Driver.js.
const driverObj = driver({
// Array of steps to highlight. You should pass
// this when you want to setup a product tour.
steps?: DriveStep[];
// Whether to animate the product tour. (default: true)
animate?: boolean;
// Anmation duration in ms
duration?: number;
// Overlay color. (default: black)
// This is useful when you have a dark background
// and want to highlight elements with a light
// background color.
overlayColor?: string;
// Lock body scroll while a tour is active.
allowScroll?: boolean;
// Whether to smooth scroll to the highlighted element. (default: false)
smoothScroll?: boolean;
// Whether to allow closing the popover by clicking on the backdrop. (default: true)
allowClose?: boolean;
// Opacity of the backdrop. (default: 0.5)
overlayOpacity?: number;
// Distance between the highlighted element and the cutout. (default: 10)
stagePadding?: number;
// Radius of the cutout around the highlighted element. (default: 5)
stageRadius?: number;
// Whether to allow keyboard navigation. (default: true)
allowKeyboardControl?: boolean;
// Whether to disable interaction with the highlighted element. (default: false)
disableActiveInteraction?: boolean;
// Skip a step whose target element is specified but missing from the DOM,
// moving on in the direction of travel instead of showing the centered
// fallback popover. Steps without an element are intentional centered steps
// and are never skipped. Can be configured at the step level. (default: false)
skipMissingElement?: boolean;
// If you want to add custom class to the popover
popoverClass?: string;
// Distance between the popover and the highlighted element. (default: 10)
popoverOffset?: number;
// Array of buttons to show in the popover. Defaults to ["next", "previous", "close"]
// for product tours and [] for single element highlighting.
showButtons?: AllowedButtons[];
// Array of buttons to disable. This is useful when you want to show some of the
// buttons, but disable some of them.
disableButtons?: AllowedButtons[];
// Whether to show the progress text in popover. (default: false)
showProgress?: boolean;
// Template for the progress text. You can use the following placeholders in the template:
// - {{current}}: The current step number
// - {{total}}: Total number of steps
progressText?: string;
// Text to show in the buttons. `doneBtnText`
// is used on the last step of a tour.
nextBtnText?: string;
prevBtnText?: string;
doneBtnText?: string;
// Called after the popover is rendered.
// PopoverDOM is an object with references to
// the popover DOM elements such as buttons
// title, descriptions, body, container etc.
onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State }) => void;
// Hooks to run before and after highlighting
// each step. Each hook receives the following
// parameters:
// - element: The target DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
// Hooks to run before and after the driver
// is destroyed. Each hook receives
// the following parameters:
// - element: Currently active element
// - step: The step object configured for the currently active
// - options.config: The current configuration options
// - options.state: The current state of the driver
onDestroyStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onDestroyed?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
// Hooks to run on button clicks. Each hook receives
// the following parameters:
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
onDoneClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;;
});8. Available options for steps.
{
// The target element to highlight.
// This can be a DOM element, or a CSS selector.
// If this is a selector, the first matching
// element will be highlighted.
element: Element | string;
// The popover configuration for this step.
// Look at the Popover Configuration section
popover?: Popover;
// Callback when the current step is deselected,
// about to be highlighted or highlighted.
// Each callback receives the following parameters:
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onDeselected?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
onHighlightStarted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
onHighlighted?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void;
}9. Available popover options.
{
// Title and descriptions shown in the popover.
// You can use HTML in these. Also, you can
// omit one of these to show only the other.
title?: string;
description?: string;
// The position and alignment of the popover
// relative to the target element.
side?: "top" | "right" | "bottom" | "left";
align?: "start" | "center" | "end";
// Array of buttons to show in the popover.
// When highlighting a single element, there
// are no buttons by default. When showing
// a tour, the default buttons are "next",
// "previous" and "close".
showButtons?: ("next" | "previous" | "close")[];
// An array of buttons to disable. This is
// useful when you want to show some of the
// buttons, but disable some of them.
disableButtons?: ("next" | "previous" | "close")[];
// Text to show in the buttons. `doneBtnText`
// is used on the last step of a tour.
nextBtnText?: string;
prevBtnText?: string;
doneBtnText?: string;
// Whether to show the progress text in popover.
showProgress?: boolean;
// Template for the progress text. You can use
// the following placeholders in the template:
// - {{current}}: The current step number
// - {{total}}: Total number of steps
// Defaults to following if `showProgress` is true:
// - "{{current}} of {{total}}"
progressText?: string;
// Custom class to add to the popover element.
// This can be used to style the popover.
popoverClass?: string;
// Hook to run after the popover is rendered.
// You can modify the popover element here.
// Parameter is an object with references to
// the popover DOM elements such as buttons
// title, descriptions, body, etc.
onPopoverRender?: (popover: PopoverDOM, options: { config: Config; state: State }) => void;
// Callbacks for button clicks. You can use
// these to add custom behavior to the buttons.
// Each callback receives the following parameters:
// - element: The current DOM element of the step
// - step: The step object configured for the step
// - options.config: The current configuration options
// - options.state: The current state of the driver
onNextClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
onPrevClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
onCloseClick?: (element?: Element, step: DriveStep, options: { config: Config; state: State }) => void
}10. API methods.
// Start the tour using `steps` given in the configuration
driverObj.drive(); // Starts at step 0
driverObj.drive(4); // Starts at step 4
driverObj.moveNext(); // Move to the next step
driverObj.movePrevious(); // Move to the previous step
driverObj.moveTo(4); // Move to the step 4
driverObj.hasNextStep(); // Is there a next step
driverObj.hasPreviousStep() // Is there a previous step
driverObj.isFirstStep(); // Is the current step the first step
driverObj.isLastStep(); // Is the current step the last step
driverObj.getNextStep(); // Gent the next step
driverObj.getActiveIndex(); // Gets the active step index
driverObj.getActiveStep(); // Gets the active step configuration
driverObj.getPreviousStep(); // Gets the previous step configuration
driverObj.getActiveElement(); // Gets the active HTML element
driverObj.getPreviousElement(); // Gets the previous HTML element
// Is the tour or highlight currently active
driverObj.isActive();
// Recalculate and redraw the highlight
driverObj.refresh();
// Look at the configuration section for configuration options
// https://driverjs.com/docs/configuration#driver-configuration
driverObj.getConfig();
driverObj.setConfig({ /* ... */ });
driverObj.setSteps([ /* ... */ ]); // Set the steps
// Look at the state section of configuration for format of the state
// https://driverjs.com/docs/configuration#state
driverObj.getState();
// Look at the DriveStep section of configuration for format of the step
// https://driverjs.com/docs/configuration/#drive-step-configuration
driverObj.highlight({ /* ... */ }); // Highlight an elementAlternatives:
- Create Interactive Web App Tours in Under 10KB – GTourJS
- 10 Best Tour Plugins To Guide Visitors Through Your App
Changelog:
v1.8.0 (07/18/2026)
- Added Hints: pulsing beacons that open a popover on click; overlay optional, the page stays interactive.
- Added advanceOnClick (driver and step level) to advance the tour by clicking the highlighted element itself.
- Added waitForElement (driver and step level) to wait up to N ms for a step’s element before treating it as missing.
- Changed Popover internals shared between tours and hints.
- Fixed skipMissingElement: the last reachable step now shows Done and runs onDoneClick; step queries like isLastStep() account for skips.
v1.7.0 (07/14/2026)
- Added skipMissingElement option to skip a step whose target element is missing
- Added index on the options passed to every hook
- Added –driver-popover-font-family CSS variable to set the popover font
- The popover title and description now render in the default font stack. Set –driver-popover-font-family to use your own
- Fixed bugs
v1.6.0 (06/26/2026)
- Added animationDuration config to control how long the highlight transition takes.
- Added allowScroll config to lock body scroll while a tour is active.
- Added onDoneClick hook, fired when the done button on the final step is clicked.
- Added data property on a step for passing arbitrary data, accessible from hooks for custom per-step logic.
- Custom popover footer buttons no longer get auto styled, style them using .driver-popover-footer button selector.
- The popover exposes driver-popover-side-* and driver-popover-align-* classes as per the rendered side and alignment.
- Fixed bugs.
v1.5.0 (06/24/2026)
- Add done-btn class to next button
- Pass final state to onDestroyed hook
- Keep tour open on arrow-left at step 1
- Remove button text-shadow ghost text
- Fire onNextClick on overlay nextStep
- Add getNextStep to the driver API
- Remove unicode characters from buttons
v1.4.0 (11/19/2025)
- overlayClickBehavior now supports callbacks
v1.3.6 (05/13/2025)
- Bugfixes
v1.3.4 (02/02/2025)
- Bugfixes
v1.3.1 (11/11/2023)
- Update
v1.3.0 (09/11/2023)
- Update vite configuration to support ES2019
- Popover title to support HTML
- Fixes wrong type definition for onPopoverRender configuration
- Add validation on class name
- Upgrade all the dependencies to latest
v1.2.0 (07/24/2023)
- Adds new disableActiveInteraction config to disable interaction with the active element.
- Bugfixes
v1.1.0 (07/24/2023)
- Implemented focus trapping
- Adds ARIA attributes and use of semantic markup.
v1.0.3 (07/07/2023)
- Rewritten in TypeScript.
- Popover is much more intelligent in its placement
- Supports async steps to allow more dynamic and interactive guides
- Support for non-element steps (i.e. where you just want to show a popup on screen)
- Ask for confirmation before exit
- Support for scrollable elements
- Allows showing progress during product tours
- More customizable than ever with more hooks
- Improved documentation with code samples for usage
- Popover hooks allow you to have more control over the popover rendering
v0.9.8 (03/21/2020)
- Resolve merge conflicts
v0.9.8 (02/29/2020)
- Adds step counter feature
v0.9.7 (06/15/2019)
- Updates Dependencies
v0.9.6 (06/01/2019)
- Fix touch issue
- Error when hiding on an element without popover
v0.9.3 (02/24/2019)
- Update
v0.9.2 (02/10/2019)
- Add more options
- Doc updated
v0.7.1 (10/12/2018)
- Add more options
- Optimize
v0.6.0 (06/30/2018)
- Add support for asynchronous actions
v0.5.2 (05/23/2018)
- Add keyboardControl option and typo in readme







