A map of all Custom Elements provided by alembic. Keys are the desired names of the element and values are the Custom Elements themselves.

import { allCustomElements } from '@openlab/alembic'


A map of Custom Element layouts, where the key is the element name and the value is the HTMLElement subclass

import { layoutCustomElements } from '@openlab/alembic'


StackLayout adds whitespace (margin) between flow (block) elements along a vertical axis. Documentation →


BoxLayout is a custom element for generic containers of things. Documentation →


CenterLayout ensures a block-level element is horizontally centered with a max-width value representing the typographic measure. Documentation →


ClusterLayout groups items together with control for the margin between them. Documentation →

NOTE — if flex-gap isn't supported, items will appear flush


SidebarLayout places two elements side-by-side. If space permits it, the sidebar has a set width and the content fills up the rest of the space. If there is not enough space, the elements collapse into a single column, taking up all of the horizontal space.. Documentation →


SwitcherLayout places elements horizontally if there is space, or vertically if not. Documentation →


CoverLayout covers a block-layout element vertically with a centered principle element and accessory elements at the top or bottom. Documentation →


GridLayout creates a responsive grid using CSS Grid. Documentation →


FrameLayout displays an element with an aspect ratio. Documentation →


ReelLayout places elements horizontally and facilitates scrolling overflow. Documentation →


ImposterLayout positions an element over any other element. Documentation →


IconLayout lays out icons inline nicely. Documentation →


Create a global stylesheet under an identifier so it is only added to the DOM once. If a style with the same id is requested again, it will not be added.

This appends styles to the <head> element with the HTML id set to the parameter of the same name. The style is the raw CSS to be added.

import { addGlobalStyle } from '@openlab/alembic'

addGlobalStyle('element-abcdef', 'p { color: red; }')

which will create:

<!-- ... -->
<style id="element-abcdef">p { color: red; }</style>


Trim all the whitespace from a CSS template literal.

import { trimCss } from '@openlab/alembic'

const minified = trimCss(`
p {
color: red;

Which results in:

p { color: red; }


defineCustomElements iterates through the key-value pairs of the customElement map and registers them with the DOM using the customElements.define API. You can use this to quickly register a set of custom elements, like allCustomElements or layoutCustomElements.

import { defineCustomElements, allCustomElements } from '@openlab/alembic'



getHTMLElement is a helper method used to create HTMLElement subclasses in both the browser or a non-browser JavaScript environment. It means you can still instantiate your customElements without needing the superclass to be available. The stub does not implement any of HTMLElement it just swaps it out for an empty class so that subclass functionality can be used.

For examples of usage see the source code for the custom layout elements.


unstable use at your own risk

A Map of custom shortcodes and their resolved values. These are used when parsing custom element attributes to map what is passed to a longer value. The values are currently a work in progress and may change at any time.

import { attributeShortcodes } from '@openlab/alembic'

attributeShortcodes.get('s-5') // 'var(--s-5)'
attributeShortcodes.get('s0') // 'var(--s0)'


unstable use at your own risk

getAttribute returns the resolved attribute value given an input value based on whatever the state of attributeShortcodes is at the time of calling it. If a replacement is not found, the input value is returned instead.

import { getAttribute } from '@openlab/alembic'

getAttribute('s-5') // 'var(--s-5)'
getAttribute('something-unknown') // 'something-unknown'



processHtml takes a HTML string, looks through it for Alembic usage and modifies the HTML to include custom element styles (e.g. for the layouts).

You can optionally provide options to inject extra HTML into the inputHtml too at either the script or style location. This is useful to automatically add the Alembic base styles / scripts from getBaseStyles and getBaseScripts. Your build process could write these files somewhere then make sure they are linked to from the HTML here.

import { processHtml } from '@openlab/alembic'

const options = {
extraStyles: [`<link rel="stylesheet" href="/alembic/style.css">`],
extraScripts: [`<script type="module" src="/alembic/script.js"></script>`],

processHtml('<html>...', options)

You control where the styles and scripts are injected using a special HTML comments <!-- @openlab/alembic inject-css --> and <!-- @openlab/alembic inject-js -->. You opt in to those features by adding the comment to your HTML.


getStyles takes a HTML string, looks through it for Alembic usage and returns the styles to satisfy it. This is useful for SSR when you have something that has already generated style ids on custom elements and need to get the styles for a whole document in one go.

import { getStyles } from '@openlab/alembic'

getStyles('<html>...') // Map<string, string>


Get the base styles for non-dynamic Alembic. Useful for creating a stylesheet during SSG to be linked to from a HTML document.

const sourcecode = await getBaseStyles()


Get the labcoat styles along with the base styles for non-dynamic Alembic. Useful for creating a stylesheet during SSG to be linked to from a HTML document.

const sourcecode = await getLabcoatStyles()


Get the scripts as a string to run Alembic in-browser. Useful for creating a script during SSG to be linked to from a HTML document.

const sourcecode = await getBaseScripts()