@zeix/ui-element
Version:
UIElement - minimal reactive framework based on Web Components
320 lines (281 loc) β’ 15.4 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">
<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.11.0</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>π¨ 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>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>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>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>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>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>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>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>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>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>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>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>Β© 2025 Zeix AG</p>
</div>
</footer>
</body>
</html>