I simply want to style an <input type="color"> element so that it's a circle without changing its on-click behavior.
My first approach was to just style it with CSS, but this requires the use of ::-webkit-color-swatch/::-moz-color-swatch which are non-standard features and have poor browser support.
const randomColor = () =>
'#' + ((1 << 24) * Math.random() | 0).toString(16).padStart(6, '0');
const color = document.querySelector('#color');
color.addEventListener('click', event => {
event.currentTarget.value = randomColor();
event.currentTarget.style.backgroundColor = event.currentTarget.value;
});
color.addEventListener('input', event => {
event.currentTarget.style.backgroundColor = event.currentTarget.value;
});
#color {
border-radius: 25px;
height: 50px;
padding: 0;
width: 50px;
}
#color::-webkit-color-swatch {
display: none;
}
#color::-moz-color-swatch {
display: none;
}
<input id="color" type="color">
My second approach was to hide the color selector and trigger its click handler from a div styled to look like a circle instead. The problem with this approach is that the event handler passed to the input element doesn't retain its x and y coordinates, so Chrome shows the color selector in the top left corner of the window rather than under the element.
const randomColor = () =>
'#' + ((1 << 24) * Math.random() | 0).toString(16).padStart(6, '0');
const div = document.querySelector('#div');
div.addEventListener('click', event => {
const selector = event.currentTarget.firstElementChild;
selector.value = randomColor();
// This doesn't pass the x and y coordinates.
selector.click();
// This alternative approach doesn't work either.
//selector.dispatchEvent(new MouseEvent(event.type, event));
event.currentTarget.style.backgroundColor = selector.value;
});
div.addEventListener('input', event => {
event.currentTarget.style.backgroundColor = event.currentTarget.firstElementChild.value;
});
#div {
border: 1px solid;
border-radius: 25px;
height: 50px;
padding: 0;
width: 50px;
}
#color {
display: none;
}
<div id="div">
<input id="color" type="color">
</div>
Is there a standards-compliant approach to this that doesn't break Chrome's placement of the color selector box?