讽刺型网页项目:把网站所有烦人交互集中到一个页面
2026/9/4 5:30:07 网站建设 项目流程

项目名比较直接,建议先别因为是这个名字就跳过。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: hidden,iOS 上的页面可能仍然可以滚动;如果同时使用了多个弹窗,关闭一个后要小心恢复原来的滚动位置。实战项目里还需要考虑键盘焦点是否被限制在弹窗内,是否支持Esc关闭,以及屏幕阅读器是否可以感知弹窗状态。

浏览器对弹窗的容忍度并不高,多个弹窗叠加出现时,用户在第一次遇到后就会条件反射式地找关闭按钮。

3.3 自动播放和浏览器策略

自动播放视频在桌面浏览器上有明确限制:带声音的视频通常不会被自动播放,除非用户和网站已经产生较强的互动信号。静音视频自动播放的容忍度更高一点。Chrome 这类浏览器会根据用户的媒体参与度评分决定是否允许声音播放。

所以如果要在自己的反模式演示页面里实现视频自动播放,常用写法是加上mutedplaysinlineautoplay

<video autoplay muted playsinline loop> <source src="demo.mp4" type="video/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改成pythonpy,具体以本机环境为准。

4.2 为什么不直接用 file 协议打开

很多静态页面双击 index.html 也能看,但部分资源请求、脚本模块、跨域图片在file://协议下会被浏览器拦截。特别是页面里如果使用fetch拉取远程内容,直接打开本地文件很容易报 CORS 错误。用本地 HTTP 服务可以避免大部分这类问题,也更贴近生产环境。

4.3 准备一个干净的测试环境

为了能“完整体验”到所有反模式,建议使用无痕窗口并关闭浏览器扩展。广告拦截器、弹窗拦截器、隐私插件都很可能会把 Cookie 提示或订阅层挡掉,那样你反而看不到页面设计的完整效果。

建议观察维度包括:

  • 页面加载前 3 秒内出现了几次弹窗或覆盖层。
  • 每条内容区域是否被固定栏挡住。
  • 离开页面时是否出现挽留弹窗。
  • 移动端视口下,弹窗是否覆盖整屏且难以关闭。
  • 页面底部有没有回归正常的“无打扰”状态。

5. 功能测试与效果验证

这里需要扭转一个观念:当一个讽刺页面的目标是“让人难受”时,验证标准不是“界面好不好看”,而是“模式是否生效、何时生效、给用户带来多大阻力”。

5.1 验证流程

建议按下面的流程来做一次完整走查:

  1. 打开无痕浏览器窗口,访问http://127.0.0.1:8080
  2. 观察首屏:记录 0 到 5 秒内出现哪些弹窗。
  3. 开始滚动,每次只滚一个视口高度。
  4. 记录每次新元素触发的时间点。
  5. 尝试关闭弹窗,看关闭按钮是否明显,逻辑是否正常。
  6. 尝试返回页面顶部,看是否出现挽留弹窗或障碍层。
  7. 打开 DevTools,检查滚动过程中新增的 DOM 节点和样式覆盖。
  8. 把每类问题的“出现次数”和“打断程度”记录下来。

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(headless=True) page = browser.new_page(viewport={"width": 1280, "height": 900}) page.goto(url, wait_until="networkidle") page.screenshot(path="step-00-landing.png") for i in range(10): page.evaluate("window.scrollBy(0, window.innerHeight)") page.wait_for_timeout(800) page.screenshot(path=f"step-{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 面板记录滚动过程给滚动监听加节流,或改用 IntersectionObserver
DevTools 里看到某个资产 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 年项目的最大价值,不是技术复杂度,而是把反模式做成了一次可体验的放大镜。它让我想起很多产品在“增长”和“体验”之间反复摇摆的状态:每一次弹窗上线都有理由,但叠加到最后却让人想关掉页面。

下一步建议你先做三件事:

  1. 在无痕窗口里完整滚动一遍 EFW 演示页,把让你最烦躁的三个节点记录下来。
  2. 打开自己公司官网,走一遍同样的阅读路径,看是否能在首屏到正文之间不被任何浮层打断。
  3. 把发现的问题整理成清单,交给产品和设计团队做一次专项评审。

相比 2020 年,今天的浏览器在通知权限、自动播放、弹窗拦截上已经严格很多,但骚扰式交互并没有消失,而是换成了更精致的会员引导、客服气泡、活动倒计时和 AI 助手浮窗。这个项目的讽刺对象会一直更新,开发者需要保留的,是对用户注意力的基本尊重。

如果你身边还有人不理解“网页为什么越来越重、越来越烦人”,把 EFW 打开让他滚一遍,也许比十页 PPT 更有说服力。建议先把本文收藏,等到做官网体验评审时,按里面的清单逐项走一遍,很快就能发现日常被忽略的打断点。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询