A native <input type="color"> gives you a compact button that opens a color-selection dialog. What if the controls need to stay visible while you adjust an object—and that object can be transparent? A custom color picker can combine persistent color and transparency controls in one Web Component. section 11.1
Break the control into smaller pieces:
- Use two instances of a reusable slider: one for hue, with a multicolor gradient behind it, and one for transparency, with a checkered background. section 11.1 section 11.3
- Use a coordinate picker for saturation and brightness. Its draggable thumb moves on both axes; horizontal position controls saturation, and vertical position controls brightness. section 11.2
- Add labeled text fields for red, green, blue, alpha, and hex values so users can enter values as well as drag controls. section 11.3
The coordinate picker extends HTMLElement and exposes x and y attributes. Mouse coordinates are measured against its bounds, constrained to the control, and converted to percentages that position the thumb. Its layered CSS gradients supply the visual field for choosing saturation and brightness. section 11.2
The outer <wcia-color-picker> creates a Shadow DOM and renders the sliders, coordinate picker, and fields together. A MutationObserver watches attribute changes within that shadow tree; a change listener handles field edits. Both routes pass the affected element to update handling, keeping the controls connected. The component’s public hex and alpha attributes can also initialize its color and transparency; defaults apply when they are absent. section 11.3
Put the picker on a page
Place <wcia-color-picker hex="#7687db" alpha="75"></wcia-color-picker> in a page that imports its JavaScript module. A demo uses the picker to change the page background color and the opacity of text, making both selections visible in context. section 11.4
For a consistent appearance alongside other components, replace arbitrary sizes, colors, and borders with CSS variables. Shared JavaScript CSS modules can supply text, input-field, and modal rules inside Shadow DOM, where an external design system’s styles may not reach. section 11.4
Listing 11.10. Listening to attribute changes with a MutationObserver
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = Template.render();
this.dom = Template.mapDOM(this.shadowRoot);
const observer = new MutationObserver( e => this.onMutationChange(e)); #1
observer.observe(this.shadowRoot, { attributes: true, subtree: true }); #2
}
onMutationChange(records) {
records.forEach( rec => { #3
this.data = Handlers.update({ #4
model: this.data,
dom: this.dom,
component: this,
element: rec.target,
attribute: rec.attributeName,
});
});
}
The MutationObserver listing shows how the outer component watches attribute changes throughout its shadow tree and passes each change to update handling. section 11.3



