Public API
All of it is available. It is written down so that the milestones and the EchoEditor builder work to the same contract. Instance methods follow EchoEditor: on, destroy, and for the slider go, next, prev, current.
Loading
<link rel="stylesheet" href="/echobox/dist/echobox.min.css">
<script src="/echobox/dist/echobox.min.js" defer></script>
The classic script sets the globals. The ES module exports the same names and sets no global: import { EchoBox } from '/echobox/dist/echobox.esm.min.js'.
EchoBox
| Member | Status | Purpose |
|---|---|---|
EchoBox.version | available | The version |
EchoBox.registerLanguage(code, entries) | available | Adds a language, or adds to one. en and cs are in the bundle, the others will be separate files (D-012). The language comes from <html lang>, and English fills what a language lacks. The slider's keys are slider.carousel, slider.slide, slider.prev, slider.next, slider.pause, slider.play, slider.slides, slider.goTo, the lightbox's lightbox.dialog, lightbox.close, lightbox.prev, lightbox.next, lightbox.image, lightbox.item, lightbox.error, lightbox.zoom, lightbox.play, lightbox.pause, lightbox.fullscreen, lightbox.thumbs |
EchoSlider
Available.
const slider = EchoSlider.create(el, {
slidesToShow: 3,
transition: 'push', // the default, or 'fade', 'fade-push', 'circle', or an effect name
from: 'right', // 'right', 'left', 'bottom', 'top'
fallback: 'fade-push', // for an effect, when GSAP is missing
reveal: { h2: 'from-left', p: 'from-bottom' },
});
slider.next();
slider.prev();
slider.go(2);
slider.current;
const off = slider.on('change', ({ current, previous }) => {});
slider.destroy();
const all = EchoSlider.bind('[data-slider]', options);
all.destroy();
EchoSlider.registerTransition(name, ({ incoming, outgoing, sign, vertical, duration, ease, mode, animate, done }) => ({ cancel() {} }));
Each child of the element is a slide. Options keep Slick's names where they exist (D-008, D-023), and one Slick does not have here is ignored. The attribute data-slider holds the same options as JSON, and options in the call go over it. A second create on an element gives the same slider. go takes a whole number and ignores anything else. change comes once the move has started, so a listener may move the slider itself. Arrow keys with a modifier stay the browser's.
| Option | Default | Purpose |
|---|---|---|
slidesToShow | 1 | How many are in view, a fraction such as 1.6 for a part of the next one. Above 1 always uses push |
centerMode | false | The current slide stands in the middle, with parts of its neighbours on both sides when slidesToShow is a fraction above 1 (D-030) |
arrows, dots | true, false | The controls. With no more slides than fit, there are none |
infinite | true | The loop. Without it the arrows say so with aria-disabled |
speed | 500 | Milliseconds. 0 changes at once |
ease | 'power2.out' | As in EchoReveal |
transition | 'push' | push, fade, fade-push, circle (D-031), or an effect by name: parallax, wipe, curtain, zoom, stack, and in 3D and depth cube, door, dive (D-032). A name nobody knows gives a fade |
fade | false | true means transition: 'fade' |
from | 'right' | Where the next slide comes from. Going back comes from the other side, and the keys follow |
fallback | 'fade-push' | What an effect becomes without GSAP |
swipe | true | Dragging. See below |
autoplay, autoplaySpeed | false, 3000 | Moves by itself. With infinite: false it goes back to the first from the last. A slide whose video has data-len shows that many milliseconds instead. It waits while a modal dialog, such as the lightbox, is open |
pauseOnHover, pauseOnFocus | true, true | What holds it. Only focus from the keyboard counts, not a click |
useAutoplayToggleButton | true | The button that stops it and the videos of the slides, which WCAG 2.2.2 needs |
reveal | {} | Classes to add inside each slide, by selector |
revealOptions | {} | For that content: distance (24), duration (600), delay (150), stagger (60), ease |
regionLabel | null | The name of the region. Without it, or an aria-label or aria-labelledby of the site, it is "Slides" |
appendArrows, appendDots | null | A selector or an element to put them in |
responsive | [] | [{ breakpoint: 900, settings: {} }]. Only the smallest breakpoint the window is under counts, the current slide stays, and a pause the visitor asked for stays |
bodyClass | false | A class on <body> that names the slider and its slide, counted from 1: true takes the slider's id, as slider-home-slide-2, and a string is the name instead. A name that starts with slider-, as the builder's ids do, is not doubled: slider-hdfojg-slide-1 (D-033). See below |
motion | 'auto' | See Motion |
animate | by the classes, or 'auto' | See Motion |
A GSAP effect runs only when named (D-019). A site's own transition runs only with all motion: with animate: 'reduced' a fade plays instead (D-028). reveal adds reveal classes to what its selectors find inside each slide, and that content comes in when its slide becomes current, on GSAP when it is on the page and natively when it is not. .reveal and [data-reveal] already in a slide's HTML come in the same way. A fast swipe leaves nothing half way. A bind of EchoReveal leaves all of this to the slider, whichever of the two runs first.
One swipe moves at most one slide, however hard (D-020). A drag counts as a move from a fifth of a slide, or a shorter one at 0.4 pixels per millisecond. Only push follows the finger. During a move, input counts from the slide the move was heading for (D-022).
The arrow keys work while focus is inside the slider, except in a form field. Up and down on a vertical slider.
The page by the slide. With bodyClass, <body> has one class for each such slider, slider-<name>-slide-<n>, which changes as a move starts, before change. A breakpoint does not change the name. The page may write the first one itself, for the first paint, and destroy puts back the classes of <body> as they were; only if the page changed them meanwhile does it just remove its own. true on a slider without an id, or a name with a space, gives a warning and no class.
arrows: false with dots: false leaves only dragging for a pointer, which WCAG 2.5.7 does not allow on its own. A site that does this needs its own controls, through go, next and prev.
Videos. A <video> with autoplay in a slide plays only while its slide shows, the slider is in view and its autoplay is not stopped, by the button or, on animate: 'auto', by reduced motion (D-026, D-028). A slide that comes in plays its videos from the start. List the sources as CORE does, with the mp4 first, which every browser plays. destroy lets every video play, as its markup asks. A video the visitor starts is left alone.
Images. Write loading="lazy" in the HTML on all but the first, and the slider wakes what is about to show. A slide's own <img> or <video>, also inside a link or a <picture>, fills the slide with object-fit: cover: slides are as tall as the tallest, so photos of another shape or a taller video leave no gap, and a slider with a height of its own crops them all to it (D-029). A site keeps the image's own shape with a rule that names its slider, such as #gallery .slide > img { height: auto }. Before the script, [data-slider] is a row a visitor can scroll, with the widths of the slider: see the builder brief for several in view. For slidesToShow above 6, or in a slider without data-slider, set --per-view in the site's CSS. Spacing between slides goes inside the slide (D-021).
Centred, or a part of the next. Every slide is as wide as the others, 100% / slidesToShow. Only a slide that shows whole can be reached, and one that shows in part is inert until it is current. A centred move needs a spare slide beyond those that show at all, so with 1.6 in view it moves from 4 slides, and with fewer it changes at once. Slick's variableWidth is ignored: a site that used it with slides of one width sets the fraction they filled, such as slidesToShow: 1.6, and keeps its responsive. For the first paint, a fraction needs --per-view in the site's CSS, as the stylesheet reads only whole numbers from the attribute.
EchoLightbox
Available, with zoom, thumbnails, a slideshow and full screen (D-024, D-025), for images, videos, pages in a frame and content of the page (D-027).
const binding = EchoLightbox.bind('[data-lightbox], [data-fancybox]', { thumbs: true }); // the defaults
binding.destroy(); // also closes a lightbox it opened
const box = EchoLightbox.open([{ src, type, thumb, alt, caption }], { start: 0, thumbs: true }); // null with no items
box.current;
box.go(1);
box.close();
| Option | Default | Purpose |
|---|---|---|
thumbs | true | false opens with the thumbnails hidden, as the eshop does. Their button shows them |
animate | by the classes, or 'auto' | See Motion. Read when it opens: for bind from the classes of the link and around it, for open from those of <html> |
start | 0 | open only: the item shown first |
type of an item | src | Shows |
|---|---|---|
image, the default | the image | the image, which zooms |
video | a video file, or the address of a video on YouTube or Vimeo | the video with its controls, or the player in a frame |
iframe | an http or https address | the page in a frame |
inline | #id of an element of the page | the element itself |
bind opens the items of a group from a click on one of them, also on links added later (D-024). Links with the same value of data-lightbox or data-fancybox form a group in the order of the page, hidden ones included, and a link without a value opens alone. A link counts as fancyBox reads it (D-027): by data-type (image, video, iframe or inline), by an #id in data-src or href, or by the end of its path, from data-src before href. .avif, .bmp, .gif, .jpg, .jpeg, .png, .svg and .webp are images, .mp4, .m4v, .webm, .ogv and .mov videos, and .pdf a page in a frame. A link to a video on YouTube or Vimeo opens its player, YouTube's from youtube-nocookie.com, which the site's policy must allow in frame-src. Any other link, data-type="ajax" included, and a click with Shift, Ctrl, Alt or Meta, keeps its own way. A second lightbox closes the first. Links in a slider work the same, those in slides out of view included, and a drag that starts on one opens nothing (D-026).
- Name of an item: the
altof the thumbnail, or the text of a link without one, then the caption, then "Image n", or "Item n" for one that is not an image. - Caption:
data-captionas plain text, or thefigcaptionof a figure that holds this one link. - Moving: the arrows, the arrow keys and a swipe move one item, round the group.
- Closing: Escape, the close button, or a click beside the item that also began there. The focus goes back to the link.
- Loading: the image or the video shown and one to each side. One that fails, a missing element, and a frame's address that is not
httporhttpssay so. - Videos, pages and content: a video plays while it shows and pauses when left, and a press or the arrow keys on it are its own, also in a slider. A frame is made when its item shows and removed when it is left, so its page loads again. Content of the page moves into the lightbox, shown though
hiddenor adisplay: nonestyle hid it, and goes back where it was, hidden again, when the lightbox closes. - The page behind is inert and keeps its place and its width. Where nothing may move (see Motion) it opens and moves at once.
- Zoom: a click or a tap on an image zooms in at that point and out again, the wheel and a pinch zoom freely, and zoomed in a drag or the arrow keys pan. The zoom button does the same at the middle. An image goes no further than its own size.
- Thumbnails: a row of buttons under the image, from the thumbnails on the page, or from
thumbof an item given toopen. An image without one is its own thumbnail, so the strip loads it in full: give large images athumb. A video shows the play icon, and a page or content another. - Toolbar: zoom, the slideshow at 3 seconds an item, waiting while a video plays, full screen where the browser offers it, thumbnails, and close.
- Opening: the first image grows from its thumbnail when it loads within 400 ms.
EchoZoom
Available. The lightbox uses it for each image (D-025).
const zoom = EchoZoom.create(img); // its parent is the frame
zoom.zoomed; // zoomed in
zoom.zoomable; // larger than its place
zoom.toggle(); // in at the middle of the frame, or out again
zoom.panBy(x, y); // pixels, zoomed in, within the edges
zoom.growFrom(rect); // plays the image growing from a box of the page, such as its thumbnail
zoom.reset();
zoom.destroy();
It zooms an image, as far as the image's own size, so one no larger than its place has nothing to zoom. The parent of the image is the frame: it should clip what overflows, and the image's edges never come inside it. A click or a tap zooms in at its point and out again, the wheel and a pinch zoom freely, and zoomed in a drag pans. The image moves by its own scale and translate, so a site should not set those on it. The keys are the caller's: the lightbox pans with the arrows through panBy. EchoZoom.create(img, { animate }) takes the setting of Motion, and with 'reduced' it jumps, as a zoom has nothing to fade. changed in the options is called when zoomed or zoomable may have changed, for the site's own zoom button; read both once after create too, as an image already loaded says nothing until the pointer comes to it. On a page, a touch on the image that is not a pinch belongs to the page: give the image touch-action: pan-y, and none while it has the class ebx-zoomed, as the demo does.
EchoReveal
Available.
const reveal = EchoReveal.bind();
const reveal = EchoReveal.bind({ '.card > h2': 'from-left', '.card > p': 'from-bottom' }, { once: true });
reveal.destroy();
Call it when the document is parsed: in a defer script, or from DOMContentLoaded.
The existing markup works as it is: .reveal with .from-left, .from-right, .from-top or .from-bottom, and [data-reveal]. [data-reveal="photo"] opens from a clip while its img settles from a slight scale. [data-reveal="row"] is the same as [data-reveal]. Without a side, an element comes from below, or from above when it enters over the top edge.
The first argument adds classes by selector, reveal always among them, and destroy() removes what it added. Rules run before anything else, so a rule's classes decide the direction. Inside an EchoSlider its reveal option does this instead, because a bind takes its trigger from the viewport (D-019).
| Option | Default | Purpose |
|---|---|---|
distance | 8 | Pixels an element travels |
duration | 600 | Milliseconds. A photo takes 4/3 of it, and its image twice. 0 shows an element at once |
ease | 'power2.out' | 'power2.out', 'expo.out' or any CSS easing run natively. Any other GSAP ease needs GSAP on the page, and becomes power2.out without it |
stagger | 60 | Milliseconds between elements that come in together |
once | true | false hides an element again when it leaves the viewport, and plays it again when it returns |
motion | 'auto' | See Motion |
animate | by the classes, or 'auto' | See Motion. Each element's own, read when it binds |
The hidden state. The stylesheet hides .reveal and [data-reveal] from the first paint, where the nearest class of Motion lets them move, and without a class unless the system asks for less motion. Without a script and in print nothing is hidden. An animate given only to bind does not reach the stylesheet, so give it as a class in the HTML. If nothing binds, a failsafe shows them after 4 seconds, and a script that arrives later plays the entrance over what is already visible.
- An element selected only by a rule is not hidden before the script runs, so if it is in view at load it can flash. Classes in the HTML avoid that.
bindsets the classebx-revealon<html>, and it stays afterdestroy(). A page that keeps its own reveal code while it migrates writes<html class="ebx-reveal">, which turns the hidden state off.- A second
bindleaves the elements of the first alone. To run a reveal on content added later, bind again.
EchoCounter
Available.
<b data-count="18900" data-suffix=" Kč">18 900 Kč</b>
<b data-count="3.4" data-dec="1" data-suffix=" %">3,4 %</b>
const counter = EchoCounter.bind({ duration: 2000 });
counter.destroy();
It counts when the element comes into view, and ends on the text of the HTML. data-dec sets the decimals, from 0 to 20: anything else is an error in the console, and also stops the counters that came into view with it. data-suffix follows the number, with its first space made unbreakable. Values on the way are formatted in the language of <html lang>. A number between 1000 and 2100 without decimals or a suffix reads as a year: it starts 40 lower and is not grouped. Without a script, or where nothing may move (see Motion), the text stays. An element without a text gets the formatted number. An element with child elements, or whose data-count is not a number, is left alone. Options: duration, motion, animate.
Motion
How much moves is animate, alike for all five components (D-028).
animate | Moves | Meant for |
|---|---|---|
'auto' | Everything, or nothing when the visitor's system asks for less motion (on Windows, Animation effects turned off) | Institutions. The default |
'off' | Nothing, whatever the system allows | |
'reduced' | Fades only, whatever the system asks: nothing travels, grows or is clipped | E-shops |
'always' | Everything, whatever the system asks | Presentation sites |
A page sets it with a class on <html>, a part of the page or one component with a class on its element or around it, and a script with the option animate, also in data-slider:
<html class="ebx-animate-reduced">
<div id="slider-home" class="slider-fullscreen ebx-animate-always" data-slider>
The option wins, then the nearest class, and without either it is 'auto'. With 'reduced' a push puts the slide in place at once and fades it in, an effect, fade-push or circle becomes a fade, the content of a slide and a reveal only fade in, the lightbox fades its background and its images, and a zoom jumps. The autoplay and the videos of a slider run with 'reduced' and 'always' under reduced motion too, and the stop button stays as useAutoplayToggleButton says: without it, WCAG 2.2.2 is the site's to meet. The counter counts with both. A slider reads the classes at each move, the lightbox when it opens, a reveal when it binds, and a counter when its element comes into view.
Which engine runs it is motion: 'auto' | 'gsap' | 'native', see D-002 and architecture.md. 'gsap' on a page without GSAP runs natively. animate: 'off' replaces the former motion: 'none'.