本杰明·阿斯特 (Benjamin Aster) 的令人难以置信的项目:
此页面不包含 JavaScript。所有逻辑均由纯 HTML 和 CSS 编写。为了获得最佳性能,请关闭其他标签页和正在运行的程序。
该页面实现了完整的 Minecraft 风格的世界编辑器:您可以在 9x9x9 的世界中放置和移除 7 种不同类型的方块,并以 3D 方式旋转该世界以从不同角度查看它。
它仅用480 行 CSS … 和 46,022 行(3.07MB)HTML 实现!
实现这一功能的关键技巧是将标签与has()
选择器结合使用。该页面包含 35,001 个<label>
元素和 5,840 个<input type="radio">
元素——这些单选按钮元素是状态存储引擎。点击立方体六个可见面中的任意一个,相当于点击了一个标签,而该标签的for=""
则代表该维度上相邻立方体的单选按钮。
当你切换材料时,你实际上是在切换可用的可见标签:
.控件:有( > . block-chooser > . stone >输入[ type = radio ] :已选中 ) ~ main . cubes-container > . cube : not (. stone ) { 显示:无; }
Claude Opus 4解释:“选中“石头”单选按钮后,除具有.stone
类的元素之外的所有立方体元素都将被隐藏( display: none
)”。
这段 HTML 代码有助于展示操作的结构:
< div class =“ cubes-container ” style =“ --layer:0; --row:0; --column:3 ” > < div class ="立方体空气" > <输入 类型=“收音机” 名称=“立方体层-0-行-0-列-3 ” id ="立方体层0行0列3空气" 检查 /> <标签为=" cube-layer-0-row-0-column-3-air " 类=“正面” > </标签> <标签为=" cube-layer-0-row-0-column-3-air " 类=“返回” > </标签> <标签为=" cube-layer-0-row-0-column-3-air " 类=“左” > </标签> <标签为=" cube-layer-0-row-0-column-3-air " 类=“右” > </标签> <标签为=" cube-layer-0-row-0-column-3-air " 类=“顶部” > </标签> <标签为=" cube-layer-0-row-0-column-3-air " 类=“底部” > </标签> </ div > < div class ="立方体石头" > <输入 类型=“收音机” 名称=“立方体层-0-行-0-列-3 ” id ="立方体-层-0-行-0-列-3-石头" /> <标签为=" cube-layer-0-row-1-column-3-stone " 类=“正面” > </标签> <标签为=" cube-layer-0-row--1-column-3-stone " 类=“返回” > </标签> <标签为=" cube-layer-0-row-0-column-4-stone " 类=“左” > </标签> <标签为=" cube-layer-0-row-0-column-2-stone " 类=“右” > </标签> <标签为=" cube-layer--1-row-0-column-3-stone " 类=“顶部” > </标签> <标签为=" cube-layer-1-row-0-column-3-stone " 类=“底部” > </标签> </ div > < div class ="立方体草" > <输入 类型=“收音机” 名称=“立方体层-0-行-0-列-3 ” id ="立方体层0行0列3草" /> <标签为=" cube-layer-0-row-1-column-3-grass " 类=“正面” > </标签> <标签为=" cube-layer-0-row--1-column-3-grass " 类=“返回” > </标签> <标签为=" cube-layer-0-row-0-column-4-grass " 类=“左” > </标签> <标签为=" cube-layer-0-row-0-column-2-grass " 类=“右” > </标签> <标签为="立方体层--1-行-0-列-3-草" 类=“顶部” > </标签> <标签为=" cube-layer-1-row-0-column-3-grass " 类=“底部” > </标签> </ div >
因此,对于 9x9x9 = 729 个立方体,每个立方体都有一组八个同名的单选框,在本例中为cube-layer-0-row-0-column-3
,这意味着它可以有八个值(“air” 表示净空,其他值表示材质类型)。立方体的每个面都有六个标签,每个标签对应一个立方体。 for=""
标签指向当前所选可见材质类型对应的下一个方块。
另一个巧妙的技巧是它通过控制旋转和移动视口来实现 3D 视图。这里的技巧依赖于 CSS 动画:
.controls : has ( .up : active ) ~ main.down { 动画播放状态:正在运行; } .controls : has ( .down : active ) ~ main.up { 动画播放状态:正在运行; } .controls : has ( .chronological : active ) ~ main.chronological { 动画播放状态:正在运行; } .控件:有(.逆时针:活动) 〜主.逆时针{ 动画播放状态:正在运行; }
然后为每个不同的控件定义动画:
.内容.顺时针{ 动画: var ( --animation-duration )线性1毫秒暂停顺时针旋转; } @keyframes顺时针旋转 { 从{ 旋转: y 0转; } 到{ 旋转: y计算( -1 * var (-- max-rotation )); } } .内容.逆时针{ 动画: var ( --animation-duration )线性1毫秒暂停逆时针旋转; } @keyframes逆时针旋转 { 从{ 旋转: y 0转; } 到{ 旋转: y calc ( var ( --max-rotation )); } }
任何时候,只要按住鼠标在某个控件上,动画状态就会从paused
切换到running
,直到再次松开该按钮。动画运行时,它会更改应用于所选元素的各种 3D 变换属性。
它极其聪明,一旦你弄清楚了它使用的核心技巧,它实际上相当优雅和易读。
来源: Hacker News
原文: https://simonwillison.net/2025/May/26/css-minecraft/#atom-everything