Описанное поведение OP относится к группе <input type='radio'>
, имеющей один и тот же атрибут [name]
- можно отметить только одну радиокнопку.
Добавление visibility:collapse/visible
max-height:0/(large number)px
, transition
до <li>
и overflow:hidden
до <ul>
делает анимированные свертки / развёртывание списков.Также псевдоэлемент ::after
, CSS-функция attr()
и data-idx
были использованы для того, чтобы текст каждой метки переключал текст «открыть / закрыть».
JavaScript и добавлен тег <form>
позволяет переключателю переключаться как флажок.Теперь оба поведения реализованы, детали прокомментированы в демонстрационной версии.
// Register the first <form> to click event callback is chx()
document.forms[0].onclick = chx;
/*
//A Pass the Event Object
//B Reference the clicked tag's (e.target) preceding
adjacent sibling tag (radio button before clicked
label (e.target))
//C if the clicked tag is a <label>...
//D and if the radio button occuring before the clicked
label is checked...
//E -- uncheck it...
//F otherwise check it
*/
function chx(e) { //A
const node = e.target.previousElementSibling; //B
if (e.target.matches('label')) { //C
if (node.checked) { //D
node.checked = false; //E
} else {
node.checked = true; //F
}
}
return false;
}
.node {
display: none
}
label {
cursor: pointer
}
ul {
overflow: hidden
}
.node+label::after {
content: ' open list 'attr(data-idx);
}
.node+label+ul li {
visibility: collapse;
max-height: 0;
transition: 1s;
}
.node:checked+label::after {
content: ' close list 'attr(data-idx);
}
.node:checked+label+ul li {
visibility: visible;
max-height: 500px;
transition: 1s;
}
<form onsubmit='return false'>
<ul class="lists">
<li>
<input id="node1" name='node' class='node' type="radio">
<label for="node1" data-idx='1'>Click to</label>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</li>
<li>
<input id="node2" name='node' class='node' type="radio">
<label for="node2" data-idx='2'>Click to</label>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
</li>
</ul>
</form>