使用纯 CSS 制作的折叠标签页
是的,这又一篇关于纯 CSS 有多棒,以及如何不用一行 JavaScript 就能做出酷炫作品的“文章”。我为什么要费心写它?因为我仍然着迷于纯 CSS 有多棒,以及如何不用一行 JavaScript 就能做出酷炫作品。
在我们开始之前,您可以在这里找到代码的演示,以及代码本身。欢迎随意探索和体验!
最后的小免责声明:这一切只是为了好玩,并向您展示 CSS 有多么神奇。
HTML结构
我们将使用非常简单的 HTML 标记来定义我们的手风琴标签:
.tabs-container
— 包装元素来承载所有与标签相关的元素;input.tab-actor
— 隐藏单选按钮来控制标签内容的可见性;label.tab-button
— 链接到输入的标签,用作标签按钮;.tab-content
— 包装您认为值得放入的任何内容;
最小的例子如下:
<div class="tab-container">
<input type="radio" id="tab-1" name="tabs" class="tab-actor" checked />
<label for="tab-1" class="tab-button">Lorem ipsum</label>
<section class="tab-content">
<div class="content">…</div>
</section>
</div>
工作原理
主要思路是利用 HTML 表单控件简单却强大的功能,通过 CSS 伪类来获取状态并访问状态。也就是说,我:checked
在这里使用了伪类。这意味着我使用组合器来设置已检查输入框的相邻兄弟元素的样式+
。
为了模拟标签页的行为,我需要只显示活动标签页的内容。所谓活动标签页,指的是最靠近已勾选单选按钮的内容。
单选按钮也应该隐藏,只留下链接的标签可见且可交互。
长话短说,这些标签页的工作原理就是这样的。让我们为这些标签页编写一些基本的 CSS 代码。
一些基本代码
:root {
--tab-button-order: 1;
--tab-content-order: 10;
}
.tab-container {
display: flex;
flex-wrap: wrap;
}
.tab-actor {
display: none;
}
.tab-button {
order: var(--tab-button-order);
}
.tab-content {
order: var(--tab-content-order);
display: none;
}
.tab-actor:checked + .tab-button + .tab-content {
display: block;
}
让我们仔细研究每条规则来了解发生了什么。
首先,我为 order 属性创建了一些 CSS 变量,这就是内部:root
规则。我们稍后再讨论这个问题。
.tab-container {
display: flex;
flex-wrap: wrap;
}
我们采用了弹性布局。它允许我们使用任意数量的标签页,因为它会自动分配其子元素。否则,我们需要手动设置固定宽度的值。
默认情况下,所有弹性项目都挤在一行中,但我们需要将 Tab 按钮放在顶部,将内容放在底部。使用flex-wrap: wrap
弹性布局可以将较大的元素放在下一行。
<input type="radio" id="tab-1" name="tabs" class="tab-actor" checked />
<label for="tab-1" class="tab-button">Lorem ipsum</label>
我们使用输入的属性和标签的属性将标签链接到输入id
。当输入-标签对的属性值相同时,点击标签会像直接点击输入一样激活输入。
这使我们能够隐藏输入:
.tab-actor {
display: none;
}
接下来,我们添加一些黑色弹性魔法来获得我们想要的布局。
HTML中我们已经写出了这样的结果:
[tab]
[content]
[tab]
但我们需要的是:
[tab][tab]
[content]
为了实现我们的目标,我们应该使用一个order
CSS 属性,无论元素在 DOM 树中的实际位置如何,它都会对 flex 布局中的元素进行排序(这里没有双关语的意思)。以下代码设置了元素的顺序,使其.tab-button
位于布局的开头和.tab-content
末尾:
.tab-button {
order: var(--tab-button-order);
}
.tab-content {
order: var(--tab-content-order);
display: none;
}
.tab-content
默认情况下是隐藏的。我们使用以下代码取消隐藏活动选项卡的内容:
.tab-actor:checked + .tab-button + .tab-content {
display: block;
}
当然,这是一个很大的选择器,但它却能做到所有神奇的事情。所有内容都被隐藏,我们只想显示与激活的选项卡按钮对应的内容。这个选择器的字面含义如下:
显示选中输入后的按钮后的内容
+
组合器选择紧邻的元素,这就是为什么 HTML 代码应该遵循这个精确的顺序。
另一种方法是使用~
组合器。它也是相邻的,但不严格,会选择所有匹配的相邻元素。使用~
组合器可以将选择器简化为:
.tab-actor:checked ~ .tab-content {
display: block;
}
不过在本例中,第一个选项卡会激活所有相邻的内容。为了避免这种情况,我们需要指定哪个选项卡显示哪些内容:
/* Don't write code like this. Please. */
.tab-actor.tab-1:checked ~ .tab-content.tab-1,
.tab-actor.tab-2:checked ~ .tab-content.tab-2,
.tab-actor.tab-3:checked ~ .tab-content.tab-3,
.tab-actor.tab-4:checked ~ .tab-content.tab-4 {
display: block;
}
说实话,优化并不多。
好的,现在我们有了用纯 CSS 和 HTML 制作的虽然不漂亮但可以工作的标签。
音乐时间!
或者更准确地说,是时候将标签页转换为手风琴了。
为什么?
在小屏幕上,标签并不是显示内容的最佳选择,而我们一开始试图避免的布局在这里却派上了用场:
Desktop:
[tab][tab]
[content]
Mobile:
[tab]
[tab]
[content]
我们所需要的只是恢复弹性顺序并调整按钮宽度以适应小屏幕:
@media screen and (max-width: 480px) {
.tab-button,
.tab-content {
order: initial;
}
.tab-button {
width: 100%;
}
}
就是这样。成功了。
等等!还有更多!
一切都很酷很棒,就是这些标签太无聊了。让我们把它们打扮得漂漂亮亮吧!
* {
margin: 0;
padding: 0;
}
body {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
max-width: 1280px;
margin-inline: auto;
}
.tab-container {
box-shadow: rgba(0, 0, 0, 0.5) 0 1px 2px;
justify-content: center;
}
.tab-button {
padding: 8px 16px;
border-bottom: transparent 4px solid;
transition: border-bottom-color 0.4s;
}
.content {
padding: 16px;
}
.tab-actor:checked + .tab-button {
border-bottom-color: rgb(82, 2, 136);
}
我们添加了一些内边距、颜色和一些动画。现在看起来很棒!不过,正如你所注意到的,“移动”模式下的内容切换很慢,没有一点乐趣。接下来我们来添加一些亮点:
@media screen and (max-width: 480px) {
.tab-button {
border-bottom: 1px solid #ccc;
transition: none;
}
.tab-content {
background-color: ivory;
}
.tab-container.full-height {
height: 100vh;
flex-direction: column;
}
.tab-container.full-height .tab-content {
display: block;
height: auto;
flex: 0;
overflow: hidden;
transition: 300ms flex;
}
.tab-container.full-height .tab-actor:checked + .tab-button + .tab-content {
flex: 1;
}
}
这里发生了什么?我们添加了一个.full-height
类.tab-container
,并在其上添加了一些有趣的 CSS。
.tab-container.full-height {
height: 100vh;
flex-direction: column;
}
就在这里,我们告诉我们的手风琴占据整个屏幕的高度,并按列弹性布局排列所有子项。
.tab-container.full-height .tab-content {
display: block;
height: auto;
flex: 0;
overflow: hidden;
transition: 300ms flex;
}
.tab-container.full-height .tab-actor:checked + .tab-button + .tab-content {
flex: 1;
}
现在我们对其施展魔法.tab-content
,让它以漂亮的动画展开和收拢。
结语
我的朋友们,这就是我遇到的......啊,对不起,这就是我们如何制作响应式标签,无需一行 JS 即可动态切换到手风琴布局。
文章来源:https://dev.to/babichweb/accordion-tabs-with-pure-css-35ji