Start with the state
Rethink your styles by considering state-first.
<input type="text" placeholder="Text input styled with Loci" data-style data-:hover data-:focus data-:active data-::placeholder />
State-based styles
Loci is a low-level CSS framework that is centered around state.
npm i loci
css
Rethink your styles by considering state-first.
<input type="text" placeholder="Text input styled with Loci" data-style data-:hover data-:focus data-:active data-::placeholder />
Set colors, spacing, and more with CSS custom properties. In Loci, every value is a custom property.
const colors = { red: { 50: #f00, 100: #f00, 200: #f00, 300: #f00, // … } }
:root { --loci-red-300: #f00; --loci-space-8: 8px; }
Use single-purpose, utility style declarations with your defined variables. Verbose, understandable.
<input type="text" placeholder="Loci" data-style="width:100% border-color:blue-500 padding:16 font-size:20 color:blue-900 background-color:blue-100" data-:hover="background-color:blue-200" data-:focus="background-color:blue-200" data-:active="background-color:blue-300" data-::placeholder="color:blue-600" />
Prefer writing p
instead of
padding
or bg
instead of
background-color
? Set your alternative property names in your
configuration file.
{ [`alternativePropertyNames`]: { [`background-color`]: `bg`, [`margin-bottom`]: `mb`, [`margin-left`]: `ml`, [`margin-right`]: `mr`, [`margin-top`]: `mt`, [`margin`]: `m`, [`padding-bottom`]: `pb`, [`padding-left`]: `pl`, [`padding-right`]: `pr`, [`padding-top`]: `pt`, [`padding`]: `p`, } }
<input type="text" placeholder="Loci" data-style="width:100% border-color:blue-500 p:16 font-size:20 color:blue-900 bg:blue-100" data-:hover="bg:blue-200" data-:focus="bg:blue-200" data-:active="bg:blue-300" data-::placeholder="color:blue-600" />
Use utility styles to define grouped component styles with a class.
{ [`components`]: { [`button`]: { [`style`]: `appearance:none bg:red-300 border-color:blue-400 color:red-800 pt:8 pb:8 pr:16 pl:16`, [`:hover`]: `bg:red-400 color:red-900`, [`:focus`]: `bg:red-400 color:red-900`, [`:active`]: `bg:red-500`, } } }
<button class="button">Press</button>
Extend components with variant grouped styles.
const variants: Variants = { [`button:primary`]: { [`style`]: `bg:blue-300 border-color:blue-600 color:blue-800`, [`:hover`]: `bg:blue-400 color:blue-900`, [`:focus`]: `bg:blue-400 color:blue-900`, [`:active`]: `bg:blue-500`, } }
<button class="button" data-variant="button:ghost">Press</button> <button class="button" data-variant="button:primary">Press</button> <button class="button" data-variant="button:danger">Press</button>
::before
and
::after
content
<p data-style="mt:0 mb:0" data-::before-content="✅" data-::after-content=" (Or at least tried my best.)" data-::after="color:amber-400" > I have read it all. </p>
Change variables in scoped elements.
<div data-style="p:16 bg:blue-900 color:red-300"> <h2 data-style="mt:4 font-family:sans-serif">Section title</h2> <p>Section description with the same text color.</p> <blockquote data-style="color:red-300 ml:0 p:8 border-style:solid" data-custom-property="--loci-red-300:limegreen" > Block quote with a different text color. </blockquote> <p>Section description continued.</p> </div>
Add styles based on aria
states and roles.
<input aria-invalid data-aria-invalid="border-color:red-600" >
Display a banner when your app is using CSS that is not purged for production.
const config: Config = { choices: { base: [`theme`, `developerMode`], }, }
See developer mode banner at the bottom of this page.
:first-letter, @media, @keyframes, etc.
<input data-::placeholder="p1 bg:blue-200" />
Can Loci answer the question: How do I do apply dark + xl + hover?
Name your custom states: dark|xl|hover or my-compound-dark-extra-large-hover-state
Styles are deliberately applied per state and leverage the familiar HTML + CSS API.
Allows the user to define their own states, like `data-task-completed`.
This may have been addressed in another section.
`data-task-completed="--var:val"`
Standard themes that can be used in many contexts.
Let's get some TypeScript in there.
Is it possible to warn a user if two of the same property are applied to the same state? For example:
<div data-:hover="bg:blue-100 bg:blue-200">…</div>
* { box-sizing: border-box; } *::selection { background-color: var(--blue-100); } For example:
<div data-global="bg:blue-100">…</div>
Or, should these be accomplished with scoped variables?
<div data-custom-property="--loci-selection-background-color:blue-100">…</div>
Ensure styles are applied in all browsers that support them, and gracefully degrade to legacy browsers.
Display all property and values in use. (This is already available in the config file. 🤔)
Roll a custom framework that works for you.
<div data-style="padding:0.25rem">…</div>
<div data-style="p:0.25rem">…</div>
<div data-style="p:s
">…</div>
<div data-style="padding-right:auto padding-left:auto">…</div>
<div data-style="px:auto">…</div>
<div data-style="px:a
">…</div>
Consider pulling CSS data from mdn-data.