html - 仅使用 CSS 内部带有选项的菜单切换
问题描述
我正在尝试创建一个包含选项的菜单。我只使用带有checkbox
和radio
输入的 CSS。
通过更改其中一个选项,我还希望关闭菜单。我尝试使用label
inside label
,但它不起作用。我的原型代码:
input {
display: none;
}
label {
cursor: pointer;
}
label span:hover {
font-weight: 600;
}
.opener .menu {
background-color: #f3f3f3;
display: flex;
flex-direction: column;
color: #4d4d4d;
padding: 12px 4px;
width: 270px;
}
#menu:checked~.opener .menu {
display: none;
}
#menu~.opener>span:nth-of-type(1) {
display: none;
}
#menu:~.opener>span:nth-of-type(2) {
display: block;
}
#menu:checked~.opener>span:nth-of-type(1) {
display: block;
}
#menu:checked~.opener>span:nth-of-type(2) {
display: none;
}
.box {
height: 50px;
width: 50px;
margin: 20px 0;
}
#red:checked~.box {
background-color: red;
}
#blue:checked~.box {
background-color: blue;
}
#green:checked~.box {
background-color: green;
}
<input id="menu" type="checkbox"></input>
<input id="red" type="radio" name="opcoes" checked></input>
<input id="blue" type="radio" name="opcoes"></input>
<input id="green" type="radio" name="opcoes"></input>
<label class="opener" for="menu"><span>Open</span><span>Close</span>
<div class="menu">
<label for="red"><span>red</span></label>
<label for="blue"><span>blue</span></label>
<label for="green"><span>green</span></label>
</div>
</label>
<div class="box"></div>
或者你可以在这里查看:https ://codepen.io/anon/pen/JxzPKR
当您在没有 JavaScript 的情况下单击其中一个选项时,有没有办法关闭菜单?
解决方案
Sometimes, contrary to popular opinion, it's just more dev friendly to use Javascript.
There is too much conditional logic for this to be a pure CSS solution. There are ~3 if-then-else
conditions you would have to satisfy, while keeping the styles cascading. I think the most arduous task to satisfy is that you have a toggle header, in addition to other controls toggling it.
This will inherently get more complex and convoluted the more components you add. But here is an example using :target
. This is a work-around and provides a solution to the question at hand. You won't be able to 'toggle' the menu this way so I had to add the header under the elements so it can be accessed via some kind of sibling selector:
.menu {
position: relative;
width: 45%;
}
input[type="radio"] {
position: absolute;
opacity: 0;
height: 0;
width: 0;
}
a:any-link {
all: unset;
}
.menu-header {
position: absolute;
top: 0;
padding: 5px 10px;
color: white;
width: 100%;
background-color: cornflowerblue;
}
.menu-header a {
font-weight: bold;
cursor: pointer;
color: white;
font-size: 22px;
}
.menu-header .close {
display: none;
}
#menu-body {
display: none;
flex-flow: column nowrap;
position: absolute;
top: 34px;
background-color: rgba(220,220,220,1);
height: 100px;
color: black;
width: 100%;
padding: 10px;
}
.menu-header a,
#menu-body label {
cursor: pointer;
}
#menu-body:not(:target) {
display: none;
}
#menu-body:not(:target) + .menu-header > a:not(.close) {
display: inline-block;
}
#menu-body:target {
display: flex;
}
#menu-body:target + .menu-header > a {
display: none;
}
#menu-body:target + .menu-header > a.close {
display: inline-block;
}
<div class="menu">
<div id="menu-body">
<input id="red" type="radio" name="opcoes" checked/>
<label for="red"><a href="#">Red</a></label>
<input id="blue" type="radio" name="opcoes"/>
<label for="blue"><a href="#">Blue</a></label>
<input id="green" type="radio" name="opcoes"/>
<label for="green"><a href="#">Green</a></label>
</div>
<div class="menu-header"><a href="#menu-body">≡ Open</a><a href="#" class="close">≡ Close</a></div>
</div>
You should consider accessability using this method, or at minimum, how this effects site navigation.
Edit: A demo in regards to discussion in comments:
.menu {
position: relative;
width: 45%;
}
input[type="radio"] {
position: absolute;
opacity: 0;
height: 0;
width: 0;
}
a:any-link {
all: unset;
}
#menu-header {
position: absolute;
top: 0;
padding: 5px 10px;
color: white;
width: 100%;
background-color: cornflowerblue;
}
#menu-header a {
font-weight: bold;
cursor: pointer;
color: white;
font-size: 22px;
}
#menu-header .close {
display: none;
}
#menu-body {
display: none;
flex-flow: column nowrap;
position: absolute;
top: 34px;
background-color: rgba(220,220,220,1);
height: 100px;
color: black;
width: 100%;
padding: 10px;
}
.menu-header a,
#menu-body label {
cursor: pointer;
}
#menu-body:not(:target) {
display: none;
}
#menu-body:not(:target) ~ .menu-header > a:not(.close) {
display: inline-block;
}
#menu-body:target {
display: flex;
}
#menu-body:target ~ #menu-header > a {
display: none;
}
#menu-body:target ~ #menu-header > a.close {
display: inline-block;
}
#red:target ~ .box {
background-color: red;
}
#blue:target ~ .box {
background-color: blue;
}
#green:target ~ .box {
background-color: green;
}
.box {
background-color: black;
width: 75px; height : 75px;
}
<div class="menu">
<input id="red" type="radio" name="opcoes" checked/>
<input id="blue" type="radio" name="opcoes"/>
<input id="green" type="radio" name="opcoes"/>
<div id="menu-body">
<a href="#red">Red</a>
<a href="#blue">Blue</a>
<a href="#green">Green</a>
</div>
<div class="box"></div>
<div id="menu-header">
<a href="#menu-body">≡ Open</a>
<a href="#" class="close">≡ Close</a>
</div>
</div>
推荐阅读
- swift - 如何减少从 NSLocale.Key.currencyCode 返回的货币代码数量
- excel - 在动态表上使用 VBA 的 Excel-IE 自动化
- c++ - 在 vector.push_back(foo{}) 三次调用构造函数时创建的静态结构对象
- java - 在 TouchImageView 中获取图像的点击位置,并按比例调整图像的大小以缩放?
- python - XGBoost 收敛于高深度和儿童体重
- arrays - 在数组中搜索数据 [Node.JS]
- hl7-fhir - 使用 HL7-FHIR 标准的提供者信息
- prestashop - 在 Prestashop 1.6 中付款后我应该使用哪个钩子来获取有关购物车的信息
- ios - 两个垂直集合视图和它们之间的标签以作为一个元素一次滚动
- c# - 将计算列的结果从数据库获取到实体中