随笔,【100 种语言速成】第 3 节:CSS

在开始这个系列之前,我已经计划好了前两种语言。对于第三个问题,我决定询问 GitHub Copilot。它的建议是:

写更多关于 Python 的剧集
按字母顺序从 C 到 Rust,然后在本系列的其余部分继续介绍 Rust
实际上写了很多语言但有很多重复
HTML
好的,所以也许人工智能不会很快取代我们。但是最后一个建议并不太疯狂——HTML 可能不是一种编程语言,但 CSS 基本上变成了一种语言!

这一集不是关于居中元素或任何类似的事情,我们将用 CSS 编写真正的程序!

Hello World!

首先,Hello World!

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <style>
    :root {
      --who: "World";
    }
    body {
      margin: 0;
      min-height: 100vh;
      font-size: 48px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    body::after {
      content: "Hello, " var(--who);
    }
  </style>
</head>
<body>
</body>
</html>

看起来和你预期的一样,HTML 正文中没有任何内容:

忽略body上的规则,它们只是居中。有趣的技术在别处。

我们可以使用 –variablename: value; 在 CSS 中设置变量。 然后它被每个子元素继承。 我们可以将此类变量与 var(–variablename) 一起使用。

::after我们可以创建像和一样的“伪元素” ::before,并设置它们的内容。这些被添加到 CSS 中以处理诸如列表编号之类的事情。当你说

  1. One
  2. Two

,HTML实际上需要显示1. One 2. Two。那些“1”在哪里。和“2”。来自?仅来自这样的伪元素(在这种情况下::marker,但足够接近)。

大多数“使用 CSS 编程”将严重依赖伪元素。哦,它们的命名也很容易混淆 -body::after意思是“身体内部;毕竟内容”而不是“身体之后”。

FizzBuzz

现在让我们编写真正的程序,FizzBu​​zz!为此,我们将在 HTML 中放置 100 个空 span,并使用纯 CSS 执行 FizzBu​​zz:

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <style>
    body {
      margin: 0;
      min-height: 100vh;
      counter-reset: fizzbuzz-counter;
    }
    span {
      counter-increment: fizzbuzz-counter;
    }
    span::after {
      content: ", ";
    }
    span:last-child::after {
      content: ".";
    }
    span::before {
      content: counter(fizzbuzz-counter);
    }
    span:nth-child(3n)::before {
      content: "Fizz";
    }
    span:nth-child(5n)::before {
      content: "Buzz";
    }
    span:nth-child(15n)::before {
      content: "FizzBuzz";
    }
  </style>
</head>
<body>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
  <span></span><span></span><span></span><span></span><span></span>
</body>
</html>

这是什么?一个格式很好的 FizzBu​​zz:

它是如何工作的?我们在这里使用了一些新技术。

每个跨度都有两个伪元素,::before和::after。

伪元素获取计数器值或“Fizz”或“Buzz”或“ ::beforeFizzBu​​zz”。为了支持表格上的浅色和深色条纹等重要功能,CSS 允许我们将规则应用于每 N 个元素的元素。稍后编写的具有相同特性的规则优先。所以span:nth-child(5n)::before只适用于每 5 个元素,除了那些span:nth-child(15n)::before优先的元素。

我们不为此使用 CSS 变量,我们使用 CSS 计数器。计数器用 来创建counter-reset: countername;,用 递增counter-increment: countername;,然后用 来访问counter(countername)。

伪元素要么是所有其他元素的::after逗号,要么是我们选择的最终元素的句点:last-child。这个功能实际上偶尔会在现实生活中使用,将列表表示为句子。

计数器也比你想象的更有用——列表不需要它们,但对于像节和小节编号的标题编号,CSS 可以很容易地用 counters 做到这一点。

斐波那契数列

现在我们遇到了一个非常意想不到的问题:

  • CSS 有字符串和数字,没有办法将一个转换为另一个!
  • 所有计算只能对数字进行
  • 所有content显示必须是字符串
  • counter(…)返回一个字符串
  • counter只能设置为一个常数整数,或按一个常数整数递增,而不是计算出来的
    完全莫名其妙。我一生中从未见过无法打印数字的语言,但这就是我们到达这里的方式。

好吧,让我们忽略所有这些,只制作一系列斐波那契数字大小的条形图。

我们需要使用 CSS 变量而不是 CSS 数字进行计算。CSS 变量可以访问它们的父变量,而不是它们的兄弟变量,所以我们需要做一些深度嵌套。同样不幸的是,虽然我们可以对它们进行一些计算,但 CSS 属性并没有真正排序,因此我们不能在一层上进行多个相互依赖的更改。因此,我们将为每个斐波那契数使用 3 个嵌套跨度。由于 CSS 没有任何 global :nth-element-globally(3n),我们将给它们特定的类。

有可能这些限制可以避免,我们很可能会获得 CSS 功能,让我们以更好的方式对其进行编码(很可能是数字到字符串的转换)。

即使有这些限制,我认为这仍然是一个很好的结果。

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <style>
    :root {
      --x: 0px;
      --y: 1px;
    }
    body {
      margin: 8px;
      font-size: 48px;
      min-height: 100vh;
    }
    span {
      display: block;
    }
    span.a {
      --z: calc(var(--x) + var(--y));
    }
    span.b {
      --x: var(--y);
    }
    span.c {
      --y: var(--z);
    }
    span.c::before {
      display: block;
      background-color: #480;
      height: 5px;
      width: var(--x);
      margin: 2px;
      content: "";
    }
  </style>
</head>
<body>
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
  <span class="a"><span class="b"><span class="c">
</body>
</html>

看起来像这样:

肯定还有更多

虽然这是对 CSS 编程的快速介绍,但这绝不是它的限制。

人们一直在编写整个纯 CSS 游戏,比如这个或这个。

学习这会让你成为更好的前端开发人员吗?并不会,但这绝对很有趣

正文完