I am trying to come up with pure css menu with submenus (no js), out of curiosity.
Link to jsfiddle and code snippet below:
// no javascript
label {
cursor: pointer;
user-select: none;
}
label:hover {
text-decoration: underline;
}
ul > li > ul {
display: none;
}
#example1,
#example2,
#example3,
#example4 {
background: #eee;
display: inline-block;
}
#example1 > li > input,
#example2 > li > input {
/*display: none;*/
}
#example1 > li > input:checked + ul,
#example2 > li > input:checked + ul {
display: block;
}
#example3 > li > input[type="radio"]:checked + input[type="checkbox"]:checked + ul {
display: block;
}
#example4:hover > li > input[type="radio"]:checked + ul {
display: block;
}
<h3>Can collapse all, <u>BUT</u> can't display a sigle submenu at the time</h3>
<ul id="example1">
<li>
<label for="categories">Category</label>
<input id="categories" type="checkbox">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label for="settings">Settings</label>
<input id="settings" type="checkbox">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
<h3>Can display a sigle submenu at the time, <u>BUT</u> can't collapse all</h3>
<ul id="example2">
<li>
<label for="categories2">Category</label>
<input id="categories2" type="radio" name="menu">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label for="settings2">Settings</label>
<input id="settings2" type="radio" name="menu">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
<h3>Can display a sigle submenu at the time <u>and</u> can collapse all, <u>BUT</u> requires more then 1 click</h3>
<ul id="example3">
<li>
<label for="categories3check">Category</label>
<input id="categories3radio" type="radio" name="menu">
<input id="categories3check" type="checkbox">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label for="settings3check">Settings</label>
<input id="settings3radio" type="radio" name="menu">
<input id="settings3check" type="checkbox">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
<h3>Can display a sigle submenu at the time <u>and</u> can collapse all, <u>BUT</u> uses hover and if radio is selected it opens submenu on hover</h3>
<ul id="example4">
<li>
<label for="categories4radio">Category</label>
<input id="categories4radio" type="radio" name="menu">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label for="settings4radio">Settings</label>
<input id="settings4radio" type="radio" name="menu">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
I was trying to think outside of the box but ran out of options.
Link to jsfiddle and code snippet below, with plenty of jQuery:
$("span").click(function() {
var display = $(this).next()[0].style.display;
$("ul > li > ul").hide();
if (display == "" || display == "none")
$(this).next().show();
else if (display == "block")
$(this).next().hide();
});
ul > li > ul {
display: none;
}
span {
user-select: none;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<span>Category</span>
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<span>Settings</span>
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
Is it possible to accomplish such submenu functionality without js? If yes, how. If not, why not? Any amount hacks in any order is acceptable, as long as just html/css is used and no js.
This answer is build on top of @kuzkuz's answer that uses :focus
. Thank you very much @kuzkuz.
The ides is to have yet another transparent "hider" span that becomes displayed on :focus
and is positioned on top of menu link. Clicking "hider" span will cause to "unfocus" menu item.
// no javascript
label {
cursor: pointer;
user-select: none;
text-decoration: underline;
}
ul>li>ul {
display: none;
position: relative;
top: -20px;
margin-top: 0;
}
#example1 {
display: inline-block;
}
#example1>li>input {
display: none;
}
#example1>li>label:focus~ul {
display: block;
}
label:focus {
outline: none;
}
label:focus + .hider {
width: 60px;
height: 20px;
display: block;
position: relative;
top: -20px;
cursor: pointer;
/* background: rgba(255,0,0,0.2); */
}
.visible {
background: rgba(255,0,0,0.2);
<h3>Invisible hider</h3>
<ul id="example1">
<li>
<label tabindex='-1' for="categories">Category</label>
<span class="hider"></span>
<input id="categories" type="checkbox">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label tabindex='-1' for="settings">Settings</label>
<span class="hider"></span>
<input id="settings" type="checkbox">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
<h3>Visible hider for demonstation purposes</h3>
<ul id="example1">
<li>
<label tabindex='-1' for="categories">Category</label>
<span class="hider visible"></span>
<input id="categories" type="checkbox">
<ul>
<li>cars</li>
<li>animals</li>
</ul>
</li>
<li>
<label tabindex='-1' for="settings">Settings</label>
<span class="hider visible"></span>
<input id="settings" type="checkbox">
<ul>
<li>general</li>
<li>notifications</li>
</ul>
</li>
</ul>
Edit: here is styled, more better looking version based on this silly concept: codepen