Open source · MIT v2.0.0

A minimal, themeable CSS component library.

Write plain HTML and get styled components automatically, or use classes when you need more control.

npm install mdst-ui

~10 kB gzipped · No JavaScript required · Works with any framework, or none

JD
Jamie Doe Product designer
Active
Onboarding3 of 4
75%
Same HTML, different tokens Theme: Default

Try a theme

These are stock components, and each theme only changes a handful of CSS variables.

Welcome back

Password

No account? Create one


Press ⌘ K to search

Team

4
Name Role Status
AK Ada King Owner Online
LT Linus T. Engineer Away
GH Grace H. Engineer Online
MH Margaret H. Design Locked

Notifications

Pro

Popular
£12 / month
  • Unlimited projects
  • Custom domains
  • Priority support

Deploying main

✓
Build
✓
Test
3
Deploy
4
Live
68%
Storage212 of 256 GB
212 GB

Feedback

Changes saved. Payment failed.
design v2 urgent

It’s mostly HTML

Write normal HTML, and add a class when you want a variant.

<body class="mdst-ui">
  <form>
    <label for="name">Name</label>
    <input id="name" placeholder="Ada">

    <select>
      <option>Designer</option>
      <option>Engineer</option>
    </select>

    <label>
      <input type="checkbox"> Subscribe
    </label>

    <button>Save</button>
  </form>
</body>
Result · zero classes
<button class="mdst-button--solid">
  Publish
</button>
<button class="mdst-button--borderless">
  Cancel
</button>

<span class="mdst-tag mdst-tag--success">
  Live
</span>

<table class="mdst-table--striped">
  …
</table>
Result · modifiers on bare elements
Live
Plan Seats
Starter 3
Pro 10
Team 50
<div class="mdst-stepper">
  <div class="mdst-stepper__step"
       data-state="completed">…</div>
  <div class="mdst-stepper__step"
       data-state="active">…</div>
  <div class="mdst-stepper__step"
       data-state="upcoming">…</div>
</div>

<script>
  // Bring any JS (or none).
  // We style every state.
  step.dataset.state = "completed";
</script>
Result · try it
1
Account
2
Team
3
Launch

The buttons only flip data-state. All the visual states come from the CSS.

Result · drag to retheme
Ink colour
Tag

Make a page

Add some blocks, pick a theme, and copy the HTML.

Add a block

Your page

    Using it with AI

    If an AI is writing your front end, give it something small and predictable to build on.

    Native HTML, nothing to invent

    No bespoke component API to hallucinate. Models already write good semantic HTML, and modest-ui styles it.

    The whole library in one file

    llms.txt lists every class, token, and pattern. Drop it into context and your agent knows the system.

    Customise with tokens, not rewrites

    Brand changes are a handful of --mdst-* variables, so new screens keep matching instead of drifting.

    Your CSS always wins

    Everything sits in a cascade layer, so any CSS you or your agent add on top wins. No !important wars.

    Scoped to .mdst-ui

    Adopt it one screen at a time. Third-party widgets and legacy pages outside the scope stay untouched.

    Open source, no lock-in

    MIT licensed, plain CSS, no build step, and no runtime. Install from npm, use the CDN, or vendor the files.

    Starter prompt
    Use modest-ui (npm: mdst-ui) as the CSS foundation for this project.
    
    - Load it: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/mdst-ui@2/dist/modest-ui.min.css">
      or: npm install mdst-ui, then @import "mdst-ui/dist/modest-ui.css";
    - Put class="mdst-ui" on <body> and write semantic, native HTML first.
    - Only add .mdst-* modifier classes for variants (e.g. .mdst-button--borderless).
    - Drive runtime state with data-state; use modifier classes for variants.
    - Theme by overriding --mdst-* tokens in :root. Don't restyle components.
    - Put custom layout CSS in your own layer on top.
    - Reference: https://modest-ui.com/llms.txt

    Example pages

    Complete pages built with modest-ui and a little layout CSS.

    Install

    Add the stylesheet, put .mdst-ui on the body, and write HTML.

    npm install mdst-ui
    /* in your CSS */
    @import "mdst-ui/dist/modest-ui.css";
    
    /* or in your JS bundler */
    import "mdst-ui";
    <!doctype html>
    <html lang="en">
    <head>
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/mdst-ui@2/dist/modest-ui.min.css" />
    </head>
    <body class="mdst-ui">
      <h1>Hello world</h1>
      <button>Click me</button>
    </body>
    </html>
    /* Always include tokens first */
    @import "mdst-ui/base/tokens.css";
    
    /* Then only what you need */
    @import "mdst-ui/components/button/button.css";
    @import "mdst-ui/components/input/input.css";

    How it works

    Classless, classes, and your CSS on top

    Classless. Bare elements inside .mdst-ui get a styled baseline for free: every native <button>, <input>, and <table>.

    Classes. Component classes like .mdst-button always override the classless defaults, and modifiers like .mdst-button--borderless work directly on bare elements.

    Your CSS. All of modest-ui sits in the mdst-ui cascade layer, so anything you write outside a layer wins, whatever its specificity or load order.

    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 it all sits in a cascade layer, your own styles always take priority.

    Theming with tokens

    Override CSS custom properties to make it yours. Try the Theme Playground to generate them.

    :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;
    }

    Open source

    MIT licensed, so use it, fork it, or send a pull request.

    Copied to clipboard