modest-ui

A minimal, themeable CSS component library. Write plain HTML and get styled components automatically — or use classes when you need more control.

Just write HTML

Add .mdst-ui to your <body> and every native element — buttons, inputs, tables, details — is styled out of the box. No classes needed.

Your HTML
<body class="mdst-ui">

  <h1>Welcome</h1>
  <p>This is styled automatically.</p>

  <button>Save</button>
  <input type="text" placeholder="Your name" />

</body>
Result

No classes. No JavaScript. Every element picks up your theme tokens and gets hover states, focus rings, and transitions for free.

Add classes when you need variants

The classless defaults cover the base appearance. When you need a variant — ghost, inverted, compact, small — add a modifier class. It overrides the default automatically.

Classless default
<!-- Just works -->
<button>Save</button>
<button>Cancel</button>
Result
With variants opt-in
<!-- Add classes for control -->
<button class="mdst-button--inverted">Save</button>
<button class="mdst-button--ghost">Cancel</button>
Result

You can also use the full class-based API directly — .mdst-button, .mdst-input, .mdst-table — all the explicit classes still work exactly as before. Classes always win over the classless defaults, so there's never a specificity conflict.

How it works

01

Classless layer

Bare elements inside .mdst-ui are styled using :where(), which keeps specificity at zero. Every native <button>, <input>, <table>, etc. gets a styled baseline for free.

02

Class layer

Component classes like .mdst-button and .mdst-input have normal specificity, so they always override the classless defaults when applied. Use them when you want explicit control.

03

Variant classes

Modifiers like .mdst-button--ghost work directly on bare elements inside .mdst-ui. No need to pair them with the base class.

Scoped and safe

Unlike classless frameworks that style every element on the page globally, modest-ui is scoped to .mdst-ui. Third-party widgets, embedded content, and anything outside the scope are unaffected. And because the classless layer uses :where() selectors, your own styles and any class-based overrides always take priority — zero specificity battles.

Example

Here's what a page built with modest-ui looks like. See more full-page examples.

Build something great

A platform for creators who value simplicity. No clutter, no distractions — just the tools you need.

Create an account

Minimal

No unnecessary styles. Just the essentials to get you started.

Themeable

Customise everything with CSS variables. Make it yours.

Native

Built on native HTML elements. No JavaScript required.

Installation

Via CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/thisismodest/modest-ui@v0.2.0/dist/modest-ui.min.css" />

Or with a package manager:

npm install github:thisismodest/modest-ui

Then import in CSS:

@import "modest-ui/dist/modest-ui.css";

Or cherry-pick components:

/* Always include tokens first */
@import "modest-ui/base/tokens.css";

/* Then pick what you need */
@import "modest-ui/components/button/button.css";
@import "modest-ui/components/input/input.css";

Quick start

Add the stylesheet and put .mdst-ui on the body. That's it.

<!doctype html>
<html lang="en">
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/thisismodest/modest-ui@v0.2.0/dist/modest-ui.min.css" />
</head>
<body class="mdst-ui">

  <h1>Hello world</h1>
  <p>This paragraph is styled automatically.</p>
  <button>Click me</button>
  <input type="text" placeholder="Type here" />

</body>
</html>

Theming

Override CSS custom properties to make it yours:

:root {
  --mdst-color-fg: #000;
  --mdst-color-bg: #fff;
  --mdst-color-border: #000;
  --mdst-color-muted: #666;
  --mdst-color-subtle: #f5f5f5;
  --mdst-color-focus: #000;
  --mdst-radius: 0;
}

Try the Theme Playground to experiment, or browse the components in the sidebar to see every option.