Skip to content
EldanCSS

Docs

Getting started

Add one stylesheet to a page and keep writing semantic HTML.

EldanCSS is a classless CSS stylesheet. There are no component classes to learn and no build step. If the HTML describes the content correctly, the stylesheet should handle the rest.

Install

Copy eldan.css into your project and link it from the document head:

<link rel="stylesheet" href="/eldan.css">

There is no package manager, bundler, or JavaScript file to add.

From the CDN

For local development or a quick prototype, link the hosted copy directly instead of downloading it. The unversioned URL always serves the latest release and is cached for five minutes:

<link rel="stylesheet" href="https://eldancss.com/eldan.css">

For a stable build, pin the versioned path instead: /eldan/<version>/eldan.css is immutable and cached for a year. The versioned download link above points at the current release.


Note: Code samples in these docs are highlighted by the Hugo build. EldanCSS itself only styles the pre and code elements.


Write HTML

Use the elements that describe your content. This is enough for a complete page:

<main>
  <h1>Field notes</h1>
  <p>A short description of the page.</p>
  <a href="/archive/">Read the archive</a>
</main>

The stylesheet intentionally leaves layout to the document. It sets a readable measure, spacing, and a type scale, but it does not impose a grid or a component structure.

Light and dark

Every color token resolves through light-dark() and the document declares color-scheme: light dark, so the page follows the operating system by default. No script or extra markup is required.

The same mechanism also supports an explicit switch: set color-scheme on the root and remember the choice. The docs header uses this pattern.

:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

Apply the saved value before first paint to avoid a flash:

try {
  const theme = localStorage.getItem("theme");
  if (theme === "light" || theme === "dark") {
    document.documentElement.dataset.theme = theme;
  }
} catch (error) {}

Then wire up a control and persist changes:

const root = document.documentElement;
const select = document.querySelector("[data-theme-select]");

const applyTheme = (theme) => {
  if (theme === "light" || theme === "dark") root.dataset.theme = theme;
  else root.removeAttribute("data-theme");
};

const stored = localStorage.getItem("theme") || "auto";
select.value = stored;
applyTheme(stored);

select.addEventListener("change", () => {
  const theme = select.value;
  applyTheme(theme);
  if (theme === "auto") localStorage.removeItem("theme");
  else localStorage.setItem("theme", theme);
});

auto removes data-theme so prefers-color-scheme decides again. Because color-scheme also drives native controls and scrollbars, the selected theme stays consistent across the page.

Browser support

EldanCSS targets current evergreen browsers and does not include a fallback layer.

Most of the stylesheet is Baseline Widely Available: custom properties, calc(), clamp(), :is(), :not(), :has(), color-mix(), logical properties, :user-invalid, native <dialog>, and the native popover attribute.

The token layer uses two Baseline 2024 features: @property and light-dark(). light-dark() is what resolves the color tokens, so browsers without it may fall back to the initial foreground and background colors. text-wrap: balance is also Baseline 2024.

The JavaScript popover methods are Baseline 2025, but the stylesheet only styles [popover]; the declarative attribute is enough to open and close it. The declarative commandfor/command modal path is also Baseline 2025 newly available, so the docs keep showModal() as the portable example.

Two declarations are progressive enhancements. text-wrap: pretty is ignored by Firefox, which falls back to normal wrapping. accent-color is not yet Baseline because Safari’s implementation is partial; older browsers keep their default control accent.

See Baseline for current support.

Next steps