具有功能面包屑导航的纯 css 多层菜单
Pure css multi-tiered menu with functioning breadcrumb navigation
我正在尝试创建一个带有面包屑导航的多层菜单,但不使用 javascript。我遇到过大量纯 css 菜单和面包屑,但从未组合在一起工作。这是我想要实现的设计(点击“更多”汉堡菜单):
这就是我目前在 html/css 中的内容(参见下面的代码笔 link)。请原谅 crude/hacky 代码。目前我只是在测试想法,找到解决方案后我会简化和美化我的代码。
http://codepen.io/jessbenz/pen/LZWjjz
这是一个代码片段,但请查看上面的代码笔 link 以获得更好的感受:
<div class="smart-nav">
<input type="radio" id="bread-home" class="breadcrumb" name="bread" />
<input type="radio" id="bread-women" class="breadcrumb" name="bread" />
<input type="radio" id="bread-womens-clothing" class="breadcrumb" name="bread" />
<div class="smart-nav-panels">
<ul id="home">
<li>
<input type="radio" name="first">
<label>1 Women</label>
<ul id="women">
<li>
<input type="radio" name="second">
<label>1.1 Women's Clothing</label>
<ul id="womens-clothing">
<li>
<label>1.1.1 Women's Shirts</label>
</li>
</ul>
</li>
</ul>
</li>
<li>
<input type="radio" name="first">
<label>2 Men</label>
<ul id="men">
<li>2.1 Men's Shirts</li>
</ul>
</li>
</ul>
</div>
</div>
和我的 sass:
.breadcrumb:checked ~ .smart-nav-panels ul {
display: none;
}
#bread-home:checked ~ .smart-nav-panels > ul {
display: block;
}
#bread-women:checked ~ .smart-nav-panels {
#home, #women {
display: block;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#home, #women, #womens-clothing {
display: block;
}
}
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
display: block;
}
.smart-nav-panels {
margin: 0;
padding: 0;
ul {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background: lightgrey;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
}
> ul:first-child {
ul {
left: 100%;
}
}
li {
input + label + ul {
display: none;
}
input:checked + label + ul {
display: block;
// left:0;
}
}
}
input:checked ul {
display: block;
}
如果您点击我的 codepen 样本中的女装,您会发现我已经完成了一半,已经达到了我的需要。顶部的水平单选按钮代表面包屑,灰色块内的垂直单选按钮代表层级菜单。当我 select 面包屑收音机时,问题就来了。显示了正确的幻灯片,但是如果我再次 select 菜单中的收音机,它不会显示,因为我的面包屑 css 正在优先选择并隐藏相关内容。我想这就是不使用 javascript 的问题所在。如何使用纯 css 让我的两个导航相互了解?可能这种结合两个无线电导航的方法是不正确的。我真的希望有人能分享他们的智慧。 :)
提前致谢
你不会回避挑战,是吗? :)
在我展开更多细节之前,我会说简短的回答是 "build a static site"。换句话说,假设您的设计约束之一是 "no javascript",将问题移到您 确实 可以使用决策逻辑/代码的地方,以使其更容易解决(即:服务器)。
即使你设法解决了这个问题(考虑到 HTML/CSS 的限制,我不确定这是否可能),你将遇到的下一个问题是将任何类型的行为附加到它全部。您将要根据菜单选择加载特定内容,而您要这样做的唯一方法是:
- 一个javascript事件,或
- 静态 link(锚元素,因此 'why' 在我的简短回答后面)
可以加载所有内容,也许可以找到一种有条件地显示它的方法,但问题是 "how deep does the rabbit hole go?"。另外,如果您正在为功能手机构建 and/or 连接速度慢,加载所有内容将对用户体验产生负面影响。
说了这么多,我设法稍微简化了 CSS 并修复了子类别显示的错误(参见内联评论)。请注意,只有 'Women' 类别的行为符合预期,因为 'Men' 和 'Kids'.
缺少样式
.container {
position: relative;
width: 360px;
height: 480px;
border: 1px solid black;
margin: 20px auto 0 auto;
}
.breadcrumb {
margin-top: -20px;
display: inline-block;
vertical-align: top;
}
/*
.breadcrumb:checked ~ .smart-nav-panels ul {
display: none;
}
#bread-home:checked ~ .smart-nav-panels > ul {
display: block;
}
*/
/* hide all uls except the 'home' ul by default, replaces both of the above */
.smart-nav-panels ul ul {
display: none;
}
/*
#bread-women:checked ~ .smart-nav-panels {
#home, #women {
display: block;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#home, #women, #womens-clothing {
display: block;
}
}
*/
/* these next 3 style definitions are very similar to what you had before (commented
above), except that there is no longer a need to unhide the 'home' ul, and we're
being more explicit about which uls to hide in correspondence with the state of the
breadcrumb nav */
#bread-home:checked ~ .smart-nav-panels {
#women {
display: none;
}
}
#bread-women:checked ~ .smart-nav-panels {
#women {
display: block;
}
#womens-clothing, #womens-shoes {
display: none;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#women, #womens-clothing {
display: block;
}
}
/*
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
display: block;
}
*/
/* (i) the above didn't work because the ul isn't a direct descendant of the input,
rather it is a sibling, and in addition it doesn't matter which breadcrumb item is
checked now */
.smart-nav-panels li input:checked ~ ul {
display: block;
}
.smart-nav-panels {
margin: 0;
padding: 0;
ul {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background: lightgrey;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
}
> ul:first-child {
ul {
left: 100%;
}
}
/* removed unnecessary styles here */
}
/* removed unnecessary style here */
这已经解决了一些问题,但还有更多问题。我怀疑,解决其中一些问题会产生新的问题。我能立即想到的一个方法是,您希望将分层菜单的状态与面包屑联系起来,这样您就只能看到您应该看到的面包屑(现在您总是看到所有的面包屑)的)。
在某些时候,您需要 事件(用于行为)并且组件需要了解彼此的 状态。虽然 CSS 具有 一些 状态功能,但它在事件方面不提供任何内容。这些限制、级联性质(在其他问题中进行了深入讨论,例如:缺少祖先选择器)以及与 HTML 结构的耦合都有助于使这个问题很难用 HTML & [ 解决=52=]一个人.
我理解在没有 JS 的情况下拥有这种类型的导航的愿望,当然这是一个值得尝试和解决的有趣问题,但最终我认为这是错误的解决方法。
javascript 如此普遍是有原因的 - 如果没有它,我们今天的网络体验将大不相同。
(感谢 Jess 和其他同事的讨论,为这个答案的部分内容提供了信息。我自由地解释了。希望这对其他人有好处。)
我正在尝试创建一个带有面包屑导航的多层菜单,但不使用 javascript。我遇到过大量纯 css 菜单和面包屑,但从未组合在一起工作。这是我想要实现的设计(点击“更多”汉堡菜单):
这就是我目前在 html/css 中的内容(参见下面的代码笔 link)。请原谅 crude/hacky 代码。目前我只是在测试想法,找到解决方案后我会简化和美化我的代码。
http://codepen.io/jessbenz/pen/LZWjjz
这是一个代码片段,但请查看上面的代码笔 link 以获得更好的感受:
<div class="smart-nav">
<input type="radio" id="bread-home" class="breadcrumb" name="bread" />
<input type="radio" id="bread-women" class="breadcrumb" name="bread" />
<input type="radio" id="bread-womens-clothing" class="breadcrumb" name="bread" />
<div class="smart-nav-panels">
<ul id="home">
<li>
<input type="radio" name="first">
<label>1 Women</label>
<ul id="women">
<li>
<input type="radio" name="second">
<label>1.1 Women's Clothing</label>
<ul id="womens-clothing">
<li>
<label>1.1.1 Women's Shirts</label>
</li>
</ul>
</li>
</ul>
</li>
<li>
<input type="radio" name="first">
<label>2 Men</label>
<ul id="men">
<li>2.1 Men's Shirts</li>
</ul>
</li>
</ul>
</div>
</div>
和我的 sass:
.breadcrumb:checked ~ .smart-nav-panels ul {
display: none;
}
#bread-home:checked ~ .smart-nav-panels > ul {
display: block;
}
#bread-women:checked ~ .smart-nav-panels {
#home, #women {
display: block;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#home, #women, #womens-clothing {
display: block;
}
}
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
display: block;
}
.smart-nav-panels {
margin: 0;
padding: 0;
ul {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background: lightgrey;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
}
> ul:first-child {
ul {
left: 100%;
}
}
li {
input + label + ul {
display: none;
}
input:checked + label + ul {
display: block;
// left:0;
}
}
}
input:checked ul {
display: block;
}
如果您点击我的 codepen 样本中的女装,您会发现我已经完成了一半,已经达到了我的需要。顶部的水平单选按钮代表面包屑,灰色块内的垂直单选按钮代表层级菜单。当我 select 面包屑收音机时,问题就来了。显示了正确的幻灯片,但是如果我再次 select 菜单中的收音机,它不会显示,因为我的面包屑 css 正在优先选择并隐藏相关内容。我想这就是不使用 javascript 的问题所在。如何使用纯 css 让我的两个导航相互了解?可能这种结合两个无线电导航的方法是不正确的。我真的希望有人能分享他们的智慧。 :)
提前致谢
你不会回避挑战,是吗? :)
在我展开更多细节之前,我会说简短的回答是 "build a static site"。换句话说,假设您的设计约束之一是 "no javascript",将问题移到您 确实 可以使用决策逻辑/代码的地方,以使其更容易解决(即:服务器)。
即使你设法解决了这个问题(考虑到 HTML/CSS 的限制,我不确定这是否可能),你将遇到的下一个问题是将任何类型的行为附加到它全部。您将要根据菜单选择加载特定内容,而您要这样做的唯一方法是:
- 一个javascript事件,或
- 静态 link(锚元素,因此 'why' 在我的简短回答后面)
可以加载所有内容,也许可以找到一种有条件地显示它的方法,但问题是 "how deep does the rabbit hole go?"。另外,如果您正在为功能手机构建 and/or 连接速度慢,加载所有内容将对用户体验产生负面影响。
说了这么多,我设法稍微简化了 CSS 并修复了子类别显示的错误(参见内联评论)。请注意,只有 'Women' 类别的行为符合预期,因为 'Men' 和 'Kids'.
缺少样式.container {
position: relative;
width: 360px;
height: 480px;
border: 1px solid black;
margin: 20px auto 0 auto;
}
.breadcrumb {
margin-top: -20px;
display: inline-block;
vertical-align: top;
}
/*
.breadcrumb:checked ~ .smart-nav-panels ul {
display: none;
}
#bread-home:checked ~ .smart-nav-panels > ul {
display: block;
}
*/
/* hide all uls except the 'home' ul by default, replaces both of the above */
.smart-nav-panels ul ul {
display: none;
}
/*
#bread-women:checked ~ .smart-nav-panels {
#home, #women {
display: block;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#home, #women, #womens-clothing {
display: block;
}
}
*/
/* these next 3 style definitions are very similar to what you had before (commented
above), except that there is no longer a need to unhide the 'home' ul, and we're
being more explicit about which uls to hide in correspondence with the state of the
breadcrumb nav */
#bread-home:checked ~ .smart-nav-panels {
#women {
display: none;
}
}
#bread-women:checked ~ .smart-nav-panels {
#women {
display: block;
}
#womens-clothing, #womens-shoes {
display: none;
}
}
#bread-womens-clothing:checked ~ .smart-nav-panels {
#women, #womens-clothing {
display: block;
}
}
/*
#bread-home:checked ~ .smart-nav-panels li input:checked > ul:first-child {
display: block;
}
*/
/* (i) the above didn't work because the ul isn't a direct descendant of the input,
rather it is a sibling, and in addition it doesn't matter which breadcrumb item is
checked now */
.smart-nav-panels li input:checked ~ ul {
display: block;
}
.smart-nav-panels {
margin: 0;
padding: 0;
ul {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background: lightgrey;
}
ul, li {
list-style: none;
margin: 0;
padding: 0;
}
> ul:first-child {
ul {
left: 100%;
}
}
/* removed unnecessary styles here */
}
/* removed unnecessary style here */
这已经解决了一些问题,但还有更多问题。我怀疑,解决其中一些问题会产生新的问题。我能立即想到的一个方法是,您希望将分层菜单的状态与面包屑联系起来,这样您就只能看到您应该看到的面包屑(现在您总是看到所有的面包屑)的)。
在某些时候,您需要 事件(用于行为)并且组件需要了解彼此的 状态。虽然 CSS 具有 一些 状态功能,但它在事件方面不提供任何内容。这些限制、级联性质(在其他问题中进行了深入讨论,例如:缺少祖先选择器)以及与 HTML 结构的耦合都有助于使这个问题很难用 HTML & [ 解决=52=]一个人.
我理解在没有 JS 的情况下拥有这种类型的导航的愿望,当然这是一个值得尝试和解决的有趣问题,但最终我认为这是错误的解决方法。 javascript 如此普遍是有原因的 - 如果没有它,我们今天的网络体验将大不相同。
(感谢 Jess 和其他同事的讨论,为这个答案的部分内容提供了信息。我自由地解释了。希望这对其他人有好处。)