在开始这个系列之前,我已经计划好了前两种语言。对于第三个问题,我决定询问 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 中以处理诸如列表编号之类的事情。当你说
- One
- Two
,HTML实际上需要显示1. One 2. Two。那些“1”在哪里。和“2”。来自?仅来自这样的伪元素(在这种情况下::marker,但足够接近)。
大多数“使用 CSS 编程”将严重依赖伪元素。哦,它们的命名也很容易混淆 -body::after意思是“身体内部;毕竟内容”而不是“身体之后”。
FizzBuzz
现在让我们编写真正的程序,FizzBuzz!为此,我们将在 HTML 中放置 100 个空 span,并使用纯 CSS 执行 FizzBuzz:
<!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>
这是什么?一个格式很好的 FizzBuzz:
它是如何工作的?我们在这里使用了一些新技术。
每个跨度都有两个伪元素,::before和::after。
伪元素获取计数器值或“Fizz”或“Buzz”或“ ::beforeFizzBuzz”。为了支持表格上的浅色和深色条纹等重要功能,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 游戏,比如这个或这个。
学习这会让你成为更好的前端开发人员吗?并不会,但这绝对很有趣