项目名比较直接建议先别因为是这个名字就跳过。GitHub 上有一类“讽刺型”开源项目Every Fucking Website (2020)属于那种几乎不需要解释、打开就知道在骂谁的类型它把 2020 年前后内容型网站最常见的用户骚扰手段集中放进了一个滚动页面里让访问者亲自经历一遍“打开网页就中招”的过程。严格讲它不是组件库不是前后端框架也不依赖 GPU、CUDA、模型权重这些东西。它是一个纯前端静态页面形态的反模式合集。你从页面顶部往下滚动时会遇到 Cookie 弹窗、订阅弹窗、自动播放视频、固定导航条、分享按钮轰炸、进度条伪装、下载 App 引导这类现代网站常见操作。讽刺的地方在于它把所有套路堆在一起所有设计都精准地踩在用户烦躁点上。对开发者来说这个项目的价值不只是“看个乐”。它可以把很多交互设计教科书里分散描述的问题压缩成一次亲身走查你不必阅读长篇 UX 理论只要滚动这个页面就能回忆起自己曾经因为哪个弹窗、哪个按钮、哪个自动播放的视频而直接关掉网站。这种“负面体验”反而能成为前端评审时很好的对照样本。下面我会从项目定位、反模式清单、页面技术实现、本地启动、走查方法、合规边界这几个方向展开适合前端工程师、交互设计师、负责官网或 ToB 产品体验的技术负责人阅读。最后会给出一套可以抄到团队内部的自查清单。1. 核心能力速览先用一张表把项目能力说清楚避免浪费阅读时间。能力项说明项目名称Every Fucking Website (2020)项目性质讽刺型网页实验 / 前端反模式合集主要功能在滚动过程中复现常见网站骚扰式交互发布时间2020 年技术形态Web 静态页面HMTL/CSS/JavaScript运行方式浏览器直接访问或使用本地静态服务器硬件要求无特殊要求不需要 GPU也不需要大内存依赖情况从项目形态推测为轻量实现最终以仓库 README 为准接口 API不提供也不需要批量任务不支持适用人群前端、交互、产品、内容平台运营、前端教学它没有显存占用、采样步数、模型推理之类的问题运行方式比大模型项目简单得多。如果你之前主要接触 Stable Diffusion、ComfyUI、TTS 这类重计算工具这个项目会让你回到一个相对纯粹的 Web 场景打开浏览器看网页自己表演。2. 这个项目在讽刺什么2020 年的网站“通病”2.1 滚动页面本身就是展览Every Fucking Website (2020)的目录设计本质上是一个长滚动叙事页面。它没有复杂路由也没有多人协作、数据库、后台管理。访问者的预期行为就是滚动而滚动又恰好是所有浏览器里最容易触发事件的用户行为之一。每次滚动进入一个新的展示区块页面就会模拟一个网站“症状”。这样的设计有一个好处用户可以亲身感受到突然弹出的弹窗打断了当前阅读节奏。这种体验不是看截图能获得的。2.2 里面集中反映的网站反模式下面这些反模式不是所有都一定出现在项目每一屏里但整体上代表了 2020 年前后主流内容网站被吐槽最多的问题Cookie 同意弹窗刚进入页面就弹出占据半个屏幕解释得云里雾里。邮件订阅弹窗用户只看了一两段正文订阅框就覆盖过来。自动播放视频静音与否先不谈它总是抢占视口让人措手不及。固定导航和按钮不管用户滚到哪里总有几个悬浮元素遮挡内容。分享按钮堆叠阅读页侧边放一长排社交按钮横跨移动端和桌面端。无限滚动或“加载更多”用户无法定位自己阅读的位置刷新后彻底迷路。通知请求刚打开网站就问“是否允许发送通知”。下载 App 横幅明明用浏览器也能完成操作页面仍反复引导安装客户端。右键禁用和复制限制阻止用户复制文字却没有提供合理的替代方案。文章中间的广告插入正文被切成多段每段之间塞入与内容无关的广告。这些模式在单一网站里出现一两个用户还能忍当一整个网页把每个环节都做成“打扰点”之后体验会非常糟糕。项目利用的正是这种叠加效应。2.3 商业指标和用户体验的冲突值得深挖的是这些反模式并不是某个开发者突然拍脑袋做出来的很多是 A/B 测试优化后的结果。订阅弹窗能提高邮件转化率通知请求能带来回访流量无限滚动能拉高页面浏览深度。这些都是运营数据上的“正面指标”但对真实读者而言它们消耗的是注意力和耐心。从 2020 年之后网络趋势看用户开始主动安装广告拦截器和弹窗拦截器浏览器也逐步收紧通知权限和自动播放策略。正是在这种对抗环境下Every Fucking Website 提供了一次集中的“镜像展示”让设计和业务人员重新思考“诱导用户”和“服务用户”之间的边界。3. 前端技术拆解这类恼人效果是怎么实现的虽然不能直接拿这个项目当源码教程但从页面暴露出的行为模式看它用到的前端技术非常基础很适合用来做模仿练习。3.1 滚动监听和交叉观察器要让“用户滚到某个区域就弹出东西”最简单的方案是监听scroll事件再判断元素是否进入视口。更标准的做法是使用IntersectionObserver不用频繁触发滚动函数性能更好。一个页面代码如下用于在陷阱区域进入视口时触发自定义事件const traps document.querySelectorAll([data-trap]); const observer new IntersectionObserver( (entries) { entries.forEach((entry) { if (entry.isIntersecting) { const trap entry.target.dataset.trap; window.dispatchEvent( new CustomEvent(show-trap, { detail: { trap } }) ); } }); }, { threshold: 0.6 } ); traps.forEach((node) observer.observe(node));如果项目版本比较老可能使用的是window.addEventListener(scroll, handler, { passive: true })。滚动处理函数中会判断getBoundingClientRect()确认弹窗容器是否已经进入视口。两者都能达到效果差别主要在性能体验上。3.2 弹窗层叠与滚动锁定网页“烦人感”一大来源是样式层叠。弹窗出现后背后页面通常会被盖上一层半透明遮罩同时锁定背景滚动。代码会类似这样function openModal() { document.body.style.overflow hidden; modal.classList.add(modal--visible); overlay.classList.add(overlay--visible); } function closeModal() { document.body.style.overflow ; modal.classList.remove(modal--visible); overlay.classList.remove(overlay--visible); }滚动锁定是移动端最常见的坑之一。如果只是设置overflow: hiddeniOS 上的页面可能仍然可以滚动如果同时使用了多个弹窗关闭一个后要小心恢复原来的滚动位置。实战项目里还需要考虑键盘焦点是否被限制在弹窗内是否支持Esc关闭以及屏幕阅读器是否可以感知弹窗状态。浏览器对弹窗的容忍度并不高多个弹窗叠加出现时用户在第一次遇到后就会条件反射式地找关闭按钮。3.3 自动播放和浏览器策略自动播放视频在桌面浏览器上有明确限制带声音的视频通常不会被自动播放除非用户和网站已经产生较强的互动信号。静音视频自动播放的容忍度更高一点。Chrome 这类浏览器会根据用户的媒体参与度评分决定是否允许声音播放。所以如果要在自己的反模式演示页面里实现视频自动播放常用写法是加上muted、playsinline和autoplayvideo autoplay muted playsinline loop source srcdemo.mp4 typevideo/mp4 / /video但注意这里只能保证“静音自动播放”无法绕过浏览器的声音自动播放策略。这也是为什么很多自动播放广告会先静音播放等用户点击后再出声。3.4 表单弹窗的“假门槛”Cookie 和订阅弹窗通常还会涉及表单验证逻辑。常见实现是用 JavaScript 拦截表单提交人为制造 loading 状态再随机决定是成功还是请求失败以模拟网络请求。这样做的好处是能在静态演示里营造真实感但如果在生产业务里故意延迟用户操作就属于典型的 dark pattern不值得推荐。4. 本地运行与体验方式Every Fucking Website (2020)的运行门槛很低。从公开形态看它更接近一个静态站点没有强烈的服务端依赖。最稳妥的做法是克隆仓库后用本地静态服务器跑起来。4.1 基本启动步骤# 将 仓库地址 替换成实际仓库地址 git clone 仓库地址 cd 项目目录 python3 -m http.server 8080然后打开浏览器访问http://127.0.0.1:8080如果你没有配置 Python也可以使用 Node 生态的 serve 工具npx serve .它会自动挑一个端口并打印访问地址。如果你在 Windows 上使用 Python可能要把python3改成python或py具体以本机环境为准。4.2 为什么不直接用 file 协议打开很多静态页面双击 index.html 也能看但部分资源请求、脚本模块、跨域图片在file://协议下会被浏览器拦截。特别是页面里如果使用fetch拉取远程内容直接打开本地文件很容易报 CORS 错误。用本地 HTTP 服务可以避免大部分这类问题也更贴近生产环境。4.3 准备一个干净的测试环境为了能“完整体验”到所有反模式建议使用无痕窗口并关闭浏览器扩展。广告拦截器、弹窗拦截器、隐私插件都很可能会把 Cookie 提示或订阅层挡掉那样你反而看不到页面设计的完整效果。建议观察维度包括页面加载前 3 秒内出现了几次弹窗或覆盖层。每条内容区域是否被固定栏挡住。离开页面时是否出现挽留弹窗。移动端视口下弹窗是否覆盖整屏且难以关闭。页面底部有没有回归正常的“无打扰”状态。5. 功能测试与效果验证这里需要扭转一个观念当一个讽刺页面的目标是“让人难受”时验证标准不是“界面好不好看”而是“模式是否生效、何时生效、给用户带来多大阻力”。5.1 验证流程建议按下面的流程来做一次完整走查打开无痕浏览器窗口访问http://127.0.0.1:8080。观察首屏记录 0 到 5 秒内出现哪些弹窗。开始滚动每次只滚一个视口高度。记录每次新元素触发的时间点。尝试关闭弹窗看关闭按钮是否明显逻辑是否正常。尝试返回页面顶部看是否出现挽留弹窗或障碍层。打开 DevTools检查滚动过程中新增的 DOM 节点和样式覆盖。把每类问题的“出现次数”和“打断程度”记录下来。5.2 用 DevTools 验证触发逻辑打开 DevTools 的 Console 面板滚动过程中可以看到页面对事件的处理日志。如果你的目标不是单纯浏览而是学习工程实现可以在 Console 里执行以下代码观察页面上有哪些陷阱节点const traps document.querySelectorAll([data-trap]); console.log(traps.length); traps.forEach((node) console.log(node));如果页面并没有为节点加上这类标记你也可以在 Elements 面板逐层查看被插入的遮罩和弹窗结构。这比猜代码更准确。5.3 判断一次走查是否完成建议当用户完成以下动作后才算一次完整走查打开页面并读完第一段正文。滚动至少十个视口。触发至少三种弹窗。完成一次弹窗关闭操作。尝试搜索或点击链接。在移动端模拟器里重跑一遍。如果这些动作还没有完成用户就已经产生“关掉页面”的冲动说明反模式叠加得足够强也说明这个项目确实说出了很多人对网站体验的不满。6. 把反模式清单变成团队评审工具一个 2020 年的讽刺页面今天还能给团队带来什么价值我认为最有价值的是把它转成一套“官网自检清单”。很多团队设计官网时会对齐竞品但是竞品往往也有同样的问题订阅弹窗、通知请求、悬浮广告一个不少。如果你照着竞品抄最终产品会共同走向用户疲劳。EFW 提供了一个很有用的对照组把所有反模式剥离出来避免出现在自己的核心路径上。以下是一份可以当作日常走查的清单当用户首次访问时页面会在几秒内发起多少打扰请求正文区域之外的固定元素是否遮挡内容关闭弹窗后是否会在短时间再次弹出用户进入页面的核心目标是否被无关模块打断通知权限请求是否在用户产生足够信任前出现移动端是否有覆盖整屏且难以关闭的浮层是否能一键刷新页面重新查看全部内容清单不需要一开始很复杂。你可以先围绕“首屏、正文、滚动过程、离开页面”四个场景设置检查点运行一段时间后再根据用户反馈补充条目。7. 自动化观察用 Playwright 记录“打扰过程”前端页面如果要做回归巡检可以把 EFW 这类演示页面作为一个自动化的“压力测试样本”。用 Playwright 控制浏览器滚动并在滚动过程中截屏或记录 DOM 变化能快速得到一份反模式触发时间线。下面是一个通用脚本示例不针对任何精确选择器只演示思路from playwright.sync_api import sync_playwright url http://127.0.0.1:8080 with sync_playwright() as p: browser p.chromium.launch(headlessTrue) page browser.new_page(viewport{width: 1280, height: 900}) page.goto(url, wait_untilnetworkidle) page.screenshot(pathstep-00-landing.png) for i in range(10): page.evaluate(window.scrollBy(0, window.innerHeight)) page.wait_for_timeout(800) page.screenshot(pathfstep-{i 1:02d}.png) browser.close()这段脚本的价值在于它可以可重复地检测“页面在滚动过程中是否会稳定复现预期问题”。如果你想统计弹窗出现频率可以在每次滚动后查询页面里可见的遮罩节点数量把结果输出成 JSON 记录。const overlays [ ...document.querySelectorAll(.modal, .popup, .overlay, [class*modal]), ].filter((el) { const style window.getComputedStyle(el); return style.display ! none style.visibility ! hidden; }); console.log(visible overlays: ${overlays.length});在 headless 浏览器中这类统计能帮你识别页面是否因为某些定时器或滚动事件出现“无休止的新增节点”。如果页面存在内存泄漏持续滚动后DOM 节点数会不断上升最终影响浏览器性能。8. 常见问题与排查方法这个项目本质是前端页面所以多数问题集中在运行环境、弹窗拦截和静态资源路径上。问题现象可能原因排查方式解决方案页面打开后没有看到任何弹窗扩展插件拦截弹窗或浏览器隐私设置过于严格使用无痕窗口并禁用扩展关闭广告拦截扩展后再试双击 index.html 打开后样式错乱file 协议下资源路径不对查看 Network 面板是否有 404改用本地静态服务器视频没有自动播放浏览器自动播放策略限制打开 DevTools 查看 Media 报错给 video 加 muted 和 playsinline滚动过程中页面卡顿大量脚本反复修改 DOM 或样式打开 Performance 面板记录滚动过程给滚动监听加节流或改用 IntersectionObserverDevTools 里看到某个资产 404路径写死或目录结构改变查看页面源码中资源路径把项目放到根目录启动页面字体或图片无法加载远程资源被网络环境拦截查看 Network 面板目标状态把资源下载到本地再测试关闭某个弹窗后背景仍无法滚动滚动锁定没有正确恢复检查 overflow 样式是否被覆盖显式移除 body 上的 overflow hidden如果排查后仍然复现问题优先看两个位置一是浏览器 Console 里的报错信息二是 Network 面板里的请求状态。大部分静态页面问题都能通过这两个入口定位到原因。9. 合规、安全与二次开发边界讽刺页面和真实业务页面之间存在一条清晰界限前者可以把所有反模式做到极致只为了表达情绪后者必须在收集用户数据、推送订阅、投放广告时遵守数据隐私和用户同意规则。9.1 不要直接把讽刺页面当成合规模板有些反模式看似“提升了转化”实际可能回避了用户真正的同意意愿。比如 Cookie 弹窗中把“同意”按钮做得非常大把“拒绝”或“管理设置”放在很隐蔽的位置体验上更像诱导而非告知。真实业务如果照抄这种交互很容易在法律和用户信任两个层面同时出问题。在国内外个人信息保护相关规定里要求用户自主选择和撤回同意已经成为共识。页面可以设计成默认不开启非必要 Cookie而不是默认全开。每一次弹出提示都应该能明确回答三个问题为什么收集、收集什么、用户如何撤回。9.2 尊重原作者版权如果你把 EFW 的设计改造成内部文档、课程截图或团队分享材料需要先确认许可证和仓库 README 中的使用约定。讽刺作品仍然受版权保护别因为页面的内容是“讽刺”就直接搬运。用于教学或技术讨论时建议保留出处并标注这是一个反模式演示避免让读者误解为推荐的做法。9.3 二次开发时的内容安全如果你想参考它的视觉语言去做一个团队内部 Demo要注意项目本身包含直接的不雅措辞和成人向表达。这部分内容适合放在私人讨论、代码演示或内部培训时说明公开传播时需要做好内容边界控制。任何二次开发都应该符合你的目标受众与社区规范不可以用一个本来用于反思的讽刺作品去传播攻击性内容。9.4 涉及用户数据时的安全红线真实的站点复现 Cookie 弹窗时必须关联隐私政策、数据收集清单和用户撤回机制。不要只在界面上做样子背后仍然偷偷埋点。涉及自动通知、自动定位、读取通讯录或访问相机麦克风时必须拿到明确、分场景的用户授权。这套红线与技术实现无关属于产品合规底线。10. 这个项目更合理的三种使用方式看完了整页的“折磨”如果只停在“好真实”三个字上多少有点可惜。把它用到自己的开发流程里效果会更好。10.1 给新人当“反面教材”新前端常常把注意力放在动效流畅度、页面精美度上而忽略弹窗机制是否礼貌、通知权限是否滥用。新人把 EFW 完整刷一遍再对照自己写的官网组件想想哪些代码会造成类似效果会更容易建立同理心。它不是标准答案却是一张踩坑地图。10.2 给设计评审提前排雷准备上线新站或改版前可以专门安排一次“反模式走查”。让团队成员扮演极端用户不允许点击任何弹窗只找关闭按钮看路径是否顺畅。很多体验问题会在这个环节暴露。10.3 做浏览器行为教学EFW 很适合用来讲浏览器的自动播放策略、滚动监听、弹窗层级、DOM 动态插入和移动端视口适配。讲课前先打开页面滚动两轮再切换到代码讲解比直接念 PPT 高效得多。不要把它当作 UI 风格指南也不要把它当作可以原样复制到商业项目里的“增长模板”。它真正的价值恰恰是反面警示。11. 总结与下一步实践这个 2020 年项目的最大价值不是技术复杂度而是把反模式做成了一次可体验的放大镜。它让我想起很多产品在“增长”和“体验”之间反复摇摆的状态每一次弹窗上线都有理由但叠加到最后却让人想关掉页面。下一步建议你先做三件事在无痕窗口里完整滚动一遍 EFW 演示页把让你最烦躁的三个节点记录下来。打开自己公司官网走一遍同样的阅读路径看是否能在首屏到正文之间不被任何浮层打断。把发现的问题整理成清单交给产品和设计团队做一次专项评审。相比 2020 年今天的浏览器在通知权限、自动播放、弹窗拦截上已经严格很多但骚扰式交互并没有消失而是换成了更精致的会员引导、客服气泡、活动倒计时和 AI 助手浮窗。这个项目的讽刺对象会一直更新开发者需要保留的是对用户注意力的基本尊重。如果你身边还有人不理解“网页为什么越来越重、越来越烦人”把 EFW 打开让他滚一遍也许比十页 PPT 更有说服力。建议先把本文收藏等到做官网体验评审时按里面的清单逐项走一遍很快就能发现日常被忽略的打断点。