使用 CSS 计数器和 CSS 网格进行计数

Avatar of Preethi
Preethi

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

我敢肯定您听说过 CSS 网格。考虑到整个前端开发人员社区在过去一年中一直在热议它,很难错过它。

无论您是 Grid 的新手还是已经使用了一段时间,我们应该从 W3C 的文字 中的简短定义开始这篇文章。

网格布局是 CSS 的一种新的布局模型,它具有强大的功能来控制盒子及其内容的大小和位置。与单轴方向的弹性盒子布局不同,网格布局针对二维布局进行了优化:那些在两个维度上都需要对齐内容的布局。

用我自己的话说,CSS 网格是无形的水平线和垂直线的网格。 我们在这些线之间的空间中排列元素以创建所需的布局。一种更轻松、更稳定且更标准化的方式来在网页中结构化内容。

除了方格纸基础之外,CSS 网格还提供了源顺序无关的布局模型的优势:无论网格项目在源代码中放置在何处,它都可以定位到屏幕上的网格中的任何地方,跨越两个轴。这非常重要,不仅是因为当您发现更新 HTML 并在页面上重新排列元素时会很麻烦,而且在您发现某些源代码位置会限制布局时也很重要。

虽然我们总是可以使用其他技术(如translatepositionmargin)将元素移动到屏幕上所需的坐标,但与 CSS 网格等真正的布局机制相比,它们在编码和更新响应式设计等情况时都更难。

在这篇文章中,我们将演示如何使用 CSS 网格的源顺序独立性来解决由于源顺序约束而导致的布局问题。具体来说,我们将看看复选框和 CSS 计数器

使用复选框进行计数

如果您从未使用过 CSS 计数器,请不要担心,这个概念非常简单!我们将计数器设置为在同一 DOM 层级上计算一组元素。该计数器在这些单个元素的 CSS 规则中递增,本质上是对它们进行计数。

以下是如何计算选中和未选中复选框的代码

<input type="checkbox">Checkbox #1<br>
<input type="checkbox">Checkbox #2
<!-- more checkboxes, if we want them -->

<div class="total">
  <span class="totalChecked"> Total Checked: </span><br>
  <span class="totalUnChecked"> Total Unchecked: </span>
</div>
::root {
  counter-reset: checked-sum, unchecked-sum;
}

input[type="checkbox"] {
  counter-increment: unchecked-sum;
}

input[type="checkbox"]:checked {
  counter-increment: checked-sum;
}

.totalUnChecked::after {
  content: counter(unchecked-sum);
}

.totalChecked::after {
  content: counter(checked-sum);
}

在上面的代码中,使用 counter-reset 属性在根元素处设置了两个计数器,并使用 counter-increment 在其各自的规则中递增,一个用于选中复选框,另一个用于未选中复选框。然后,使用counter() 将计数器的值显示为两个空<span> 的伪元素的内容。

以下是使用此代码获得的结果的简化版本

查看 CodePen 上 CSS-Tricks 的 CSS 计数器网格 笔记。(@css-tricks

这很酷。我们可以将其用于待办事项列表、电子邮件收件箱界面、调查表或任何用户切换框并希望看到已选中和未选中多少项的地方。所有这一切都只需使用 CSS!很有用,不是吗?

但是,当我们意识到显示总计数的元素只能源代码中要计数的所有元素之后出现时,counter() 的有效性就会减弱。这是因为浏览器首先需要有机会计算所有元素,然后才能显示总数。因此,我们不能简单地更改标记以将计数器放置在复选框上方,如下所示

<!-- This will not work! -->
<div class="total">
  <span class="totalChecked"> Total Checked: </span><br>
  <span class="totalUnChecked"> Total Unchecked: </span>
</div>
<input type="checkbox">Checkbox #1<br>
<input type="checkbox">Checkbox #2

那么,我们如何在布局中将计数器放置在复选框上方?这就是 CSS 网格及其布局渲染能力发挥作用的地方。

添加网格

我们基本上将之前的 HTML 包装在一个新的<div> 元素中,该元素将充当网格容器。

<div class="grid">

  <input type=checkbox id="c-1">
  <label for="c-1">checkbox #1</label> 
  <input type=checkbox id="c-2">
  <label for="c-2">checkbox #2</label> 
  <input type=checkbox id="c-3">
  <label for="c-3">checkbox #3</label> 
  <input type=checkbox id="c-4">
  <label for="c-4">checkbox #4</label> 
  <input type=checkbox id="c-5">
  <label for="c-5">checkbox #5</label> 
  <input type=checkbox id="c-6">
  <label for="c-6">checkbox #6</label>

  <div class=total>
    <span class="totalChecked"> Total Checked: </span>
    <span class="totalUnChecked"> Total Unchecked: </span>
  </div>

</div>

以下是网格的 CSS 代码。

.grid { 
  display: grid; /* creates the grid */
  grid-template-columns: repeat(2, max-content); /* creates two columns on the grid that are sized based on the content they contain */
}

.total { 
  grid-row: 1; /* places the counters on the first row */
  grid-column: 1 / 3;  /* ensures the counters span the full grid width, forcing other content below */
}

这是我们得到的结果(带有一些额外的样式)。

查看 CodePen 上 Preethi 的 CSS 计数器网格 笔记。(@rpsthecoder

看到了吗?计数器现在位于复选框上方!

我们在 CSS 中定义了网格元素上的两列,每列根据其自身内容的大小进行调整。

当我们将元素网格化时,其内容(包括文本)会形成块级,这意味着它们会获得网格级盒子(类似于块级盒子),并自动放置在可用的网格单元格中。

在上面的演示中,计数器占用了第一行中的两个网格单元格,如指定的那样,之后,每个复选框都位于第一列,每个复选框后的文本都位于最后一列。

复选框被强制到计数器下方,而无需更改实际的源顺序!

由于我们没有更改源顺序,因此计数器可以正常工作,我们可以看到选中和未选中复选框的运行总计数位于顶部,就像它们位于底部时一样。功能不受影响!

说实话,有 无数种方式来编写和实现 CSS 网格。您可以使用网格线编号、命名网格区域以及许多其他方法。您对它们的了解越多,它们就越容易使用,也越有用。我们在这里介绍的只是冰山一角,您可能会发现其他方法来创建同样有效(甚至更好)的网格。