Frequently asked questions.
PAGE 08The questions that come up most often, answered directly. If yours is not here, the discussions board is the right place to ask.
Getting started
What is EPaper?
EPaper is an open-source library of 81 web components built for e-paper and e-ink (also spelled "eink") displays. The components are vanilla custom elements — they extend HTMLElement directly, use no Shadow DOM, ship no animations and depend on no framework.
It is published as @marcomattes/epaper-components under the MIT licence, and the full barrel is roughly 58 KB brotli.
Do I need a build step or a framework?
No. The elements register themselves on import and upgrade any matching tags already in the document, so a plain <script type="module"> in an HTML file is enough.
A bundler helps if you want to import individual components rather than the whole barrel, but nothing about the library requires one.
<link rel="stylesheet" href="…/styles/tokens.css">
<link rel="stylesheet" href="…/styles/base.css">
<link rel="stylesheet" href="…/styles/components.css">
<script type="module" src="…/index.js"></script>
<div class="ink-page">
<e-title level="1">Hello, e-paper.</e-title>
<e-button variant="primary">Get started</e-button>
</div>
Can I import a single component instead of all of them?
Yes. Every component has its own sub-path export, so @marcomattes/epaper-components/button registers <e-button> and nothing else.
Styles are separate from the JavaScript: the three stylesheets are shipped whole, so a page importing one component still links the same CSS.
import '@marcomattes/epaper-components/button';
import '@marcomattes/epaper-components/input';
// Only <e-button> and <e-input> are defined.
Which browsers are supported?
Evergreen Chrome, Edge, Firefox and Safari. The two hard requirements are custom elements and ElementInternals with form association, which Safari was last to ship in 16.4.
There is no polyfill path for older browsers, and none is planned — the form controls depend on ElementInternals behaviour that a polyfill cannot reproduce faithfully.
E-paper and rendering
Do I need an e-paper display to use this?
No. The components are ordinary web components and render normally on any screen. The e-paper constraints — no animation, no hover, high contrast — produce a stark, print-like interface that works fine in a browser.
People use it for kiosks, embedded panels, print-oriented layouts and low-distraction interfaces as well as for actual e-ink hardware.
Why are there no animations or transitions?
Because an e-paper controller redraws in discrete waveform cycles rather than frames. A 300 ms fade is not a smooth gradient on e-ink — it is a few dozen full-region refreshes queued faster than the panel can drain them, each one a visible flash.
base.css resets transition and animation globally inside .ink-page, so the guarantee holds even for markup the library did not render.
Why are there no :hover styles?
E-paper devices are touch or button driven and have no pointer, so :hover never matches and anything hidden behind it is unreachable.
The library uses :focus-visible, [aria-selected], [aria-checked] and [data-active] instead. These work on touchscreens generally, not only on e-ink.
What is a "surgical DOM update" and why does it matter?
It means patching individual text nodes and attributes in place rather than reassigning innerHTML. It matters because an e-paper update costs the bounding box of everything that changed — so rebuilding a container to change one number produces a full-panel refresh instead of a small, fast one.
Every EPaper component keeps references to the nodes it owns and updates them through helpers that compare before writing, so an update with no actual change performs no DOM write at all.
Does EPaper talk to the display controller directly?
No, and nothing in a browser can. There is no web API for selecting a waveform mode or triggering a partial refresh.
What the library does is shape the DOM changes so the layers below it — the compositor, the framebuffer, the EPDC — infer a small damaged region and can choose a fast update mode on their own. It is an indirect lever, but it is the only one available from a page.
Will this work on a colour e-paper panel like Kaleido?
Yes. The library is monochrome by default but themed entirely through CSS custom properties, so a colour panel is a matter of setting different token values.
The design advice is to keep colour redundant with something already stated in text — colour e-paper has a narrow gamut and lower contrast than monochrome, so a design that depends on hue tends to disappoint on the actual hardware.
How do I stop ghosting?
Ghosting is residual charge left by fast partial-update waveforms, and the only cure is a periodic clearing refresh. Force a full-page repaint on a schedule — hourly is usually invisible in practice — so the controller selects a clearing waveform and resets the residue.
Reducing the number of partial updates helps more than anything else, which is the point of batching updates onto a single timer rather than painting per event.
Frameworks and integration
Can I use EPaper with React?
Yes, and it got much easier with React 19, which added proper custom-element support — attributes, properties and custom events now work as expected.
On React 18 and earlier you need ref-based event wiring for custom events, because React 18 does not attach listeners for events it does not know about. That is the one genuine friction point, and it is a React limitation rather than a library one.
// React 19: this just works.
<e-input label="Name" onE-change={(e) => setName(e.detail.value)} />
// React 18: wire the listener through a ref.
const ref = useRef(null);
useEffect(() => {
const el = ref.current;
const on = (e) => setName(e.detail.value);
el.addEventListener('e-change', on);
return () => el.removeEventListener('e-change', on);
}, []);
return <e-input ref={ref} label="Name" />;
Does it work with Vue, Svelte or Angular?
Yes, all three handle custom elements and their events natively. Vue needs compilerOptions.isCustomElement configured so it does not warn about unknown tags; Angular needs CUSTOM_ELEMENTS_SCHEMA on the module. Svelte needs no configuration at all.
Can I server-render pages that use EPaper?
Yes, with a caveat about which components. Because there is no Shadow DOM, markup is just markup — an SSR framework emits the tags and the elements upgrade on the client.
The caveat is that components building their DOM from attributes in connectedCallback show nothing until the JavaScript runs. Where content must be readable without scripting, emit the library's markup and class names directly; this site does exactly that for its prose pages.
Is TypeScript supported?
Yes. The package ships type declarations plus a generated HTMLElementTagNameMap augmentation, so document.querySelector('e-input') is typed as EInput without a cast.
How do I theme or rebrand it?
Set CSS custom properties on .ink-page or any ancestor. Colours, border widths, spacing scale and type sizes are all tokens, so a panel vendor can restyle the entire library without touching JavaScript.
The full registry of properties is documented in THEMING.md in the repository.
.ink-page {
--ink-fg: #1a1a1a;
--ink-bg: #f4f2ec;
--ink-border-width: 3px;
--ink-text-body: 18px;
}
Forms and accessibility
Do the inputs work inside a normal <form>?
Yes. Every input is a form-associated custom element built on ElementInternals, so it appears in FormData, participates in constraint validation, responds to form.reset() and restores its value after a back-button navigation.
No hidden <input> shims are involved — the controls are real form participants.
How do I read values out of a form?
With FormData, exactly as you would for native inputs. The e-submit event carries the underlying HTMLFormElement in its detail.
document.querySelector('e-form')
.addEventListener('e-submit', (e) => {
const data = new FormData(e.detail.form);
console.log(Object.fromEntries(data));
});
Is the library accessible?
That is the intent, and several of its constraints push in that direction: no colour-only status cues, no hover-only information, high contrast by default and visible focus rings everywhere.
Components carry appropriate roles and ARIA state, and the absence of Shadow DOM means aria-labelledby and for references work normally rather than needing to cross a shadow boundary. It has not been through a formal third-party audit, so treat it as accessible by design rather than certified.
Does it work with screen readers?
Yes. Interactive components expose their state through ARIA attributes rather than through visual styling alone, and content is in the light DOM where assistive technology reads it without shadow-root traversal.
The project
Is EPaper based on Lit?
No. The components extend HTMLElement directly and have zero runtime dependencies. Lit appears only as a development dependency, used for templating in Storybook stories.
How big is it?
About 58 KB brotli for the full barrel with all 81 components registered. Individual components are far smaller — the size budget enforced in CI is 6 KB for <e-button> and 8 KB for <e-input>, both brotli.
What licence is it under, and can I use it commercially?
MIT, so yes — commercial use, modification and redistribution are all permitted, and the only requirement is that the licence and copyright notice travel with copies of the source.
Is it production ready?
It is at version 1.x with a stable public API, a test suite running in real browsers, visual regression baselines and size budgets enforced in CI.
It is also a young project with a single maintainer. That is a reasonable trade for many teams and the wrong one for others — the code is MIT licensed and the repository is public, so the due diligence is available to anyone who needs to do it.
How do I contribute or report a bug?
Issues and pull requests go to the GitHub repository. CONTRIBUTING.md covers the component-author contract — the cleanup rules, the escaping requirement and the JSDoc the documentation generator reads.