I am trying to make a radio button using the radio type of the <input>
. Instead of label, components are bundled together, and instead of using packages such as MUI
, I try to use the <input>
tag directly.
The functions I want are:
I succeeded change the color using the accent-color
property. However, the color of both the outer circle and the inner circle changes together. Is there a way to satisfy all of the above functions using <input type="radio"..>
?
There's no way (as far as I know) to reliably exert full control over the appearance of the input itself.
However, there is a common trick to overcome this limitation: hide the actual input and render a pseudo-element in its place, as in the example below.
I've wrapped the inputs in a <label>
here so that clicks still trigger the native inputs to check/uncheck.
Note that because inputs may be replaced elements it's possible that input::after
won't work in every browser. If it's a problem you could use an actual span (or whatever) instead.
Also: I haven't needed to solve this problem in a long time, so my method may be outdated. There are several articles and demos to be found that may give you other solutions or better ideas.
.radio {
--size: 30px;
--padding: calc(var(--size) + 1em);
position: relative;
margin: .25em;
min-height: var(--size);
padding-left: var(--padding);
cursor: pointer;
}
.radio input {
visibility: hidden;
position: absolute;
}
input[type=radio]::after {
--color-border: lightgray;
--color-dot: var(--color-border);
content: '';
visibility: visible;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: calc(var(--padding) * -1);
width: var(--size);
height: var(--size);
border-radius: 50%;
color: lightgray;
background: radial-gradient(var(--color-dot) 0%, var(--color-dot) 40%, white 40%);
box-shadow: 0 0 0 2px var(--color-border);
pointer-events: none;
}
input[type=radio]:checked::after {
--color-dot: blue;
}
<label class="radio">
<input type="radio" name="demo" value="1" checked />
One
</label>
<label class="radio">
<input type="radio" name="demo" value="2" />
Two
</label>
<label class="radio">
<input type="radio" name="demo" value="3" />
Three
</label>