Lessons for reusable web components / Project starter / dan—webnotes
Skip to main content
jun 07, 2026
🔗 Lessons for reusable web components
Many people commented that they expected the<br>CSS-native parallax effect to have an interactive demo, so I re-opened and modernized a small code-sandbox web component I built last year.
Since then, I've dropped it into a handful of projects. Reusing the thing confirmed some of the choices I've made, and gave me some new useful ideas.
⚠️ Note:<br>This post doesn't touch advanced web-components techniques, like the shadow DOM or using and elements. These tips can apply broadly to UI components and CSS libraries.
# Own a short, distinctive namespace
Every class and custom property in the component now starts with csb. For example, I have .csb-header, .csb-controls, and so on.
Short, because it repeats on every element and every variable, and being short might shave a few bytes and a few minutes of typing.
Distinctive, because the point of a component is to land in a page you don't control, and a generic .header or .button might collide with the host's styles.
# Theme with namespaced CSS variables
This is the most important. Rather than ship override classes, every value worth changing is a CSS custom property, with its default written in as the fallback:
.csb-header {<br>border-color: var(--csb-border-color, light-dark(#ddd, #6b6b6b));
The component renders correctly with zero configuration, because the fallback is the default. Theming it means setting variables on the root element, or any parent element, and let the cascade do its thing:
code-sandbox {<br>--csb-border-color: var(--my-color);<br>--csb-editor-bg: #282c34;
No !important, no descendant selectors reaching three levels deep, no cascade to fight. The list of variable names is the whole public surface, which also means that you should try to keep these ones stable between versions.
# Let modern CSS and JS do the magic
A reusable component lands in contexts you can't predict, so using the modern features that the platform offers is one of the best way to achieve adaptability and resilience:
Container queries, not media queries. You don't know if a component will be added in a narrow sidebar or full width. Use container-type: inline-size on the parent element, so the child can responds to its own width.
light-dark() with color-scheme to have dark mode by default.
System fonts (system-ui, ui-monospace) and system colours (Canvas) so the default always works, and is consistent as possible with the underlying OS.
Logical properties (border-block-end, padding-inline) so it can support right-to-left layout, if needed.
em for sizing, so the whole component scales with whatever font size it inherits.
# Publish it instead of pasting it
While it can sound like a good idea copying the JS and CSS into each project by hand to achieve the final simplicity, copying and pasting gets tiring quite fast. It's now on NPM, and it can be imported in a line and updated with a version bump rather than a copy-paste tour of old projects.
npm i @danieledep/code-sandbox
Publishing it on NPM gives you for free command-line installing and CDN hosting , useful for the no-build case. So a static HTML page can use it by importing it in the of the file.
script type="module" src="https://cdn.jsdelivr.net/npm/@danieledep/code-sandbox@1/src/code-sandbox.js">script><br>link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@danieledep/code-sandbox@1/src/code-sandbox.css" />
# Then document all of it
A module only counts as reusable once someone other than you can actually use it and customize it. The code-sandbox README carries the theming table, the layout and highlighter guides, and the install instructions.
# Repository
danieledep/code-sandbox
# Resources
@danieledep/code-sandbox on NPM
Fullscreen API
CSS type
light-dark() CSS function
Making Fullscreen Experiences
Shiki Syntax highlighter