
CSS允许您在Internet上创建动态布局和界面,但是作为一种标记语言,它是静态的-设置值后就无法更改它。 没有讨论机会的想法。 在运行时生成随机数是JavaScript领域,而不是CSS。
还是不行 如果我们允许少量的用户交互,则实际上可以在CSS中产生一定程度的随机性。 让我们来看看!
随机性用其他语言
正如罗宾·雷德尔(Robin Rendle)在
有关CSS技巧的文章中所解释的那样,有多种方法可以使用CSS变量获得“动态随机化”。 但是这些解决方案不是100%CSS,因为它们需要JavaScript才能使用新的随机值更新CSS变量。
我们可以使用Sass或Less等预处理器来生成随机值,但是,一旦CSS代码被编译并导出,这些值就被固定,并且随机性会丢失。
为什么我担心CSS中的随机值?
过去,我开发了简单的纯CSS应用程序,例如
Quiz ,
CS Simon的游戏和
Magic Trick ,但我想做一些更复杂的事情。
*我将只在以后讨论在CSS中创建这些代码段的有效性,实用性或实用性。
基于某些棋盘游戏可以表示为状态机(FSM)的事实,然后可以使用HTML和CSS表示它们。
因此,我开始开发游戏
“ Leela” (它也是“ Snakes and Ladders”)。
这是一个简单的游戏。 简而言之,游戏的目标是将筹码从棋盘的起点推进到终点,避免出现蛇,并试图爬上楼梯。
该项目似乎可行,但是我错过了一些东西,是的-骰子!
投掷骰子(在其他游戏中,投掷硬币)是获得随机值的公认方法。 您掷骰子或扔硬币,每次获得未知值。 一切似乎都很简单。
模拟骨头的随机投掷
我打算用标签覆盖图层,并使用CSS动画“旋转”并共享最上面的图层。 像这样:

模拟此随机化的代码不太复杂,可以使用动画和各种动画延迟来实现:
@keyframes changeOrder { from { z-index: 6; } to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: -0.0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; }
放慢了动画速度以简化交互(但仍然足够快,可以看到下面解释的障碍)。 伪随机性也更清楚。
<label for="d1">Click here to roll the dice</label> <label for="d2">Click here to roll the dice</label> <label for="d3">Click here to roll the dice</label> <label for="d4">Click here to roll the dice</label> <label for="d5">Click here to roll the dice</label> <label for="d6">Click here to roll the dice</label> <div> <input type="radio" id="d1" name="dice"> <input type="radio" id="d2" name="dice"> <input type="radio" id="d3" name="dice"> <input type="radio" id="d4" name="dice"> <input type="radio" id="d5" name="dice"> <input type="radio" id="d6" name="dice"> <p>You got a: <span id="random-value"></span></p> </div>
@keyframes changeOrder { from { z-index: 6;} to { z-index: 1; } } label { animation: changeOrder 3s infinite linear; background: #ddd; cursor: pointer; display: block; left: 1rem; padding: 1rem; position: absolute; top: 1rem; user-select: none; } label:nth-of-type(1) { animation-delay: 0s; } label:nth-of-type(2) { animation-delay: -0.5s; } label:nth-of-type(3) { animation-delay: -1.0s; } label:nth-of-type(4) { animation-delay: -1.5s; } label:nth-of-type(5) { animation-delay: -2.0s; } label:nth-of-type(6) { animation-delay: -2.5s; } div { left: 1rem; position: absolute; top: 5rem; width: 100%; } #d1:checked ~ p span::before { content: "1"; } #d2:checked ~ p span::before { content: "2"; } #d3:checked ~ p span::before { content: "3"; } #d4:checked ~ p span::before { content: "4"; } #d5:checked ~ p span::before { content: "5"; } #d6:checked ~ p span::before { content: "6"; }
但是后来我遇到了一定的限制。 我得到了随机数,但是有时,即使单击“骰子”,该字段也不会返回任何值。
我试图增加动画时间,这似乎有所帮助,但是我仍然有一些意想不到的价值。
那时,我做了大多数开发人员在发现他们无法解决的障碍时所做的事情-我突然在StackOverflow上寻求帮助。 我推荐。
对我来说幸运的是,总会有人愿意提供帮助,就我而言,正是
泰曼尼·阿夫夫(Temani Afif)的解释 。
如果尝试简化,问题是浏览器仅在元素处于活动状态(单击鼠标时)时才触发click事件,换句话说,与按下鼠标按钮时处于活动状态的元素相同。
由于动画的变化,单击鼠标时,顶层(标签)实际上并不是按下鼠标时的顶层(标签),除非我做得足够快,好或慢,以至于动画已经设法遍历了周期的所有值。 这就是动画时间增加隐藏了此问题的原因。
解决方案是应用“静态”位置来破坏堆栈上下文,并使用伪元素(例如::之前或::之后)使用更高的z-index代替它。 因此,当您将鼠标悬停在上方时,活动标签将始终位于顶部。
label:active { margin-left: 200%; position: static; } label:active::before { content: ""; position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 10; }
以下是具有更快动画时间的解决方案的代码:
进行此更改后,仍然需要创建一个小的界面来绘制可以用鼠标单击的伪立方体,并且CSS
游戏《蛇和梯子》已经完成。
这种技术有一些明显的缺点。
- 需要与用户互动-必须单击标签以引起“随机数的产生”。
- 该方法不能很好地扩展-它适用于较小的一组值,但是对于较大的范围却很痛苦。
- 这不是真正的随机数,而是伪随机数,计算机可以轻松地确定每时每刻将生成什么值。
但另一方面,它是100%CSS(不需要预处理器或其他外部帮助器),对于一个人来说,它看起来可能是100%随机的。
而且,是的,该方法不仅可以用于随机数,还可以用于所有随机数。 在这种情况下,我们使用它来“意外”地在游戏“剪刀石头布”中选择一台计算机。