Hi there I really never had this problem but today I dont't really understand why the focus is not working - I tried to built a custom switch without using js --- and it looks good and with the mouse it is working. Unfortunately not with the focus state -
but here is the code:
input {
appearance: none;
position: relative;
display: inline-block;
background: lightgrey;
height: 1.65rem;
width: 2.76rem;
vertical-align: middle;
border-radius: 2rem;
box-shadow: 0px 1px 3px #0003 inset;
transition: 0.25s linear background;
}
input::before {
content: "";
display: block;
width: 1.25rem;
height: 1.25rem;
background: #fff;
border-radius: 1.2rem;
position: absolute;
top: .2rem;
left: .2rem;
box-shadow: 0px 1px 3px #0003;
transition: 0.25s linear transform;
transform: translateX(0rem);
}
:checked {
background: green;
}
:checked::before {
transform: translateX(1rem);
}
input:focus-visible {
outline: 2px solid dodgerblue;
outline-offset: 2px;
}
input:focus {
outline: none;
outline-color: transparent;
}
`
<label for="awesomeFeature">
<input type="checkbox" name="awesomeFeature" id="awesomeFeature">
my awesome feature
</label>
I expect the focus highlightning
This is because the CSS selectors input:focus-visible
and input:focus
are both matching when the element is focused.
:focus-visible
is not more specific than :focus
. In the absence of any other selectors, the browser sees your input:focus-visible
and input:focus
selectors to be as important as each other. Now, your input:focus-visible
rules have a visible outline, but your input:focus
rules have an outline of none
. The browser can't do both, so it picks the final rule of that specificity to be the one that's applied. The input:focus
's rule wins out and the element is given an outline of none
.
To fix this you could re-order your CSS:
input:focus {
outline: none;
outline-color: transparent;
}
input:focus-visible {
outline: 2px solid dodgerblue;
outline-offset: 2px;
}
With this the :focus-visible
rule is last and thus will be the one applied.