UI composition & animation in pure HTML


One concept for all your UX patterns

UX patterns like menus, sliders, layers & lightboxes, parallax effects, page-swipes, zoom effects, etc. are really just interactive animated layers. layerJS is a simple open source library that provides one simple universal concept to create such patterns in pure HTML.

How layerJS works

In layerJS Frames are containers that contain your content, like sub pages, menues, lightboxes, cards, slides, etc. These are fit into Stages which are like virtual windows in which UI interaction happens. Watch the animation on how it works:


▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄

▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄ ▄▄▄▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄

▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄



▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄



▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄



▄▄▄▄ ▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄

Play Replay




One library for all UX patterns. Slider, Popups, Accordeon, Menu, Parallax, (Touch) Gestures, etc.



Layout your interface with HTML attributes and define interaction with Links


Plays with

Angular, VueJS, React, jQuery. Use your framework to modify frame content or generate frames dynamically.


All designs

Totally design agnostic. layerJS just provides the navigation effects while leaving the design up to you.



30kb minimized gezipped. No dependencies.



Works on mobile or desktop. Use your choice of mediaqueries. Adds even more options to fit content to different screens.

Define in pure HTML

<div lj-type="stage">
  <div lj-type="layer">
    <div id="f1" lj-type="frame">
      … your HTML code …
    <div id="f2" lj-type="frame">
      … your HTML code …

Simply define Stages and Frames by adding attributes to HTML elements. Define the dimensions of the Stages through CSS. Layers allow overlaying Frames. Each Stage needs at least one Layer. Use HTML links to trigger transitions, e.g.

<a href="#f2">Frame 2</a>

To make everything work simply include layerJS in the head of your document. Our Sponsor KeyCDN will provide you with ultrafast server access to the library.

<script src=""></script>
<link href="" type="text/css" rel="stylesheet" /> 

Fitting modes & responsiveness

Since your content will display on various screen sizes, the aspect ratios of your Stages and Frames will generally not match. layerJS offers different fitting modes, including width, height, cover, contain, responsive, responsive-width, responsive-height. Just select a mode using an HTML attribute:

<div lj-type="frame" lj-fit-to="responsive-width"></div>

Depending on the fitting mode, scrolling may occur. The initial scroll position can be any of top, left, bottom, right, center, top-center, bottom-left, etc.. This will be set with:

<div lj-type="frame" lj-start-position="top"></div>

You can disable scrolling using

<div lj-type="frame" lj-no-scrolling="true"></div>

You can still define an initial "scroll" position to specify the alignment of the Frame.

▄▄▄▄▄▄▄ ▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄▄▄


▄▄▄▄▄▄ ▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄▄▄

Every Layer has an active Frame. Transitions are exchanging the current active Frame of a Layer with a target Frame using an animation. Different transition types exist, among others left, right, up, down, fade, blur, zoomin, zoomout. The active Frame can become the special "!none" Frame in which case no Frame is shown. You can specify the transition type in a link (see "Routing" section) or as Frame or Layer attribute:

<div lj-type="frame" lj-transition="left"></div>

Layouts define which Frames are shown where. The default Layout is the Slide-Layout which only shows the active Frame fitted into the Stage. During a transition the current Frame and the target FRame are shown. See the Layouts sections in the Wiki.

Interstage transitions allow sending Frames across Layers and Stages. This allows for example to "zoom" a Frame from a grid to fullscreen.

Control with CSS

Alternative to controlling layerJS by HTML attributes (lj-* or data-lj-*) you can also use custom CSS properties. The advantage is that you can make the behaviour itself responsive by using media queries.

#menu {
  width: 100px;
  --lj-fit-to: responsive-height;
  --lj-transition: left;
@media (max-width: 640px) {
  #menu {
    --lj-fit-to: responsive;
    --lj-transition: fade;

The above example will modify the fitting mode and the transition type of a frame with id menu for screens smaller than 640px.

You can use any layerJS attribute also in CSS except lj-type, lj-name. You can mix CSS properties and HTML attributes, in which case CSS properties will precede.

▄▄▄▄▄▄▄ ▄▄▄▄

▄▄ ▄▄ ▄▄

▄▄▄▄ ▄▄▄▄

▄▄ ▄▄ ▄▄

Routing & State

▄▄▄▄▄▄ ▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄▄▄

Using a standard HTML link you can trigger transitions. The link should contain a '#' followed by the Frame name or id. This will make the Frame the active Frame in the containing Layer.

<a href="#f1&p=right&t=1s"></a>
You can add the parameters 'p' for the transition type and 't' for the transition duration.

There exist special Frames like !none, !next, !prev. You will need to specify a Layer id or name in order to use them:

<a href="#sliderlayer.!next"></a>
If you specify a Layer and a Frame from a different Layer you will trigger an interstage transition.
<a href="#otherlayer.f1"></a>

The State of the UI defines which Frames are in which Layers (and hence in which Stages) and which Frames are active. The State is represented by an array of paths:

stage.contentlayer.home stage.menulayer.leftmenu
You can supply such an array as link using ';' as separator to trigger several transitions at the same time. It is usually sufficient to only supply Layer name and Frame name and only supply the paths that should change:
<a href="#contentlayer.f2;menulayer.!none"></a>

Transitions change the State. The State will be represented by the URL. When you transition from 'f1' to 'f2' the URL will change: -->
The URL will only show State information that diverts from the default State. Generally, the first Frame in a Layer will be the default active Frame unless you specify a default Frame using:
<div lj-type="layer" id="menulayer" lj-default-frame="!none"></div>
URL modifications can be disabled per Layer using the 'lj-no-url' Layer attribute.


Gestures can trigger transitions. This includes touch gestures and swipes on the touchpad. There exist 4 directions left, right, up, down. Those directional gestures will trigger transitons to frames that are specified in the neigbor property of the Frame.

<div lj-type="frame" id="f2" lj-neighbors.l="f1" lj-neighbors.r="f3"></div>

▄▄▄▄▄▄ ▄▄▄▄

▄▄▄▄▄▄▄ ▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄▄▄

One finger swipe left gesture outlined hand symbol free icon

Feedback & questions

Your feedback is very welcome! If you have any questions or comments please contact us at We are continiously improving layerJS so with your feedback you can help shaping the future development.

Also please checkout our "Getting started" tutorial, examples, FAQ and Wiki for more detailed documentation of the layerJS functions.