It is a set of helper CSS classes to implement:
.uni-primary-button
, .uni-alert-success
, etc.uni-section-primary
, .uni-card
, .uni-label-control
, etcIf you are looking for UI Components library check <🥋/> Uniform components.
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.
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.
Name | Default value | Sample |
---|---|---|
--uni-white |
var(--white, #ffffff); |
|
--uni-gray-1 |
var(--gray-1, #f9f9f9); |
|
--uni-gray-2 |
var(--gray-2, #f6f6f6); |
|
--uni-gray-3 |
var(--gray-3, #efefef); |
|
--uni-gray-4 |
var(--gray-4, #e7e7e7); |
|
--uni-gray-5 |
var(--gray-5, #e1e1e1); |
|
--uni-gray-6 |
var(--gray-6, #868e96); |
|
--uni-gray-7 |
var(--gray-7, #606c76); |
|
--uni-transparent-black |
var(--transparent-black, #00000033); |
|
--uni-blue |
var(--blue, #0084b4); |
|
--uni-dark-blue |
var(--dark-blue, #1a587f); |
|
--uni-dark |
var(--dark, #141d26); |
|
--uni-green |
var(--green, #3fa13f); |
|
--uni-inky |
var(--inky, #1b2936); |
|
--uni-livid |
var(--livid, #8696a5); |
|
--uni-mouse |
var(--mouse, #e7ecf0); |
|
--uni-red |
var(--red, #df4534); |
|
--uni-yellow |
var(--yellow, #ffdb25); |
|
--uni-primary |
var(--uni-blue); |
|
--uni-secondary |
var(--uni-blue); |
|
--uni-success |
var(--uni-green); |
|
--uni-danger |
var(--uni-red); |
|
--uni-warning |
var(--uni-yellow); |
|
--uni-disabled |
var(--uni-gray-5); |
|
--uni-section-padding-horizontal |
40px |
|
--uni-section-padding-vertical |
20px |
|
--uni-layout-left-nav-background |
var(--uni-mouse, var(--uni-default-mouse)) |
|
--uni-layout-left-nav-side-background |
var(--uni-inky, var(--uni-default-inky)) |
|
--uni-layout-left-nav-side-color |
var(--uni-gray-5, var(--uni-default-gray-5)) |
|
--uni-layout-left-nav-side-link-color |
var(--uni-livid, var(--uni-default-livid)) |
|
--uni-layout-left-nav-side-link-color-hover |
var(--uni-white, var(--uni-default-white)) |
|
--uni-layout-left-nav-side-link-highlight |
3px solid var(--uni-blue, var(--uni-default-blue)) |
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>
.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>
.uni-*-button
Makes a specific type of a button
Normal | Disabled |
---|---|
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>
.uni-pagination, .uni-previous, .uni-next, .uni-pages
To style pagination widget use:
.uni-pagination
- to wrap all page-related links,.uni-previous
- to wrap the "previous", or "first" link,.uni-next
- to a list of pages,.uni-pages
- to wrap the "next", or "last" link,[disabled]
- to disable a link, simply put "disabled" attribute,[aria-current="true"]
- to mark current item, use ARIA attribute (see the spec for more values).<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>
As with other Uniform classes you can use them to style elements from the same tree as you style distributed elements.
.uniform-form
🚧 Currently, it just sets margin-bottom
for div
s. 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>
.uni-alert-info, .uni-alert-warning, .uni-alert-danger
uni-alert-warning
This is just a warninguni-alert-danger
This is a more serious warninguni-alert-info
Hi! This is some info
uni-alert-success
This 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>
<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>
.uni-card
.
<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-card
by using details
.
and this is my expanded section.
<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>
.uni-section-primary
- to have a greyish background,.uni-section-secondary
- to have white background,.uni-section-tertiary
- to have dark blue background<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.
div
(block) card in a section. Useful for full-width content.display: grid
on the section (with two columns and a gap).div
(block) card with max-width: 500px
in a section. Useful for content that should be read vertically, not horizontally, such as forms.span
(inline)
cards in a section.
Useful for single-line content.
display: inline-block
on the card,<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>
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:
<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:
<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>
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.
<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>