5

erikt/ui

A CSS reset and a small UI library in one stylesheet.

erikt/ui is somewhere between a CSS reset and a classless CSS project. It styles native HTML elements directly, so plain semantic markup looks decent with no extra work. A small set of opt-in class names covers the things HTML can't express on its own.

The core idea is borrowed from Pico CSS. A stylesheet should improve the browser's defaults, not replace them. erikt/ui adds more components and a theming layer on top.

Installation

CDN

Link the stylesheet from the CDN:

<link rel="stylesheet" href="https://esm.sh/@erikt/ui" />

You can also download the CSS file and host it yourself:

Download ui.css

npm

Install the package:

npm install @erikt/ui

With a bundler like Vite, import it by package name from your CSS:

@import "@erikt/ui";

Without a bundler, link the file in node_modules:

<link rel="stylesheet" href="node_modules/@erikt/ui/dist/ui.css" />

Or copy it into your public folder, if node_modules isn't served.

Theme

Optionally change the overall theme:

:root {
  --ui-primary: light-dark(#111, #fefefe);
}

Built in docs

When installing through npm, the package ships with a copy of these docs, built for the installed version. They work offline and always match the version in your project. Start the docs server and open http://localhost:3456:

npx @erikt/ui docs

Overview

erikt/ui styles native HTML elements directly, no class names required.

<fieldset role="group">
  <input type="text" placeholder="Input" /> <button>Button</button>
</fieldset>

UI, not layout

erikt/ui styles interactive elements (buttons, inputs, popovers) and leaves the page layout to you. flex and grid are already short to write and easy to read. Wrapping them in classes doesn't make them better.

There are a few exceptions. Some patterns show up so often that a short class saves real typing.

<style>
  form {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1rem;

    input[type="email"] {
      grid-column: 1 / -1;
    }

    button {
      grid-column: 1 / -1;
      justify-self: end;
    }
  }
</style>

<form>
  <input type="text" placeholder="First name" />
  <input type="text" placeholder="Last name" />
  <input type="email" placeholder="Email" />
  <button type="submit">Submit</button>
</form>

With Tailwind

erikt/ui and Tailwind get along. erikt/ui handles component styles, Tailwind handles layout and one-off utilities. Nothing collides, because erikt/ui wraps everything in @layer ui {} and any Tailwind utility beats it without the ! prefix.

Declare the layer order before importing either library. That puts Tailwind's reset below erikt/ui and its utilities above:

/* main.css */
@layer theme, base, ui-reset, ui, components, utilities;

@import "https://esm.sh/@erikt/ui";
@import "tailwindcss";

Philosophy

erikt/ui is also where I try out new CSS. Anchor positioning, @starting-style, the Popover API and :has() all landed here first. The question I keep poking at is how far CSS gets before JavaScript is needed.

So it leans on very new browser features and isn't meant for projects that need broad support. Treat it as an experiment rather than a production toolkit.

Search 5021 icons

Type a name to find icons from the Tabler icon set.

      Move Open Esc Close