实现纯 CSS 可折叠

可折叠小部件是创建可以收缩和扩展的内容部分的流行方式。有很多不同的实现。在这里,多亏了复选框输入元素、标签元素和:checked伪选择器,我们将能够创建这样的小部件,而无需额外的 JavaScript。

这是我们可折叠的外观:

这是它的 HTML 标记:

<div class="wrap-collabsible">
  <input id="collapsible" class="toggle" type="checkbox">
  <label for="collapsible" class="lbl-toggle">More Info</label>
  <div class="collapsible-content">
    <div class="content-inner">
      <p>
        QUnit is by calling one of the object that are embedded in JavaScript, and faster JavaScript program could also used with
        its elegant, well documented, and functional programming using JS, HTML pages Modernizr is a popular browsers without
        plug-ins. Test-Driven Development.
      </p>
    </div>
  </div>
</div>

如果您希望默认情况下打开可折叠,只需在复选框上设置checked属性:

<input id="collapsible2" class="toggle" type="checkbox" checked>

请注意,每个标签都应该与正确的复选框相关联,因此每个复选框元素都需要一个唯一的id,并且每个标签的for属性应该指向相应复选框的 id。

设计我们的可折叠

让我们一点一点地分解风格……

首先,我们将复选框元素设置为display: none该复选框将不可见,而将使用其标签来选中或取消选中它。稍后,您将看到我们将使用 CSS :checked伪选择器在选中隐藏复选框时设置不同的样式:

input[type='checkbox'] {
  display: none;
}

接下来,我们设置默认标签的样式。这里没有什么特别的事情,除了我们让标签显示为块元素的事实display: block

.lbl-toggle {
  display: block;

  font-weight: bold;
  font-family: monospace;
  font-size: 1.2rem;
  text-transform: uppercase;
  text-align: center;

  padding: 1rem;

  color: #A77B0E;
  background: #FAE042;

  cursor: pointer;

  border-radius: 7px;
  transition: all 0.25s ease-out;
}

.lbl-toggle:hover {
  color: #7C5A0B;
}

对于小箭头,巧妙使用边框可以轻松创建三角形:

.lbl-toggle::before {
  content: ' ';
  display: inline-block;

  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 5px solid currentColor;

  vertical-align: middle;
  margin-right: .7rem;
  transform: translateY(-2px);

  transition: transform .2s ease-out;
}

请参阅来自 CSS-Tricks 的这篇文章,了解您对 CSS 三角形的所有需求。

您可能还注意到,我们使用了currentColor内置变量,以便我们的三角形与标签文本的颜色相同。


我们也给内部内容一些基本的样式:

.collapsible-content .content-inner {
  background: rgba(250, 224, 66, .2);
  border-bottom: 1px solid rgba(250, 224, 66, .45);

  border-bottom-left-radius: 7px;
  border-bottom-right-radius: 7px;
  padding: .5rem 1rem;
}

现在我们可以从有趣的部分开始。默认情况下,可折叠内容div 的max-height值为0px,使其完全隐藏:

.collapsible-content {
  max-height: 0px;
  overflow: hidden;

  transition: max-height .25s ease-in-out;
}

当通过单击其标签在幕后选中可折叠的复选框时,我们会将内容 div 设置为足够高的max-height值,以便它可以增长以显示其所有内部内容。

您也可以使用具有 100vh 之类视口单位而不是尝试手动找出合适的高度。使用像 100% 这样的东西也可以,但你会失去使用过渡的能力。请注意,如果您认为可折叠中的内容可能比视口高,您仍然可能希望使用 100% 之类的内容。

当复选框被选中时,我们使用相邻的兄弟选择器 ( + ) 来选择我们的内容 div:

.toggle:checked + .lbl-toggle + .collapsible-content {
  max-height: 100vh;
}

我们使用max-height而不是height是因为我们想避免使用硬编码的高度,并且希望能够将任意高度的内容放入我们的可折叠对象中。

现在我们做一些非常相似的事情,使用相邻的兄弟选择器在可折叠对象展开时旋转我们的小三角形,并调整标签的右下角和左边框半径:

.toggle:checked + .lbl-toggle::before {
  transform: rotate(90deg) translateX(-3px);
}

.toggle:checked + .lbl-toggle {
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}

你有它!一种无需使用任何脚本即可创建可折叠部分的非常简单的方法。

关于可访问性的说明

就像现在一样,我们的可折叠小部件无法真正访问。我们将不得不添加一些 JavaScript 以使其易于访问。我知道,我知道,整个事情应该使用零 JavaScript 来实现。我能说什么!

可访问性技术在不断改进,如果有更好的方法来实现它,请在下面发表评论。

在以下脚本中,我们选择所有切换标签并侦听 keydown 事件。如果按下的键是回车空格键,我们会触发对标签的点击。

let myLabels = document.querySelectorAll('.lbl-toggle');

Array.from(myLabels).forEach(label => {
  label.addEventListener('keydown', e => {
    // 32 === spacebar
    // 13 === enter
    if (e.which === 32 || e.which === 13) {
      e.preventDefault();
      label.click();
    };
  });
});

为了使标签可聚焦,我们添加tabindex="0"

<label for="collapsible3" class="lbl-toggle" tabindex="0">With A11y</label>

所有款式

以下是全套款式,供您参考:

.wrap-collabsible {
  margin-bottom: 1.2rem 0;
}

input[type='checkbox'] {
  display: none;
}

.lbl-toggle {
  display: block;

  font-weight: bold;
  font-family: monospace;
  font-size: 1.2rem;
  text-transform: uppercase;
  text-align: center;

  padding: 1rem;

  color: #A77B0E;
  background: #FAE042;

  cursor: pointer;

  border-radius: 7px;
  transition: all 0.25s ease-out;
}

.lbl-toggle:hover {
  color: #7C5A0B;
}

.lbl-toggle::before {
  content: ' ';
  display: inline-block;

  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 5px solid currentColor;
  vertical-align: middle;
  margin-right: .7rem;
  transform: translateY(-2px);

  transition: transform .2s ease-out;
}

.toggle:checked + .lbl-toggle::before {
  transform: rotate(90deg) translateX(-3px);
}

.collapsible-content {
  max-height: 0px;
  overflow: hidden;
  transition: max-height .25s ease-in-out;
}

.toggle:checked + .lbl-toggle + .collapsible-content {
  max-height: 100vh;
}

.toggle:checked + .lbl-toggle {
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}

.collapsible-content .content-inner {
  background: rgba(250, 224, 66, .2);
  border-bottom: 1px solid rgba(250, 224, 66, .45);
  border-bottom-left-radius: 7px;
  border-bottom-right-radius: 7px;
  padding: .5rem 1rem;
}

🌈 享受你的花哨的几乎只有 CSS 的可折叠!

觉得文章有用?

点个广告表达一下你的爱意吧 !😁