把普通网页的按钮、边框和文字段落直接变成 2D 平台跳跃游戏的地形,甚至利用拖拽浏览器窗口引发的页面重排把角色弹飞——近期在开发者社区流传的交互式网页项目 Walker Playground(页面标题为 Lemmings CSS Animation),用一套精巧的 DOM 几何碰撞规则复刻了经典游戏《疯狂小旅鼠》(Lemmings)。这个项目最核心的工程价值,在于它撕掉了纯 CSS 动画的标签误区,展示了如何将浏览器排版引擎里原本被视为性能开销的页面重排(Reflow),反向改造成实时物理动量。
打开该演示页面,用户只需点击按钮或在控制台调用 __walker.add(),就能在网页里生成自主行走的像素小人。与传统内嵌在 Canvas 画布里的网页小游戏不同,这些小人直接踩在真实的 HTML 元素上。你可以用鼠标拖拽它们,或者轻拂将其抛向高处的卡片;当页面存在多列文本或自适应卡片时,快速缩放浏览器窗口触发换行,站在元素表面的小人会顺着排版突变的位移被直接弹射出去。
标题写着 CSS 动画,底子却是 JavaScript 逐帧物理仿真
很多初级开发者初看标题 Lemmings CSS Animation,容易误以为现代 CSS 已经强大到能独立处理 DOM 边界碰撞与抛物线弹射。这是一个典型的技术认知错位。

在前端领域,早就有开发者做过真正的纯 CSS 旅鼠演示。例如开发者 Joan León 曾用 box-shadow 绘制像素小人,配合 CSS keyframes 和 step-start 属性,在 8 个离散帧之间循环切换。但那种方案本质上只是预设序列的精灵图动画(Sprite Animation),小人只能在固定轨道上机械迈步,对周围的网页元素毫无感知。
CSS 的关键帧模型天生缺乏状态记忆与空间计算能力。要在网页里实现重力下落、墙壁阻挡以及窗口缩放时的动量传递,底层必须依赖 JavaScript 的 requestAnimationFrame() 接口。系统需要在每一帧获取时间戳,实时读取页面元素的几何包围盒,计算小人的位置、速度矢量与碰撞结果,再将坐标更新到视图上。
Walker Playground 真正采用的是行为与视觉解耦的混合架构。JavaScript 充当幕后的小型物理引擎,接管所有空间决策与状态机;CSS 则退居渲染层,只负责角色行走周期的步态帧切换,并通过修改 transform 和 opacity 属性来移动角色,从而避开昂贵的图层重绘开销。
标题里的 CSS 只是视觉画皮,JavaScript 才是驱动物理世界的骨骼。
为什么文字段落必须做成单向穿透地板
把现有的 DOM 树直接当成游戏关卡,最棘手的不是怎么让小人动起来,而是如何处理网页排版与刚体物理之间的冲突。如果开发者简单粗暴地把页面上所有 HTML 标签的包围盒都设为实心墙体,小人只要走进一段普通文本,就会立刻陷入死锁。

原因出在网页排版的默认几何尺度上。在常规正文中,两行文字之间的行距(Line-height)往往小于像素小人的身高。如果每一行文字都是上下左右全封闭的实心碰撞体,小人从上一行末尾掉到下一行时,头部就会被上一行的底边死死卡住,既走不动也掉不下去。
为了解决这个排版死结,该项目对 DOM 元素做了极有巧思的分类处理。卡片边框、按钮、图片和表单输入框被设定为全实心碰撞体,小人撞上侧面会掉头,掉进封闭边框里会被关住;而文本段落里的每一行字,都被单独拆解为单向穿透地板。
在这种规则下,文字行只在垂直下落方向提供支撑力。小人可以稳稳站在字行顶部,走到短句末尾时顺势跌落到下一行;但在水平行走或从下方跃起时,字行不会产生任何横向阻挡。这种取舍让小人得以在密集的多列文章段落里自由穿梭,最后由页面最底部预设的一条通栏长地板兜住所有坠落到底的角色。
把性能毒药变成核心玩法:给前端开发者的启示
在常规的 Web 性能工程里,浏览器的布局重排(Layout Reflow)一直是开发者极力规避的性能毒药。每当窗口尺寸改变导致 Flex 或 Grid 容器里的卡片换行、多列文本重新流式分布时,浏览器都要重新计算成百上千个节点的几何位置。

Walker Playground 反其道而行之,直接把排版引擎的重排过程当成了物理引擎的动力源。当用户快速拖拽缩放浏览器窗口时,卡片换行或字行重排会导致小人脚下的支撑面发生瞬时位移;系统捕捉到前后两帧之间 DOM 节点边界的剧烈坐标差,将其折算成施加给小人的加速度与初速度,从而实现了窗口缩放弹射(Resize Launch)的独特交互。
- 结论.对于前端开发者与交互设计师而言,这个项目证明了构建轻量级网页物理交互未必需要引入庞大的 WebGL 或 Canvas 游戏引擎,直接榨干原生 DOM 的几何测量接口就能做出极具生命力的创意实验。
不过,这种直接拿 DOM 当物理地形的做法也有明显的工程边界。目前公开代码库中尚未找到包含 __walker.add() 接口的已验证开源仓库(GitHub 上同名的 dynamicmobility/walker-playground 实为步行模型仿真研究,与该项目无关)。如果开发者想在生产环境的个人博客或营销落地页复刻类似效果,最大的瓶颈在于高频读取 DOM 布局信息引发的强制同步布局(Layout Thrashing)——一旦页面节点过多或同屏小人数量失控,帧率就会迅速崩盘。接下来值得观察的是,该项目的作者是否会正式开源底层碰撞代码,以及现代 CSS 正在推进的锚点定位(Anchor Positioning)等新特性,未来能在多大程度上帮 JavaScript 分担这类空间位置追踪的计算压力。
