仅使用 CSS 创建折叠导航
虽然使用 JavaScript 打开移动导航是一个不错的选择,但仅使用 CSS 也可以实现。即使是子菜单也不一定需要任何 JS 才能工作,伪类和兄弟选择器就是答案!
如何
折叠导航通常由被亲切地称为“汉堡菜单”的图标触发,该图标指的是三条水平线。这是一个备受争议的图标,但人们已经习惯了它,所以现在我们先坚持使用它。
要创建纯 CSS 导航,我们需要使用<input />
带有 的元素type="checkbox"
,并使用:checked
伪类 来判断它是否被选中。此外,我们还需要一个<label>
,并通过属性链接到 input 元素for
。
这是我通常创建的简化版本,为了清晰起见,我使用元素而不是类来设置样式:
<nav>
<input type="checkbox" id="trigger" />
<label aria-label="open main navigation" for="trigger"><span></span></label>
<ul>
<li>
<a href="#">Link</a>
</li>
<li>
<a href="#">Link</a>
</li>
<li>
<a href="#">Link</a>
</li>
</ul>
</nav>
请注意,我将标签元素放在输入元素之后,这样就可以通过输入的状态(:focus
、:checked
等)来设置标签的样式。
隐藏复选框
复选框输入框需要完全消失。我添加了位置固定,因为导航的其余部分是固定的,点击复选框标签的标准行为是滚动到它,这意味着滚动到顶部。
input {
opacity: 0;
width: 0;
height: 0;
appearance: none;
position: fixed;
}
创建触发器
您可以在此处添加汉堡图标的背景图片,也可以使用 before 和 after 选择器来创建它们。这是触发器的可见部分,它将代表“导航已关闭!”状态。
您可能对标签span
内的“不必要”感到疑惑label
,我添加它是为了使其样式更容易,您可以将跨度省略。
label {
position: fixed;
top: 0;
right: 0;
z-index: 10;
display: flex;
align-items: center;
width: 15px;
height: 10px;
margin: 40px;
}
label span {
display: block;
width: 100%;
background: hotpink;
height: 2px;
transition: transform 1s;
}
label span::before,
label span::after {
content: "";
position: absolute;
left: 0;
right: 0;
display: block;
height: 2px;
background: hotpink;
transition: 0.4s
}
label span::before {
top: 0;
}
label span::after {
top: calc(100% - 2px); /* to make the transition easier :) */
}
隐藏导航
虽然你可以直接display: none
在这里添加,然后display: block
在需要显示时使用变换会更有趣。
我选择ul
在 X 轴上平移 100vw,让它在屏幕上隐藏,直到用户点击触发器。
ul {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
transform: translateX(100vw);
transition: transform 0.2s;
background: white;
}
创造“开放状态”
我之前谈到过使用 :checked 伪类,伪类是在元素具有某种状态时添加到元素的关键字。
单选按钮和复选框输入类型都有:checked
状态。复选框可以通过点击来选中或取消选中,而要选中另一个单选按钮则需要另一个按钮。复选框更符合我们的目标,所以我们使用它们。
这是为导航触发器的打开状态添加 CSS 的地方,很多网站都没有对此进行样式和动画处理,在我看来这是一种遗憾。
如果您是 CSS 新手,这段代码可能看起来比较难懂,但如果您大声朗读出来,有时能帮助您更清楚地理解。例如,第一行:选择已选中的“input”的同级“label”的内部元素“span”。
好吧,这听起来还是有点乱,但熟能生巧。
input:checked + label span {
transform: rotate(45deg);
}
input:checked + label span::before, input:checked + label span::after {
top: calc(50% - 1px);
transition: 0.4s;
}
input:checked + label span::after {
transform: rotate(90deg);
}
显示导航
我在这里使用了通用同级选择器,这意味着“选择任何已检查输入的同级 ul”,input:checked + label + ul
也可以起作用,但对错误更敏感(如果在其间添加一个元素会怎样?)。
input:checked ~ ul {
transform: none;
transition: transform 0.4s;
}
带有贝塞尔曲线和所有精美内容的漂亮 SCSS 版本:
但为什么?
因为我们可以!
这看起来比仅仅用 JavaScript 添加一个类要复杂得多,你可能是对的。如果你想更好地处理伪类和兄弟选择器,这不仅是一个很好的练习,而且它非常坚固。想象一下,你的网站在 JS 中出现了一个小错误,这意味着人们将无法再使用你的导航。让我们把那些疯狂的动画留给 JavaScript,把像打开和关闭导航这样的简单操作保留为 CSS 代码。
可访问性
抛弃整篇文章的一个好观点是,使用输入元素来打开和关闭导航是不符合语义的。
但如果你认真想想,大多数使用屏幕阅读器的人(可能会注意到你使用了一个input
元素而不是一个更具语义的button
元素的群体)并不是真正的开发人员,但你可能会惹恼盲人开发人员,要小心。
触发器可以通过键盘自动访问,如果您还添加一个清晰的触发器,那么aria-label
您所做的就比大多数使用button
打开折叠导航的开发人员做得更多。
我真的很想听听盲人用户或无障碍专家的意见,如果我真的一无所知,请在评论中告诉我。
文章来源:https://dev.to/cydstumpel/creating-a-fold-out-navigation-with-css-only-4g9k