仅使用 CSS 重建 Windows 98
为了不断探索仅用 CSS 能实现多少功能(参见其他作品,例如纯 CSS 的 Minecraft Chicken),我决定尝试只用 CSS 和 HTML 来重现 Windows 98。有人问过我这个问题吗?并没有。尝试看看仅用 CSS 能实现什么功能很有趣吗?是的,有点意思。这会很耗时吗?很遗憾,确实很耗时。
这是演示版本——顺便提一下——这是Windows桌面版的重制版,因此当然是针对桌面浏览进行了优化。不过讽刺的是,它可能无法在Windows 98上运行,因为你必须使用非常老版本的Internet Explorer才能查看它。
演示链接在这里,因为全屏模式观看效果更佳。我认为这个演示很酷的地方包括:
- 仅使用 CSS 的扫雷游戏- 尽管没有记分功能。
- 使用全新的 CSS 父选择器登录和注销,并记住谁登录。
- 动画更新过程。
- 最小化、最大化和关闭窗口。
然而值得注意的是,有些事情很难或者根本无法用 CSS 来完成,例如:
- 拖放 - 使用 CSS 根本无法实现。
- 多种条件 - 例如,很难说一个窗口应该同时最大化和置于顶部。
- 点击任意位置即可关闭 - 您必须点击“开始”按钮才能关闭并打开它。您无法点击其他任何地方来关闭它。
- 一般而言,多个条件 - CSS 实际上没有 AND 运算符。
如何在 CSS 中构建 Windows 98
所以,我首先想做的就是让这个版本的 Windows 98 看起来更完美。我使用了一些非常酷的 Windows 98 图标(我确实认为它们应该回归),以及标准的 Windows 98 配色方案。为了获得这种内凹的感觉,我使用了相当复杂的盒子阴影,如下图所示:
.windows-box-shadow, .minesweeper .content > label {
box-shadow: -2px -2px #e0dede, -2px 0 #e0dede, 0 -2px #e0dede, -4px -4px white, -4px 0 white, 0 -4px white, 2px 2px #818181, 0 2px #818181, 2px 0 #818181, 2px -2px #e0dede, -2px 2px #818181, -4px 2px white, -4px 4px black, 4px 4px black, 4px 0 black, 0 4px black, 2px -4px white, 4px -4px black;
}
.inverse-windows-box-shadow, .minesweeper .content > label:active {
box-shadow: -2px -2px #818181, -2px 0 #818181, 0 -2px #818181, -4px -4px black, -4px 0 black, 0 -4px black, 2px 2px #e0dede, 0 2px #e0dede, 2px 0 #e0dede, 2px -2px #818181, -2px 2px #e0dede, -4px 2px black, -4px 4px white, 4px 4px white, 4px 0 white, 0 4px white, 2px -4px black, 4px -4px white;
}
其他一切都看起来和感觉上都相对简单。实现这一切的关键在于复选框和单选按钮。
使用复选框和单选按钮作为 CSS 中的信息存储
复选框和单选按钮是 CSS 中存储信息的唯一方式。我们可以使用它们来实现样式更改。复选框选中后,可以启用或禁用单个功能(例如显示窗口、最大化窗口或点击扫雷方块)。对于一次只能激活一个选项的功能(例如,哪个窗口应该显示在最上面),我们可以使用单选按钮。两者在 CSS 中都遵循相同的语法,即使用:checked
选择器:
#windows-11:checked ~ .windows-11 .text {
/* -- CSS here -- */
}
这里,当输入框#windows-11
被检查时,它会影响其兄弟元素的子元素.text
——因此我们可以应用一些自定义 CSS。重要的是,由于我们无法轻松地为 HTML 输入框添加样式,我们使用label
s 来模拟 Windows 98 的不同特性。例如:
<form id="windows">
<!-- Login and Shutdown -->
<input type="checkbox" id="login-screen-input" name="login-screen-input" />
<!-- Later on.. -->
<label for="login-screen-input">Log Off</label>
</form>
这里,label
显示的与复选框关联#login-screen-input
。这意味着当您点击标签时,它会选中复选框。这基本上让我们可以自由地跟踪用户的点击,然后使用复选框的状态以特定的表单显示特定的窗口。难点在于,一个标签:checked
只能与一个输入关联。
这意味着,如果要用按钮打开窗口并将其置于所有其他窗口之上,就必须使用 JavaScript,因为这需要跟踪两个状态:z-index
窗口的状态以及窗口是打开还是关闭。这在实现纯 CSS 版本的复杂 UI 时是一个主要障碍。
使用父选择器来跟踪谁已登录
由于我们在用户注销时会显示登录屏幕div
,因此我们无法使用同级选择器轻松跟踪登录用户。我们仍然可以使用:checked
状态来跟踪,但是输入在 DOM 中的位置太深,无法影响其父级同级的 CSS。幸运的是,我们可以使用新的 CSS 父级选择器来完成此任务:
#login-screen:has(#login-window .select-box #zark-muckerberg:checked) ~ #start-bar .zark-muckerberg,
#login-screen:has(#login-window .select-box #donald-trump:checked) ~ #start-bar .donald-trump,
#login-screen:has(#login-window .select-box #spiderman:checked) ~ #start-bar .spiderman {
display: inline;
padding-left: 0.5rem;
}
这里,如果#login-screen
有一个:checked
div,我们可以用它来在开始栏中显示用户名,尽管这些复选框位于 DOM 深处。这非常简洁,如果你想要重新创建一个纯 CSS 版本的 Windows 操作系统,这是一种使用父选择器的有效方法。
没有 CSS AND 选择器
令我沮丧的是,我根本无法AND
使用链式复选框创建 CSS 选择器。例如,考虑以下情况,我们根据某个:checked
状态应用一些 CSS:
#minesweeper-box-1-1:checked ~ .content > .minesweeper-box-1-1 {
}
上面的代码运行正常,但是如果我们想在应用 CSS 之前检查两个相邻的扫雷框是否被选中,该怎么办呢?我逻辑上认为,只有两个都选中,选择器才会继续执行——所以我尝试了以下方法:
#minesweeper-box-1-1:checked + #minesweeper-box-2-1:checked ~ .content > .minesweeper-box-1-1 {
}
但不幸的是,这行不通。所以,虽然我们有办法在 CSS 中跟踪状态,但要跟踪多条件复选框的状态并据此创建逻辑语句和样式却相当困难。这令人失望,但对于我们的 Windows 98 实现来说,这并没有太大的限制。
实现 Windows 98 文本
Windows 98 文本不支持抗锯齿。为了移除抗锯齿功能(至少对某些浏览器而言),并实现经典、清晰的 Windows 98 风格,我使用了以下 CSS:
body {
-webkit-font-smoothing: none;
-moz-osx-font-smoothing: grayscale;
}
重新制作扫雷
所以这个项目的主要工作之一是重新创建扫雷。我把网格控制得相对较小(为了保持理智),但我必须用标签创建我自己的扫雷地图。每个标签都映射到一个输入,用于跟踪单元格是否被点击。如果点击了地雷,游戏就结束了,你将无法再与棋盘互动。由于扫雷单元格大约有 56 个,我们需要大约 56 个相应的扫雷输入。用 CSS 跟踪所有这些需要大量的CSS 代码,但整体效果看起来相当酷炫。
总的来说,这遵循与前面提到的复选框和单选按钮技巧相同的逻辑 - 因此从概念上讲,它并不比我们所做的任何其他事情更复杂。
结论
希望你喜欢这篇指南。这让我回想起了以前的 Web 开发,那时的事情要困难得多,需要大量手动创建 DOM 元素。看到这么多年过去了,CSS 已经实现了这么多的功能(包括父选择器),真是令人欣喜。这真的是一种创建 Web 应用的现实方法吗?就速度而言,它确实不现实,就功能而言,它目前还没有实现,但 CSS 的功能比我想象的要多得多,我对最终的结果非常满意。
如果您喜欢这个,请考虑在 Twitter 上关注我。
文章来源:https://dev.to/smpnjn/using-only-css-to-recreate-windows-98-47b1