The timer label doesn't show up after I checked the countdown, here's the HTML structure and the CSS:
details {
display: flex;
/* Use flexbox layout */
flex-direction: column;
/* Stack children vertically */
width: 100%;
/* Full width of the container */
font-size: 0.8em;
/* Smaller font size */
column-gap: 5px;
/* Space between flex items */
}
summary {
margin-bottom: 10px;
}
label {
display: flex;
align-items: center;
gap: 5px;
margin-bottom: 10px;
}
/* More options section */
#timer {
width: 4ch;
text-align: center;
outline: none;
}
label[for='timer'] {
display: none;
}
input[name='countdown']:checked~label[for='timer'] {
display: flex;
}
/* end of options section */
<details>
<summary>More options...</summary>
<label for="blip">
<input type="checkbox" name="blipping" id="blip"> Blipping
</label>
<label for="countdown">
<input type="checkbox" name="countdown" id="countdown"> Countdown
</label>
<label for="timer">
Countdown: <input type="number" name="timer" id="timer" min="5" max="999"> Second
</label>
</details>
I've tried covering the label with a div, but the sibling combinator still didn't detect it, and still gives the same result.
The point of the question is that I want to toggle the "timer" label when user checks/unchecks the "countdown" checkbox with using only CSS.
The problem you're encountering is that the sibling combinator can't work the way you've written the code, given the following HTML (a lightly formatted/tidied copy of your posted HTML):
<label for="countdown">
<input type="checkbox" name="countdown" id="countdown"> Countdown
</label>
<label for="timer">
Countdown: <input type="number" name="timer" id="timer" min="5" max="999"> Second
</label>
The selector you're working with:
input[name='countdown']:checked~label[for='timer'] {
display: flex;
}
requires that the checked "countdown" <input>
is a preceding sibling of the <label>
element, which it isn't; the <label>
is the adjacent sibling of the parent of the "countdown" <input>
element.
So, instead – depending on the browser compatibility of your user-base – you could make use of the :has()
selector, and use:
/*
here we initially select the <label> element with the "for"
attribute equal to "countdown", which contains a checked <input>
element and then select its following sibling <label> element
(using the same general sibling combinator) that has a "for"
attribute equal to "timer":
*/
label[for=countdown]:has(input:checked) ~ label[for=timer] {
/* I'm using display: initial to update the display, that way
the browser can decide for itself to display it as block,
flex-item, grid-item, list-item... according to the CSS
cascade: */
display: initial;
}
details {
display: flex;
/* Use flexbox layout */
flex-direction: column;
/* Stack children vertically */
width: 100%;
/* Full width of the container */
font-size: 0.8em;
/* Smaller font size */
column-gap: 5px;
/* Space between flex items */
}
summary {
margin-bottom: 10px;
}
label {
display: flex;
align-items: center;
gap: 5px;
margin-bottom: 10px;
}
/* More options section */
#timer {
width: 4ch;
text-align: center;
outline: none;
}
label[for='timer'] {
display: none;
}
label[for=countdown]:has(input:checked)~label[for=timer] {
display: initial;
}
/* end of options section */
<details>
<summary>More options...</summary>
<label for="blip">
<input type="checkbox" name="blipping" id="blip"> Blipping
</label>
<label for="countdown">
<input type="checkbox" name="countdown" id="countdown"> Countdown
</label>
<label for="timer">
Countdown: <input type="number" name="timer" id="timer" min="5" max="999"> Second
</label>
</details>
References: