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:
- A circle exists inside regardless of whether it is checked or not. Instead, it is displayed in gray when it is unchecked and blue when it is checked.
- I can change the color of the radio button. However, when checked, the color of the border of the outer circle does not change (the default behavior is that the color of both the outer circle and the inner circle changes).
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"..>
?
CodePudding user response:
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 >
<input type="radio" name="demo" value="1" checked />
One
</label>
<label >
<input type="radio" name="demo" value="2" />
Two
</label>
<label >
<input type="radio" name="demo" value="3" />
Three
</label>