ARCHIVE
아카이브
기존에 공개한 글을 원래 주소 그대로 보관합니다.
과거의 글에는 작성 당시의 기술과 관점이 담겨 있습니다.
356개 글 · 2 / 12 페이지
· ZH
26个抽样页漏掉的3类违规:把WCAG-EM 2.0用在1,342个页面上
W3C 于 7 月 23 日以 Group Note 形式发布 WCAG-EM 2.0。我照着文档的抽样流程挑出 26 个页面,又把同一次构建的 1,342 个页面全部用 axe-core 扫了一遍做对照。抽样只抓到 4 类违规中的 1 类,而随机样本给出新发现的概率只有 0.29%,几乎等于没有。
· ZH
声明标题的七个位置里,只有六个是我写的
一篇文章的标题会在 title、h1、og:title、headline、RSS 等六处被声明,1,296 篇全部一致。真正出问题的是第七处:指向文章的 18,296 条内部链接里,锚文本与目标标题完全一致的只有 0.7%,根源是包住整张卡片的那一个 a 标签。本文给出七个渠道的实测数据与可照做的修复路径。
· ZH
46,382条内部链接里,有24,948条撞在301上
本来是为测量链接文本的无障碍指标写的脚本,结果挖出一个URL缺陷。对构建产物中1,334个HTML页面的内部链接做全量扫描,超过一半的24,948条指向不带尾部斜杠的地址,也就是要走一次301跳转。本文记录成因、四个阶段的修复,以及把它清到零的过程。
· ZH
把列表页从链接图里拿掉,296篇就再也走不到了:抓取深度实测
每篇文章都挂着中位数8条内链,我以为内链已经够了。对1,330个构建产物页做广度优先遍历后,1,288篇文章中有1,276篇位于深度2。可是一旦把四个语言的列表页从链接图里拿掉,296篇从首页再也走不到。相关文章模块再多,也替代不了四个语言列表页这个入口。从首页出发时,四个列表页才是通往深度2的门。
· ZH
div 网格做的表格悄悄丢掉了什么:无障碍树与文本抽取的同步实测
把同一张营业时间表用四种标记方式写出来,分别过 axe-core 和五个抽取器。axe 对四种都给出零违规,可一旦把 HTML 还原成 Markdown 或纯文本,其中三种只能复原 0/7 行。role="table" 到底在哪一层帮不上忙,这里用实测日志说清楚。
· ZH
开了 prerender,LCP 却记成 6.2 秒:不减 activationStart 的 RUM 在骗你
用 Speculation Rules 预渲染后,LCP 原始值会把整段等待都算进去。我在 Chrome 150 上实测了 6244ms 与 103.5ms 的落差,并梳理出所有需要校正的位置。
· ZH
每次升级模型都要重跑注入测试:我把这道关卡亲手搭了出来
我把注入回归测试跑在自己的 LLM 流水线上。朴素守卫 11 条只拦 2 条,结构化守卫全部拦下,重构漏掉的检测器也被关卡精准点出。
· ZH
WebMCP进入origin trial——provideContext为何半年就消失了
WebMCP以Chrome 149的origin trial正式落地,但二月介绍的那套API已经变了。navigator.modelContext迁到了document.modelContext,provideContext因安全问题被移除。本文以官方文档与规范Issue为依据,梳理现在该注册的工具形态与安全注解。
· ZH
FAQ富媒体结果已经结束,但别急着删掉Q&A标记
Google在2026年5月7日彻底停用了FAQ富媒体结果。把FAQPage JSON-LD丢进离线校验器,schema能通过,可富媒体结果返回的是DEPRECATED。就在"通过"与"可见"分岔的这个点上,本文依据Google官方文档,梳理Web开发者现在该如何改代码和内容。
· ZH
官方说「WebSocket 不再拦截 bfcache」,我重测了三次,次次都被拦
Chrome 149 宣布活动中的 WebSocket 不再阻止 bfcache。我在 Chrome 150 的三种环境里重新测了一遍,notRestoredReasons 照旧返回 websocket,三次都一样。发布说明和实测对不上的那个点,连同复现脚本、测量日志和三次运行的差异都一起记了下来。
· ZH
aria-modal="true" 什么都没拦住:模态框焦点逃逸实测与 inert
一个带 role="dialog" 和 aria-modal="true" 的「标准」模态框,按第三次 Tab 时焦点就逃到了遮罩层背后,而 axe 报告的焦点类违规为 0。我把同一份标记分别换成 aria-hidden 和 inert,逐次记录键盘焦点的实际落点。
· ZH
opens: "eleven" 三层校验全放行 — 餐厅营业时间 JSON-LD 的实测记录
给自己运营的餐厅推荐PWA补上Restaurant结构化数据:把按天存储的营业时间字符串转换成openingHoursSpecification,再把同样三个缺陷依次喂给类型检查、schema.org校验器和运行时门禁,逐层测量谁能抓住什么。并引用官方文档,诚实划清它对本地排名的作用边界。
· ZH
unload被拦,beforeunload放行:bfcache实测六轮
「后退」能不能瞬间打开,不是口味问题,是可以量的。我做了六个页面,每个只埋一种阻断条件,逐一执行真实的后退导航,读取 pageshow.persisted 与 notRestoredReasons。unload 被拦,beforeunload 和 no-store 都放行了。
· ZH
我的聚合 RSS 混着四种语言的 1,248 条,没有一条标了语言
W3C 在 2026-07-16 公开了字符串语言与方向元数据的首份草案。我照着它审计了自己的四语站点,发现聚合 RSS 的 1,248 条内容全是无标注输出。这里有实测、修复代码和防回归的构建关卡。
· ZH
WCAG 2.2 最小目标尺寸:藏在92分绿灯背后的AA不合格
一排22×22的分页链接,拇指总按偏,Lighthouse却给了无障碍92分。我把WCAG 2.2新增的SC 2.5.8(最小24×24)种进沙箱,用自写脚本和Lighthouse各测一遍。自动工具如今能抓尺寸违规,却把例外判定甩回给你。连24px圆是否相交的间距例外计算,都用实测日志和CSS修复讲清楚。
· ZH
决定 AI Overview 能否引用你页面的那一行 meta —— 实测 robots 摘要指令
一行 nosnippet 已经不只是关掉搜索摘要。Google 官方文档明确写道:这条指令还会阻止内容被用作 AI Overview、AI Mode 的输入。我做了一个坏页面和一个好页面,再写解析器逐一审计,测出 max-snippet 与 data-nosnippet 的真实效果,以及"最严格者胜"这条规则如何咬人。
· ZH
一行 CSS 把强制布局从 27.3ms 压到 1.8ms:content-visibility 实测
同一份 HTML、同样的字节数,只多加一行 CSS,强制布局成本就降了 15 倍。我把一个 400 段的页面做了两个版本,用 Chrome 追踪和 Performance API 实测 content-visibility: auto 到底省了多少渲染,并讲清 contain-intrinsic-size 与无障碍陷阱。
· ZH
点一下花了264ms — 同样的活儿切碎后只要56ms:一次INP实测
INP在2024年取代FID成为Core Web Vitals的响应性指标。我用Event Timing API直接测量同样220ms的工作在一口气跑完与用scheduler.yield切碎两种做法下的差异,并用代码和日志完整记录264ms(需改进)如何降到56ms(良好)的全过程。
· ZH
刚要点按钮,页面却跳了一下 — 把 CLS 从 0.559 压到 0.014 的实测记录
加载时布局乱跳不是审美问题,而是一个能量化的指标。我把同一个页面做了两版,用 layout-shift PerformanceObserver 测 CLS,只靠给图片预留盒子、给动态内容预留槽位,就把 0.559(POOR)压到了 0.014(GOOD)。过程有代码,有日志,也有可以照着复现的测量步骤。
· ZH
英雄图只有117KB,LCP 却要1.2秒 — 浏览器为什么"太晚才找到"你的图片
LCP 慢,往往不是图片太重,而是浏览器"什么时候发现"这张图的问题。我用 Chrome DevTools 实测了 CSS 背景图对预加载扫描器隐身的现象,再用 fetchpriority、preload 和去掉渲染阻塞 CSS,把 LCP 从 1247ms 压到 109ms。
· ZH
结构化数据要在上线前拦下 — 在 CI 里自动校验 JSON-LD
JSON-LD 解析器放行的标记,搜索引擎未必读得懂。因为 schema.org 设了 @vocab,拼写错误和大小写错误都会展开成合法的 JSON-LD。这里用一个 60 行的、懂 schema 的校验器,在 CI 里把它们拦下,附真实运行日志。
· ZH
自动无障碍检测亮了绿灯,仍留下的四道墙
我往一张结账页面里故意埋了八处WCAG障碍,再用axe-core跑一遍。规则型的四处被抓住,需要人来判断的四处却在绿灯背后原样留着。本文用实测日志说清楚自动化在结构上看不到什么,以及补上这块缺口的人工复查清单。
· ZH
JSON-LD vs Microdata vs RDFa — 结构化数据语法,何时用哪个(实测对比)
把同一个 Product 实体用三种语法各写一遍,喂进解析器,实测字节数和易碎程度。Google 三者同等对待。那么推荐 JSON-LD 的真正理由不是排名,而是能在改版中活下来的耦合度。用官方文档和可复现日志梳理出的选型标准。
· ZH
无障碍名称一旦错位,语音控制和AI智能体都按不了这个按钮
给按钮加了aria-label,无障碍树读出来的却是屏幕上根本看不到的字。我在沙盒里复现了WCAG 2.5.3 Label in Name违规,直接从无障碍树读出问题,再用Lighthouse 13.3.0新增的Agentic Browsing评分,看着它从0分变成100分。
· ZH
AI 爬虫不会执行你的 JavaScript
GPTBot、ClaudeBot 都不渲染 JS。用 curl 复现 CSR 页面为何在 AI 搜索里隐形,并给出改为服务端渲染的具体做法。
· ZH
sitemap.xml 里,Google 真正会读的只有 lastmod
给首页加上 priority 1.0 和 changefreq always,Google 全部丢弃。官方文档只用一个字段——lastmod,而且只在它可验证地准确时才用。我用官方 XSD 实际跑了三种 sitemap,看清什么通过校验、什么被悄悄忽略。
· ZH
同一份标记,不同判定 — 把 axe-core 塞进 CI 时 color-contrast 为何悄悄消失
我把一个 AI 生成的预订组件分别用 axe-core 跑在 jsdom 和真实浏览器里。四条结构性违规不用浏览器就被抓住,唯独 color-contrast 在 jsdom 里落到了 incomplete。这篇讲清楚原因,以及如何把 CI 流水线拆成两层、让覆盖率的洞不再出现,附带真实日志。
· ZH
我把技术SEO审计连跑了五天——比修好的五项更关键的是那几道门禁
对我的四语言博客做了五天实测审计。relatedPosts的404有12个、hreflang断链4对、渲染阻塞的字体CSS 405KB、翻译漂移21处、碎片化JSON-LD 7块。全都修了。但真正的成果是让它们再也回不来的构建门禁。附实测日志与检查器代码。
· ZH
把 JSON-LD 拧成一个 @graph — 让散落的结构化数据变成搜索与 AI 能读懂的实体模型
把自己页面的 JSON-LD 丢进校验工具,结果散成了三座孤岛。本文用 @id 节点引用把 Organization、WebSite、Article 拧进一个 @graph,并用 jsonld 实测连通性:三个分量如何合并成一个,以及 Google 不保证的地方。
· ZH
hreflang必须双向 — 审计自己的四语言博客,揪出首页的一个漏洞
我把一个30行的检查器直接跑在自己网站的构建产物上。248篇博客文章的hreflang集群全部通过,唯独首页没过。本文梳理Google官方的相互链接规则、实测日志、三种实现方式的对比,以及开发者可以直接套用的修复代码。