🥋 Uniform.css

Lightweight, opinionated CSS library that plays nicely within Shadow DOM.

It is a set of helper CSS classes to implement:

If you are looking for UI Components library check <🥋/> Uniform components.

Table of Contents

Usage with Underwear.css

Usually, it's recommended to put some Underwear before putting the Uniform.

Underwear is a minimalistic library that normalizes User Agent styles and puts a tiny layer of sugar on top. They are designed to play well together.

Underwear can be used both in light DOM and in Shadow DOM. Because of the shadow tree boundary, to style native HTML elements in a shadow root with Underwear, you have to explicitly load it in that shadow root.

You can see how this page looks with or without Underwear:

Please note that above distintion works best for browsers that support Shadow DOM, otherwise styles may leak. Without Shadow DOM, outer Underwear may bleed into shadow roots, and inner Underwear may leak outside. Uniform selectors are more specific, explicit and should not make so many problems.

Custom Properties

Uniform.css uses CSS Custom Properties (CSS Variables) that you can configure per (shadow) root in which you included uniform.css. You can also use them by yourself, to adhere to the consistent look and feel.

The recommended way to apply custom theme to Uniform.css is by specifying new values for the CSS custom properties in the light DOM. Uniform.css will use these values instead of the defaults.

The following demo shows:

<style>.pinky-host{ --uni-primary: pink;}</style>
<div class="pinky-host">
    <div>
        <shadowroot mode="open">
            <link rel="stylesheet" href="uniform.css">
            <style>
                .app-header{
                  color: var(--uni-danger, var(--uni-default-danger));
                }
            </style>
            <h3 class="app-header"><slot name="app/some"></slot></h3>
            <div class="uni-primary-button"><slot name="app/button"></slot></div>
        </shadowroot>
        <custom-element slot="app/content">Some content with consistent uni-colors</custom-element>
        <button slot="app/button">Pinky primary button</button>
    </div>
</div>
Some content with consistent uni-colors

Label Control

.uni-label-control

Puts slotted label to the top row, everything else in the bottom row.

It works for distributed elements.

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-label-control">
        <slot></slot>
    </div>
</shadowroot>
<label>Label</label>
<input>

You can use it as well for styling any elements in the same tree.

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-label-control">
        <label>Label</label>
        <div>
            <slot></slot>
        </div>
    </div>
</shadowroot>
<input>
<select><option>select</option></select>
<input>
<span>message</span>
message

Button

.uni-*-button

Makes a specific type of a button

You can style distributed buttons.

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-success-button">
        <slot></slot>
    </div>
</shadowroot>
<button>light</button>

As well as the elements from the same tree

<shadowroot mode="open">
    <link rel="stylesheet" href="../underwear.css/underwear.css">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-success-button">
        <slot></slot>
        <button>shadow</button>
    </div>
</shadowroot>
<button>light</button>

Pagination

.uni-pagination, .uni-previous, .uni-next, .uni-pages

To style pagination widget use:

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-pagination">
        <div class="uni-previous"><slot name="foo/previous"></slot></div>
        <div class="uni-pages"><slot></slot></div>
        <div class="uni-next"><slot name="foo/next"></slot></div>
    </div>
</shadowroot>
<span slot="foo/previous" onclick="doYourJobInJS()" href="orUseStaticLinks">Previous</span>
<span>2</span>
<span aria-current="true">3</span>
<span aria-current="false">4</span>
<span disabled>5</span>
<span slot="foo/next" disabled>Next</span>
Previous 2 3 4 5 Next

As with other Uniform classes you can use them to style elements from the same tree as you style distributed elements.

Form

.uniform-form 🚧 Currently, it just sets margin-bottom for divs. That does not serve the purpose well. But we have plans...
<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-form">
        <slot></slot>
    </div>
</shadowroot>
<label>Email</label>
<input type="text" value="stephen@fry.com">
<label>Firstname</label>
<input type="text" value="Stephen">
<label>Lastname</label>
<input type="text" value="Fry">
<label>Mobile phone number</label>
<input type="text" value="+46 707 11 33 44">
<label>Home number</label>
<input type="text" value="+46 707 11 33 44">
<a href="#">ADD PHONE NUMBER</a>
<label>Home address</label>
<input type="text" value="Bybrokajen 5, 111 48 Stockholm">
<a href="#">ADD ADDRESS</a>
<button>Submit</button>
<button>Cancel</button>
ADD PHONE NUMBER ADD ADDRESS

Alert

.uni-alert-info, .uni-alert-warning, .uni-alert-danger
uni-alert-infoHi! This is some info
uni-alert-successThis is great success!
<shadowroot mode="open">
    <link rel="stylesheet" href="../underwear.css/underwear.css">
    <link rel="stylesheet" href="uniform.css">

    <div class="uni-alert-info">
        <slot name="myapp/info"></slot>
    </div>
    <hr>
    <div class="uni-alert-warning">
        <div><code>uni-alert-warning</code>This is just a warning</div>
    </div>
    <hr>
    <div class="uni-alert-danger">
        <div><code>uni-alert-danger</code>This is a more serious warning</div>
    </div>
    <hr>
    <div class="uni-alert-success">
        <slot name="myapp/success"></slot>
    </div>
</shadowroot>
<div slot="myapp/info">
    <code>uni-alert-info</code>Hi! This is some info
</div>
<div slot="myapp/success">
    <code>uni-alert-success</code>This is great success!
</div>

Dynamic content as an alert

<shadowroot mode="open">
    <link rel="stylesheet" href="../underwear.css/underwear.css">
    <link rel="stylesheet" href="uniform.css">
    <slot></slot>
    <div class="uni-alert-success">
        <slot name="myapp/success"></slot>
    </div>
</shadowroot>

<button>Click me to see the alert</button>
<script>(function(){
    const current = document.currentScript;
    current.previousElementSibling.addEventListener('click', function loadContent(){
        const msg = document.createElement('div');
        msg.setAttribute('slot', 'myapp/success');
        msg.innerHTML = 'There was no alert before I arrived!';
        current.parentNode.appendChild(msg);
        setTimeout(()=>{msg.remove();}, 2000);
    });
}())</script>

Card

To create slightly elevated card, use .uni-card.
with distributed content.
<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-card">
        I'm an elevated panel,
    </div>
</shadowroot>
with distributed content.
You can add expandable part to .uni-cardby using details.
<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-card">
        I'm an elevated panel...
        <details>
            <summary>Expand</summary>
            <div>
                <p>and this is my expanded section.</p>
            </div>
        </details>
    </div>
</shadowroot>

Section

To create different kinds of sections, use: Note, that those sections stick to the sides of padded host.
<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-section-primary">
        Primary section
    </div>
    <section class="uni-section-secondary">
        Secondary section
    </section>
    <div class="uni-section-tertiary">
        Tertiary section
    </div>
</shadowroot>
You can nest cards within sections. It is recommended to lay out cards within sections using CSS Grid Layout.
<shadowroot mode="open">
    <link rel="stylesheet" href="../underwear.css/underwear.css">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-section-primary">
        <div class="uni-card">Default <code>div</code>(block) card in a section. Useful for full-width content.</div>
    </div>
    <section class="uni-section-tertiary" style="display: grid; grid-template-columns: repeat(2, 1fr);grid-gap: var(--uni-section-padding-horizontal, var(--uni-default-section-padding-horizontal))">
        <div class="uni-card">The first of a pair of half-width cards in a section, achieved by setting <code>display: grid</code> on the section (with two columns and a gap).</div>
        <div class="uni-card">The second  of a pair of half-width cards</div>
    </section>
    <div class="uni-section-primary">
        <div class="uni-card" style="max-width: 500px;">Default <code>div</code>(block) card with <code>max-width: 500px</code> in a section. Useful for content that should be read vertically, not horizontally, such as forms.</div>
    </div>
    <div class="uni-section-secondary">
        <span class="uni-card">Default <code>span</code>(inline)</span>
        <span class="uni-card">cards in a section.</span>
        <span class="uni-card">Useful for single-line content.</span>
    </div>
    <div class="uni-section-primary">
        <div class="uni-card" style="display: inline-block">Inline-block <br>cards, </div>
        <div class="uni-card" style="display: inline-block">achieved by <br>setting <code>display: inline-block</code> on the card,</div>
        <div class="uni-card" style="display: inline-block">useful<br>for<br> multi-line<br>content<br>of varied<br>height.</div>
    </div>
</shadowroot>

Title

Use .uni-title inside .uni-section or .uni-card to apply consistently formatted page or card title. .uni-title overwrites the font style of the slotted element.

It is recommended that you use semantic HTML elements for the title content, such as h2 for the page title and h3 for the card title.

Page title:

Page title

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-section-primary">
        <div class="uni-title">
            <slot></slot>
        </div>
    </div>
</shadowroot>
<h1>Page title</h1>

Card title:

Card title

<shadowroot mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-card">
        <div class="uni-title">
            <slot></slot>
        </div>
    </div>
</shadowroot>
<h2>Card title</h2>

Layout

Layout with left side navigation

Class .uni-layout-left-nav implements a commonly used two-column layout.

It uses two child elements:

Anchor elements <a> element within the left column that have the attribute aria-current="page" will be highlighted.

Navigation link 1 Navigation link 2 Navigation link 3
<shadowroot mode="open">
<template is="declarative-shadow-dom" mode="open">
    <link rel="stylesheet" href="uniform.css">
    <div class="uni-layout-left-nav">
        <nav>
            <slot name="navigation"></slot>
        </nav>
        <div class="uni-section-primary">
            <slot name="main-content"></slot>
        </div>
    </div>
</shadowroot>
<nav slot="navigation">
    <a href="#layout-left-nav">Navigation link 1</a>
    <a href="#layout-left-nav">Navigation link 2</a>
    <a href="#layout-left-nav">Navigation link 3</a>
</nav>
<label slot="main-content">Main content</label>