@zeix/ui-element
Version:
UIElement - minimal reactive framework based on Web Components
381 lines (330 loc) β’ 18.5 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Styling Components β UIElement Docs</title>
<meta name="description" content="Scoped styles, CSS custom properties" />
<base href="./styling-components.html" />
<link rel="stylesheet" href="assets/main.css" />
<script type="module" src="assets/main.js"></script>
</head>
<body>
<header class="content-grid">
<h1 class="content">
UIElement Docs <small>Version 0.12.2</small>
</h1>
<nav class="breakout">
<ol>
<li>
<a href="index.html">
<span class="icon">π</span>
<strong>Introduction</strong>
<small>Overview and key benefits of UIElement</small>
</a>
</li>
<li>
<a href="getting-started.html">
<span class="icon">π</span>
<strong>Getting Started</strong>
<small>Installation, setup, and first steps</small>
</a>
</li>
<li>
<a href="building-components.html">
<span class="icon">ποΈ</span>
<strong>Building Components</strong>
<small>Anatomy, lifecycle, signals, effects</small>
</a>
</li>
<li>
<a href="styling-components.html" class="active">
<span class="icon">π¨</span>
<strong>Styling Components</strong>
<small>Scoped styles, CSS custom properties</small>
</a>
</li>
<li>
<a href="data-flow.html">
<span class="icon">π</span>
<strong>Data Flow</strong>
<small>Passing state, events, context</small>
</a>
</li>
<li>
<a href="patterns-techniques.html">
<span class="icon">π‘</span>
<strong>Patterns & Techniques</strong>
<small>Composition, scheduling, best practices</small>
</a>
</li>
<li>
<a href="examples-recipes.html">
<span class="icon">π½οΈ</span>
<strong>Examples & Recipes</strong>
<small>Common use cases and demos</small>
</a>
</li>
<li>
<a href="api-reference.html">
<span class="icon">π</span>
<strong>API Reference</strong>
<small>Detailed documentation of classes and functions</small>
</a>
</li>
<li>
<a href="about-community.html">
<span class="icon">π€</span>
<strong>About & Community</strong>
<small>License, versioning, getting involved</small>
</a>
</li>
</ol>
</nav>
</header>
<main><section class="hero">
<h1 id="styling-components">
<a name="styling-components" class="anchor" href="#styling-components">
<span class="permalink">π</span>
</a>
π¨ Styling Components
</h1><p class="lead"><strong>Keep your componentsβ styles self-contained while supporting shared design tokens.</strong> UIElement does not enforce a specific styling method, but we recommend techniques that help balance encapsulation, reusability, and maintainability.</p>
</section>
<section>
<h2 id="design-principles">
<a name="design-principles" class="anchor" href="#design-principles">
<span class="permalink">π</span>
</a>
Design Principles
</h2><p>UIElement is focused on <strong>state management and reactivity</strong>, not styling. However, to <strong>ensure consistent, maintainable, and reusable styles</strong>, we recommend techniques that <strong>scope component styles properly while allowing shared design tokens</strong> (e.g., spacing, font sizes, colors, layout grids).</p>
<ul>
<li>β
<strong>Each component brings along its own specific styles.</strong></li>
<li>β
Component styles should be <strong>scoped or encapsulated</strong> so they don't leak out.</li>
<li>β
<strong>Allow customizations</strong> via CSS custom properties or pre-defined classes.</li>
</ul>
<p>Parent components may apply styles to the wrapper element of known sub-components for layout purposes. But avoid styling inner elements of sub-components directly. This would tightly couple the styles of the outer and inner components.</p>
</section>
<section>
<h2 id="scope-styles-to-custom-element">
<a name="scope-styles-to-custom-element" class="anchor" href="#scope-styles-to-custom-element">
<span class="permalink">π</span>
</a>
Scope Styles to Custom Element
</h2><p>Use the <strong>custom element name</strong> to scope component styles if <strong>you control the page and the components within</strong>. This protects against component styles leaking out, while still allowing to use the CSS cascade. No need for Shadow DOM, no duplicate style rules.</p>
<code-block language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">my-component</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> & button {</span></span>
<span class="line"><span style="color:#88846F"> /* Button style rules */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#88846F"> /* More selectors for inner elements */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
<h3 id="advantages-of-custom-element-names">
<a name="advantages-of-custom-element-names" class="anchor" href="#advantages-of-custom-element-names">
<span class="permalink">π</span>
</a>
Advantages of Custom Element Names
</h3><ul>
<li>β
By definition <strong>unique within the document</strong> with a descriptive name.</li>
<li>β
<strong>Low specificity</strong>, making it easy to override when you need to with a single class.</li>
</ul>
<callout-box class="tip">
<p><strong>When to use</strong></p>
<p>β
<strong>Best when</strong> you control the page and need styles to cascade naturally.<br>β <strong>Avoid if</strong> you expect style clashes from third-party styles.</p>
</callout-box>
</section>
<section>
<h2 id="encapsulate-styles-with-shadow-dom">
<a name="encapsulate-styles-with-shadow-dom" class="anchor" href="#encapsulate-styles-with-shadow-dom">
<span class="permalink">π</span>
</a>
Encapsulate Styles with Shadow DOM
</h2><p>Use <strong>Shadow DOM</strong> to encapsulate styles if your component is going to be used in a pages <strong>where you don't control the styles</strong>. This way you make sure page styles don't leak in and component styles don't leak out.</p>
<code-block collapsed language="html" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">html</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F8F8F2"><</span><span style="color:#F92672">my-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">template</span><span style="color:#A6E22E"> shadowrootmode</span><span style="color:#F8F8F2">=</span><span style="color:#E6DB74">"open"</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"> <</span><span style="color:#F92672">style</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F92672"> button</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F"> /* Button style rules */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#88846F"> /* More selectors for inner elements */</span></span>
<span class="line"><span style="color:#F8F8F2"> </</span><span style="color:#F92672">style</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#88846F"> <!-- Inner elements --></span></span>
<span class="line"><span style="color:#F8F8F2"> </</span><span style="color:#F92672">template</span><span style="color:#F8F8F2">></span></span>
<span class="line"><span style="color:#F8F8F2"></</span><span style="color:#F92672">my-component</span><span style="color:#F8F8F2">></span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
<callout-box class="tip">
<p><strong>When to use</strong></p>
<p>β
<strong>Best when</strong> your component is used in environments where you donβt control styles.<br>β <strong>Avoid if</strong> you need global styles to apply inside the component.</p>
</callout-box>
</section>
<section>
<h2 id="shared-design-tokens-with-css-custom-properties">
<a name="shared-design-tokens-with-css-custom-properties" class="anchor" href="#shared-design-tokens-with-css-custom-properties">
<span class="permalink">π</span>
</a>
Shared Design Tokens with CSS Custom Properties
</h2><p>Web Components canβt inherit global styles inside <strong>Shadow DOM</strong>, but CSS custom properties allow components to remain <strong>flexible and themeable</strong>.</p>
<h3 id="defining-design-tokens">
<a name="defining-design-tokens" class="anchor" href="#defining-design-tokens">
<span class="permalink">π</span>
</a>
Defining Design Tokens
</h3><p>Set global tokens in a stylesheet:</p>
<code-block language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#A6E22E">:root</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2"> --button-bg: </span><span style="color:#AE81FF">#007bff</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#F8F8F2"> --button-text: </span><span style="color:#AE81FF">#fff</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#F8F8F2"> --spacing: </span><span style="color:#AE81FF">1</span><span style="color:#F92672">rem</span><span style="color:#F8F8F2">;</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
<h3 id="using-tokens-in-a-component">
<a name="using-tokens-in-a-component" class="anchor" href="#using-tokens-in-a-component">
<span class="permalink">π</span>
</a>
Using Tokens in a Component
</h3><code-block language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">my-component</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> padding</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">var</span><span style="color:#F8F8F2">(--spacing);</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> & button {</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> background</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">var</span><span style="color:#F8F8F2">(--button-bg);</span></span>
<span class="line"><span style="color:#66D9EF;font-style:italic"> color</span><span style="color:#F8F8F2">: </span><span style="color:#66D9EF">var</span><span style="color:#F8F8F2">(--button-text);</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
</code-block>
<h3 id="advantages-of-css-custom-properties">
<a name="advantages-of-css-custom-properties" class="anchor" href="#advantages-of-css-custom-properties">
<span class="permalink">π</span>
</a>
Advantages of CSS Custom Properties
</h3><ul>
<li>β
<strong>Supports theming</strong> β Users can override styles globally.</li>
<li>β
<strong>Works inside Shadow DOM</strong> β Unlike normal CSS, custom properties are inherited inside the shadow tree.</li>
</ul>
</section>
<section>
<h2 id="defined-variants-with-classes">
<a name="defined-variants-with-classes" class="anchor" href="#defined-variants-with-classes">
<span class="permalink">π</span>
</a>
Defined Variants with Classes
</h2><p>Use <strong>classes</strong> if your components can appear in a <strong>limited set of specific manifestations</strong>. For example, buttons could come in certain sizes and have primary, secondary and tertiary variants.</p>
<code-block collapsed language="css" copy-success="Copied!" copy-error="Error trying to copy to clipboard!">
<p class="meta">
<span class="language">css</span>
</p>
<pre class="shiki monokai" style="background-color:#272822;color:#F8F8F2" tabindex="0"><code><span class="line"><span style="color:#F92672">my-button</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F"> /* Style rules for default (medium-sized, secondary) buttons */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> &.small {</span></span>
<span class="line"><span style="color:#88846F"> /* Style rules for small buttons */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> &</span><span style="color:#A6E22E">.large</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F"> /* Style rules for large buttons */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> &</span><span style="color:#A6E22E">.primary</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F"> /* Style rules for primary buttons */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2"> &</span><span style="color:#A6E22E">.tertiary</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#88846F"> /* Style rules for tertiary buttons */</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre>
<input-button class="copy">
<button type="button" class="secondary small">
<span class="label">Copy</span>
</button>
</input-button>
<button type="button" class="overlay">Expand</button>
</code-block>
</section>
<section>
<h2 id="css-only-components">
<a name="css-only-components" class="anchor" href="#css-only-components">
<span class="permalink">π</span>
</a>
CSS-only Components
</h2><p>Just because UIElement is a JavaScript library doesn't mean you have to use JavaScript in every component. It's perfectly fine to use custom elements just for styling purposes.</p>
<p>Here's the example of the <code><callout-box></code> we're using in this documentation:</p>
<component-demo>
<div class="preview">
<callout-box>This is an informational message.</callout-box>
<callout-box class="tip">Remember to hydrate while coding!</callout-box>
<callout-box class="caution">Be careful with this operation.</callout-box>
<callout-box class="danger">This action is irreversible!</callout-box>
<callout-box class="note">This is just a side note.</callout-box>
</div>
<details>
<summary>Source Code</summary>
<lazy-load src="./examples/callout-box.html">
<p class="loading" role="status">Loading...</p>
<p class="error" role="alert" aria-live="polite" hidden></p>
</lazy-load>
</details>
</component-demo>
</section>
<section>
<h2 id="next-steps">
<a name="next-steps" class="anchor" href="#next-steps">
<span class="permalink">π</span>
</a>
Next Steps
</h2><p>Now that you know how to style components, explore:</p>
<ul>
<li><a href="data-flow.html">Data Flow</a> β Learn about communication between components.</li>
<li><a href="patterns-techniques.html">Patterns & Techniques</a> β Explore best practices and advanced topics.</li>
</ul>
</section></main>
<footer class="content-grid">
<div class="content">
<h2 class="visually-hidden">Footer</h2>
<p>Β© 2024 β 2025 Zeix AG</p>
</div>
</footer>
</body>
</html>