打开网易新闻 查看精彩图片

编译 | 苏宓

出品 | CSDN(ID:CSDNnews)

多年来,“HTML、CSS 到底算不算是编程语言”一直是前端圈一个颇具争议的话题。

一边是工程师坚持认为,它们只是标记与样式描述工具,不具备传统意义上的逻辑能力;另一边则认为,在现代浏览器体系下,CSS 已经具备足够复杂的表达能力,甚至可以完成一些超出“样式表”范畴的工作。

争论还没完全有结论,一个更“实战化”的例子就出现了。

来自荷兰的开发者 Niels Leenheer 近日做了一件看起来有点离谱的事:他没有使用 WebGL,也没有依赖任何游戏引擎,仅仅依靠最基础的 HTML 和 CSS,就复刻出了一个“能玩的《DOOM》”。

在这个被称为 cssDOOM 的项目里,墙壁、地板、木桶、甚至恶魔怪物,都不是传统意义上的图形资源,而是通过一个个在三维空间中不断变形的

标签构建出来的。JavaScript 只负责游戏逻辑与主循环,而所有画面的渲染工作,则完全交给 CSS 来完成。

项目地址:https://github.com/NielsLeenheer/cssDOOM

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

Niels Leenheer 是谁?

Niels Leenheer 是一位资深开发者,他最为人熟知的创建了是 HTML5 标准测试网站 HTML5test.com,以及浏览器用户代理解析工具 WhichBrowser。同时,他也是 Fronteers 大会委员会的成员。

此前,他曾完成一项趣味实验,成功在示波器上运行《Doom》,并借此编写代码,从原版游戏 WAD 资源文件中提取地图数据。

本次 CSS 版《Doom》,正是在该实验的基础上迭代开发而来。

打开网易新闻 查看精彩图片

纯靠 HTML、CSS,Doom 是怎么实现的?

Niels Leenheer 首先将提取的游戏地图数据,编译为由数千个`

`元素构成的静态场景。

">

每一个元素都标注了《Doom》原始坐标参数。

打开网易新闻 查看精彩图片

随后,浏览器的布局与合成系统会接管渲染工作,通过 CSS 的 transform 以及诸如 hypot()、atan2() 等数学函数,把这些元素渲染成定位在三维空间中的对象。

}

与其让 JavaScript 负责完整的三维几何计算,这个实现选择了一种更“偷懒”的方式:脚本只传递原始的坐标点,以及地板和天花板的高度等参数作为自定义属性,其余诸如墙体宽度、旋转角度等三角计算,全部交给 CSS 引擎来完成。

这种分工是有意为之的:游戏核心循环逻辑改编自《毁灭战士》开源 C 语言代码,由 JavaScript 负责运行,同时仅向 CSS 开放坐标数据、状态参数与少量自定义属性,构成轻量化渲染层。

Niels Leenheer 也曾尝试把游戏状态和逻辑完全交给 CSS 来处理,但很快发现并不现实,于是放弃了这一思路,不过渲染路径依然几乎完全留在样式层完成。

整个项目中一个关键难点,在于如何把《DOOM》的坐标体系和渲染技巧,适配到浏览器的 3D 处理方式上。比如地面,就是通过将

元素绕 X 轴旋转 90 度来实现的,然后再借助 clip-path 的 polygon(),或更新的 shape() 语法,将其裁剪成任意形状的扇区多边形,从而支持复杂轮廓甚至奇偶填充规则。

打开网易新闻 查看精彩图片

在不同区域之间实现无缝纹理铺设的关键,是将背景位置锚定在“世界坐标系”中。例如,如果一个元素在水平和垂直方向分别偏移了 200px 和 400px,那么它的 background-position 就会被设置为 -200px -400px,这样纹理图案就能像被连续铺在一整块平面上一样对齐。

场景的移动方式也比较特殊:它并不是通过“摄像机”来移动视角(因为 CSS 本身并没有真正的摄像机概念),而是通过移动整个“世界”来实现效果。JavaScript 会记录玩家的位置和角度,并将其存储在四个自定义属性中,而 CSS 会对这些数值进行反向计算,使场景朝相反方向移动,同时通过额外的 translate 来补偿透视效果,其余部分则交给浏览器的渲染系统完成。

敌人和投射物的精灵渲染则依赖“广告牌(billboard)”技术:CSS 会让每个 sprite 始终面向观察者,在需要时通过 scaleX 进行镜像翻转,并使用 step() 动画来推进精灵帧序列,而 JavaScript 只负责更新对应的状态属性。

打开网易新闻 查看精彩图片

场景光照、自动门、升降平台、弹道特效,统统被转化为可动态变更的样式状态问题。区域亮度以级联自定义属性存储,搭配亮度滤镜统一调暗昏暗区域,无需逐个修改场景元素;游戏大门通过自定义属性绑定 CSS 过渡动画,实现抬升开合,脚本仅需切换状态标签,动画播放完全交由浏览器原生驱动。

弹药弹道通过起点、终点坐标与飞行时长定义,CSS 依靠位移动画完成弹道位移,搭配独立旋转属性,让投射物始终朝向玩家。

现代布局特性还被巧妙用来实现游戏自适应适配。原版固定宽度的状态栏,被重构为文档对象模型独立组件,弹药数值、生命值、角色头像、护甲值、钥匙道具拆分展示,通过弹性布局自动排版,在窄屏设备上自动换行适配。

观战模式则新增一套 CSS 镜头逻辑。

跟随视角利用角度正弦、余弦函数结合计算属性,测算偏移数值,将镜头固定在玩家斜后方与斜上方;视角切换依靠独立的位移、旋转属性,让第一人称与第三人称跟随视角之间实现丝滑过渡。

性能与画面精度问题,也暴露了这套纯 CSS 方案的固有短板。包含数千个三维变形元素的大型地图,极易导致移动端苹果浏览器出现画面卡顿,甚至程序崩溃。

为此,Niels Leenheer 加入视域剔除机制,自动隐藏玩家视野外的几何模型。

基础版剔除逻辑由 JavaScript 编写,遍历场景元素,根据距离与角度切换隐藏属性。

Niels Leenheer 还测试了纯 CSS 剔除方案:通过样式参数定义可见性判定,结合延时动画与关键帧规则,利用样式特性实现元素的自动显示与隐藏。

打开网易新闻 查看精彩图片

局限性

《Doom》原生渲染的部分核心逻辑,很难直接复刻至 CSS 环境。

原版游戏会将天空纹理以纯二维形式,绘制在地图实体前方的虚拟墙体上;而CSS渲染必须构建完整三维空间,天空图层需要置于所有景物后方。

这一差异会导致原版被天空遮挡的模型暴露出来,Niels Leenheer 只能额外增加剔除规则,隐藏玩家视角中被天空墙体遮挡的物体。

Niels Leenheer 明确表示,该项目绝非 WebGL、WebGPU 专业图形渲染方案的替代品,性能瓶颈也客观存在,但这并非本次开发的核心目的。

他在分享中提到,这项开发旨在突破 CSS 的能力边界。三角函数运算、自定义属性动画、裁剪路径、SVG滤镜、锚点定位等成熟商用级 CSS 特性,都被赋予了标准制定者从未设想过的全新用途。

最终成品完整可玩,直观证明:只要合理运用大量`

`元素与现代 CSS 语法,无需调用任何图形编程接口,就能在浏览器中完整复刻《毁灭战士》的游戏世界。

长久以来,爱好者不断挖掘各类低门槛、非常规设备运行《毁灭战士》的可能性,CSS 只是最新的趣味载体。

也正如 Niels Leenheer 所言,如果说还有什么意义的话,那它至少回答了一个没人真正问过的问题:CSS 能不能跑《DOOM》?

答案是:可以。确实可以。

来源:https://nielsleenheer.com/articles/2026/css-is-doomed-rendering-doom-in-3d-with-css/

https://www.techspot.com/news/111922-developer-rebuilds-doom-using-only-css-html-turning.html


【活动分享】"48 小时,与 50+ 位大厂技术决策者,共探 AI 落地真路径。"由 CSDN&奇点智能研究院联合举办的「全球机器学习技术大会」正式升级为「奇点智能技术大会」。2026 奇点智能技术大会将于 4 月 17-18 日在上海环球港凯悦酒店正式召开,大会聚焦大模型技术演进、智能体系统工程、OpenClaw 生态实践及 AI 行业落地等十二大专题板块,特邀来自BAT、京东、微软、小红书、美团等头部企业的 50+ 位技术决策者分享实战案例。旨在帮助技术管理者与一线 AI 落地人员规避选型风险、降低试错成本、获取可复用的工程方法论,真正实现 AI 技术的规模化落地与商业价值转化。这不仅是一场技术的盛宴,更是决策者把握 2026 AI 拐点的战略机会。