Bookmarklet 是一种将 URL 设置为以 javascript: 为前缀的单行 JavaScript 代码的书签,点击后会在当前页面执行该代码,而不会跳转到其他页面。这使得 bookmarklet 成为实时编辑页面、调试布局、显示隐藏输入内容或获取颜色的最快零安装方式——无需安装扩展、无需打开 DevTools 面板、无需构建步骤。本文将为你介绍五个真正实用、代码简洁的 bookmarklet,它们均可在当前主流 Chromium 浏览器中正常运行。文章还将说明各自的适用场景,并在介绍如何编写自定义 bookmarklet 之前,重点讲解常见的坑(单行解析、Content-Security-Policy 拦截、同源限制)。
安装方式有两种:创建一个新书签并将 javascript: 代码粘贴为其 URL,或将 href 为该代码的链接直接拖到书签栏。以下每段代码均已整理为单行格式,可直接粘贴使用。
核心要点
- Bookmarklet 必须是以
javascript:为前缀的单行代码;切勿使用//行注释——这会将其后的所有内容都注释掉。如需注释,请使用/* */。 - 对于会修改 DOM 的 bookmarklet,应以
void 0结尾,或将其包裹在void(...)中。这是因为如果javascript:URL 的最后一个表达式返回字符串,浏览器会用该字符串替换当前页面。 - 原生 EyeDropper 颜色选取器仅在 Chromium 浏览器(Chrome 和 Edge)的 HTTPS 环境下可用;截至 2026 年,Firefox 和 Safari 均不支持该 API。
- 注入外部脚本的 bookmarklet(如 eruda 控制台)在任何设置了严格
Content-Security-Policy的站点上都会被拦截,且网络请求同样受同源策略和 CSPconnect-src规则的约束。
1. 使用 design mode 实时编辑任意页面
Discover how at OpenReplay.com.
将整个页面变为可编辑文档,无需打开 DevTools 即可在线测试文案、间距和布局:
javascript:document.designMode="on";void 0;
将 document.designMode 设置为 "on" 可使整个文档进入可编辑状态——效果等同于 contenteditable="true",但作用范围是整个页面而非单个元素。点击任意标题或段落即可直接输入。当需求方询问”如果这个按钮改成 X 会怎样”,或者你想检查较长的产品名称是否会撑破导航栏,而又不想动代码库时,这个 bookmarklet 就能派上用场。
末尾的 void 0 至关重要。以字符串结尾的 javascript: URL 会被浏览器视为 HTML 文档并触发页面跳转;void 0 强制返回非字符串值,从而保持页面不跳转。如果只想编辑某个区域,可替换为:javascript:void(document.body.contentEditable=true)。
2. 为所有元素添加色调以调试布局
一次性查看页面上所有元素的盒模型边界——对于发现溢出、错位和多余外边距极为有效:
javascript:document.querySelectorAll("*").forEach(e=>e.style.background="rgb(0 0 0 / 10%)");void 0;
这段代码会为页面上的每个元素应用 10% 不透明度的黑色背景。由于半透明图层会叠加,嵌套元素会呈现出逐渐加深的颜色,因此你可以直观地判断 DOM 的嵌套深度,并立即发现哪个容器比其父元素更宽。如果你更偏好硬边框而非渐变填充,可将背景行替换为轮廓线:e.style.outline="1px solid rgb(255 0 0 / 40%)"。轮廓线不影响布局——与 border 不同,它不占用盒模型空间——因此你正在调试的页面几何结构保持不变。
3. 显示被遮蔽的密码字段
将所有密码输入框切换为明文显示:
javascript:(()=>{document.querySelectorAll('input[type=password]').forEach(el=>el.type='text')})();
这段代码会遍历所有 input[type=password] 元素,并将其 type 切换为 text,从而显示当前输入的值。在调试认证表单、验证密码管理器或浏览器自动填充实际输入了什么内容,或确认粘贴时是否带入了尾部空格时,这个 bookmarklet 非常实用。它以与页面内调试器相同的方式读取实时 DOM——对登录失败的会话回放分析常常发现自动填充写入了细微错误的值,而这是手动确认此类 bug 最快捷的方式。
4. 使用原生吸管工具获取屏幕上任意颜色
拾取屏幕上任意像素并获取其十六进制颜色值:
javascript:void(async()=>{try{prompt('HEX:',(await new EyeDropper().open()).sRGBHex)}catch(e){alert(e)}})()
这段代码调用 EyeDropper API,将光标变为带放大镜的颜色拾取器;选中的颜色以 sRGBHex 格式返回,并显示在一个可供复制的 prompt 对话框中。有一点需要注意:EyeDropper API 仅限 Chromium 浏览器(Chrome 和 Edge)使用,且只在安全上下文(HTTPS)下可用,截至 2026 年,Firefox 和 Safari 均不支持该 API。此外,该 API 需要用户主动触发——open() 必须由瞬时用户激活事件触发——而点击 bookmarklet 本身就是一个用户手势,因此可以正常触发。try/catch 会捕获并忽略用户按下 Esc 而非选择颜色时产生的异常。
5. 通过 eruda 注入移动端 DevTools
在任意页面获得完整的控制台和 DOM 检查器——包括在没有 DevTools 的手机上:
javascript:(function(){var s=document.createElement('script');s.src='https://cdn.jsdelivr.net/npm/eruda';s.onload=function(){eruda.init()};document.head.appendChild(s)})();
这段代码会追加一个 <script> 标签来加载 eruda——一个面向移动浏览器的控制台工具,当前稳定版本为 3.4.3——并在加载完成后调用 eruda.init(),在页面上浮现一个 DevTools 面板。在无法连接桌面检查器的真实设备上进行调试时,这是最突出的解决方案。有两点需要了解:未固定版本的 cdn.jsdelivr.net/npm/eruda URL 始终提供最新发布的构建版本;eruda 的发布节奏已趋于停滞(npm 上超过一年未发布新版本),因此可将其视为稳定但不再活跃维护的工具。由于需要加载外部脚本,此 bookmarklet 受下文所述 CSP 限制的影响。
为什么我的 Bookmarklet 无法运行?
以下四种故障模式几乎涵盖了所有”就是不工作”的情况:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 代码只执行了一半 | // 注释会让单行中其后的所有内容失效 | 改用 /* */;bookmarklet 是单行代码 |
| 页面跳转或显示原始文本 | 最后一个表达式返回了字符串,被渲染为 HTML | 以 void 0 结尾或用 void(...) 包裹 |
| eruda/外部脚本 bookmarklet 静默失败 | 严格的 CSP script-src 拦截了注入的脚本 | 客户端无解;站点策略优先 |
fetch() bookmarklet 被拦截 | 同源策略和 CSP connect-src 限制跨域请求 | 仅调用同源或支持 CORS 的接口 |
CSP 的情况最值得重点关注:在设置了严格 Content-Security-Policy 的站点上——可以对比在 GitHub 和宽松策略页面上分别运行 eruda bookmarklet 的效果——控制台根本不会出现,取而代之的是(真实)控制台中记录的一条 CSP 违规信息。javascript: 导航本身也可能被 script-src 拦截。
如何编写自己的 Bookmarklet?
编写自定义 bookmarklet 时,将代码包裹在 javascript: URL 内的 IIFE 中,并以 void 0 结束 DOM 修改表达式,以防止页面因字符串化的返回值而触发跳转:
javascript:(function(){/* your code here */})();
IIFE 可将变量隔离在页面全局作用域之外;javascript:foo() 通常约定加上 void 前缀,以防止调用返回字符串时意外触发导航。建议先在 DevTools 控制台中编写和调试逻辑,然后将其压缩为单行——去除 // 注释——再粘贴为书签的 URL。凡是能在控制台中输入的代码,都可以封装为一键触发的 bookmarklet 随身携带。
常见问题
为什么我的 bookmarklet 执行到一半就停了?
bookmarklet 是单行代码,因此 // 行注释会让其后的所有字符失效,包括右花括号和函数调用。请将所有 // 注释替换为 /* 块注释 */,或直接删除。将多行控制台代码压缩为 bookmarklet 时,务必先去除所有 // 注释,因为原本用于结束注释的换行符在单行中已不存在。
在 bookmarklet 中,designMode 和 contentEditable 有什么区别?
将 document.designMode 设置为 'on' 可通过一条语句使整个文档进入可编辑状态,而 contentEditable 是逐元素设置的,因此 document.body.contentEditable = true 只会使 body 区域可编辑。当你希望点击页面上任意标题、段落或按钮进行编辑时,使用 designMode;当你希望将编辑范围限定在某个特定容器内、保持页面其余部分不变时,使用 contentEditable。
EyeDropper bookmarklet 在 Firefox 或 Safari 中可以使用吗?
不可以。EyeDropper API 仅限 Chromium 浏览器使用,在 Chrome 和 Edge 中可用,且仅在安全上下文(HTTPS)下有效;截至 2026 年,Firefox 和 Safari 均不支持该 API。该 API 还需要瞬时用户激活,但点击 bookmarklet 本身即视为用户手势,因此以这种方式触发时 open() 可以正常执行。在不支持的浏览器中,由于 EyeDropper 构造函数未定义,bookmarklet 会抛出异常。
bookmarklet 可以发起跨域 fetch 请求吗?
不能随意发起。bookmarklet 内的 fetch() 调用运行在当前页面的上下文中,因此受同源策略和站点 CSP connect-src 指令的约束。对不同源的请求会被拦截,除非目标端点返回了正确的 CORS 响应头。请将 bookmarklet 的网络请求限制在与页面同源或支持 CORS 的 API 上;对于站点自身的策略,客户端没有任何绕过方式。