这篇文章原题为《如何让wordpress 在新窗口打开链接?》,发布于 2014 年。旧文把“所有链接都开新窗口”当成目标,并建议修改 WordPress 核心文件;这些做法会制造意外的上下文切换,也会在升级时丢失或与新版代码冲突,现已不应照做。
当前原则是让大多数链接保持浏览器默认的同标签页导航,让用户自行选择中键、快捷键或菜单打开新标签页。只有当保留当前任务上下文确有价值时,才对特定链接请求新的浏览上下文,并在激活前给出可见且可被辅助技术读取的提示。浏览器最终可能使用标签页或窗口,网站不能保证是哪一种。
文末完整保留
source_export的历史正文。归档围栏内的全局<base>和核心文件修改只是历史证据,绝不能执行。
Table of Contents
先决定同标签页还是新标签页
| 场景 | 建议 | 理由与边界 |
|---|---|---|
| 站内文章、分类、导航、面包屑、分页 | 同标签页 | 保留正常历史记录与“后退”行为 |
| 普通外部参考资料 | 通常同标签页 | “外部”不自动构成新标签页理由,用户仍可自行选择 |
| 用户正在填写未保存表单时的帮助或条款 | 可考虑新标签页 | 先保存草稿或保护状态,并在链接文字中预告 |
| 并排核对所需的报告、证据或说明 | 可考虑新标签页 | 需求应来自任务设计,不应只是留住流量 |
| 登录、支付、下载、协议处理器或跨应用操作 | 逐项设计 | 说明目标、文件类型/大小或将启动的应用,不把新标签页当安全控制 |
不要用跳出率、所谓“SEO 权重”或“外链一律新开”的惯例代替用户研究。链接目的、任务连续性和可访问性才是决策依据。
在 WordPress 编辑器中设置单个链接
WordPress 当前的链接控件支持按链接开启或关闭“在新标签页中打开”。界面会随 WordPress 版本、区块和站点插件略有不同,操作前先在预发布站确认:
- 选中文字、图片或按钮,并打开链接控件。
- 输入或选择完整目标;站外链接使用明确的
https://地址。 - 展开高级设置,只为已经批准的链接开启“在新标签页中打开”。
- 在链接可见文字中加入“(在新标签页中打开)”等本地化提示。
- 保存后检查前台最终 HTML;编辑器中的开关不是发布结果的替代证据。
WordPress 只检查地址格式,不保证页面存在或目标可信。发布者仍需核对最终域名、重定向、内容所有者和访问条件。对于导航区块、按钮、图片或第三方区块,设置位置可能不同;如果控件没有此能力,不要用全站 JavaScript 强行补丁。
手写 HTML 时保持意图明确
普通链接不需要 target:
<a href="/help/account">Account help</a>
确有新标签页需求时,使用固定 HTTPS 目标、明确文字和显式 noopener:
<a href="https://example.org/report"
target="_blank"
rel="noopener">Annual report (opens in a new tab)</a>
现代浏览器把带有 target="_blank" 的 <a> 视为隐含 noopener,显式写出仍可记录安全意图并兼顾旧环境。不要用 window.open()、点击处理器或伪链接取代正常 <a href>;它们会破坏复制地址、键盘操作和无脚本降级。
| 值 | 实际含义 | 使用边界 |
|---|---|---|
target="_blank" |
请求新的浏览上下文 | 不保证是标签页还是窗口;必须提前告知用户 |
rel="noopener" |
阻止新上下文通过 window.opener 控制原页面 |
新标签页链接可显式保留;不影响正常 Referer |
rel="noreferrer" |
不发送 Referer,并隐含 noopener |
仅在隐私策略需要时使用;先评估登录、分析和来源归因影响 |
rel="external" |
表明目标位于当前站点之外 | 只是关系语义,不是安全控制,也不会自动新开 |
rel="nofollow" |
表达不希望为目标背书等搜索关系 | 与新标签页和 noopener 无关,不应凭“外链”身份批量添加 |
不要把 noreferrer 当作固定模板,也不要为了统计在 URL 中添加用户标识或跟踪参数。若需要测量链接使用,应先定义合法目的、最小数据、保留期限和退出方式。
让键盘和屏幕阅读器用户预先知道变化
W3C 的 G201 与 H83 技术都强调:链接会打开新窗口或标签页时,应在激活前提供提示。这些技术是实现方式而非唯一的合规路径,但它们解释了真实风险:新上下文可能使“后退”按钮失效,让低视力、屏幕阅读器或认知障碍用户迷失。
- 使用能独立说明目的的链接文字,不用重复的“点击这里”或裸 URL。
- 把“在新标签页中打开”放进可访问名称或用可靠的关联说明提供;不能只有无替代文本的图标。
- 文件链接同时说明格式与合理可知的大小;启动邮件、电话或应用时也要预告。
- 保持正常 Tab 顺序与可见焦点,不给链接添加正数
tabindex。 - 用键盘 Enter、浏览器后退、中键/快捷键和至少一种屏幕阅读器实际测试。
- 不在获得焦点、选择下拉项或页面加载时自动打开新窗口。
图标可以作为视觉补充,但不要假设所有屏幕阅读器会根据 target 自动朗读“新标签页”。提示应由站点内容明确提供,并在各语言版本中保持一致。
外部链接的安全边界
新标签页不会让危险目标变安全。每个发布目标都应通过以下检查:
- 只允许业务明确需要的协议;普通网页目标应是核对过的 HTTPS,不接受
javascript:、data:或用户可控的任意目标。 - 跟随重定向核对最终域名、TLS、登录要求和内容,不以短链文字或外观判断。
- 不把电子邮件、账号、会话令牌或内部记录号放进查询参数。
- 生成 HTML 的主题或插件必须验证 URL,并在输出时使用与上下文匹配的转义;不要拼接未经信任的属性。
- 对下载说明文件类型、大小和来源;不要把可执行文件伪装成普通文档。
- 目标被接管、改变用途、降级到不安全传输或开始要求可疑权限时,立即撤下链接。
定期链接检查应最小化请求,不向目标泄露真实用户资料。健康检查成功也只证明当时可访问,不证明内容持续可信。
由生成链接的组件负责变更
| 链接来源 | 正确所有者 | 安全变更位置 | 不应做的事 |
|---|---|---|---|
| 单篇文章或页面正文 | 内容编辑者 | 对特定链接使用编辑器控件 | 全局重写所有正文链接 |
| 导航、模板、模板部件或同步样板 | 站点设计所有者 | 站点编辑器或受版本控制的子主题 | 修改父主题或用 <base target> |
| 插件生成的表格、目录、评论或按钮 | 插件所有者 | 官方设置、文档化钩子或自有插件 | 正则替换最终 HTML 或修改供应商文件 |
| WordPress 管理界面或核心输出 | WordPress 核心 | 接受上游行为,必要时提交问题或使用受支持扩展点 | 编辑 wp-admin、wp-includes 或核心 PHP |
| 第三方托管/嵌入内容 | 服务所有者与站点负责人 | 审查其配置、沙箱和合同边界 | 假设主题代码能安全控制内部链接 |
WordPress 官方明确不建议修改核心文件;核心更新会覆盖这些更改。父主题更新同样会覆盖直接修改,确需主题级定制时应放在子主题并纳入版本控制。任何管理设置都要有适当权限与请求验证,不能让未授权用户提交任意目标或关系属性。
批量迁移先清点,不要直接替换数据库
历史站点的链接可能存在于区块标记、经典编辑器 HTML、导航、模板、样板、小工具、评论、选项、短代码和插件自有表中。一次正则替换既无法判断真实意图,也可能破坏序列化数据、区块校验和本地化版本。
- 记录 WordPress、主题、插件和 PHP 版本,创建已验证可恢复的文件与数据库备份。
- 在隔离的预发布副本导出链接清单:来源对象、语言、可见文字、目标、当前
target/rel、最终域名和负责人。 - 为每条变更建立明确允许列表和理由;默认保持原状,不用“站外”规则自动决定。
- 由拥有该输出的编辑器、主题或插件接口做小批量变更,保留对象 ID 和前后值。
- 重新解析区块、清缓存,并对每批执行键盘、辅助技术、安全和重定向测试。
- 差异超出允许列表、出现区块无效、目标不明或无法恢复时立即停止并回滚该批。
不要直接在生产数据库运行搜索替换,不要改评论作者链接来操纵其打开方式,也不要让迁移脚本接收任意 url 参数。多语言站点必须分别核对链接提示和目标,不能只改源语言。
测试矩阵与验收证据
| 检查面 | 操作 | 通过条件 |
|---|---|---|
| 编辑器保存 | 切换单个链接后保存并重新打开 | 控件状态与前台 HTML 一致,无区块验证错误 |
| 同标签页 | 普通点击站内和一般外链,再使用后退 | 按预期停留同一上下文,历史记录可用 |
| 新标签页 | 激活批准的特殊链接 | 激活前有可见及可读提示,只产生一个新上下文 |
| 键盘 | 只用 Tab、Shift+Tab 和 Enter | 顺序合理、焦点可见、无键盘陷阱 |
| 屏幕阅读器 | 浏览链接列表并激活样本 | 目的和新上下文提示可理解,重复提示不过量 |
| 安全 | 检查最终 HTML、重定向和新页面 opener | 目标固定为 HTTPS,noopener 意图保留,无敏感查询参数 |
| 响应式与本地化 | 在移动端和每种语言测试 | 文案未截断,提示自然,目标与语言对应 |
| 所有权与更新 | 更新主题/插件并清 CDN/页面缓存 | 变更仍由正确组件生成,没有核心或父主题漂移 |
保存对象 ID、页面 URL、测试日期、浏览器/辅助技术版本和脱敏截图;不要记录登录令牌、个人浏览历史或评论者身份。
回滚与停止条件
单链接回滚是关闭编辑器开关,或只删除该链接的 target 与不再需要的关系值,同时保留经过核对的 href 和文字。组件级回滚应恢复上一版自有插件/子主题和数据库备份,清理缓存后重跑测试;不要以恢复旧核心补丁作为回滚。
出现以下任一情况应停止:没有可恢复备份;无法确定链接由谁生成;批量差异包含允许列表外对象;更新后区块无效;目的或权利不清;重定向到不同域;链接含敏感数据;提示无法被键盘或屏幕阅读器用户理解。安全的临时状态是保持同标签页或暂时移除链接,而不是施加全站补丁。
发布前清单
- 目标地址、最终域名、所有者和发布理由已核对。
- 已记录为什么需要同标签页或新标签页。
- 新标签页链接在可见文字与辅助技术中都有预告。
- HTML 使用真实链接语义,没有脚本伪链接。
noopener、noreferrer、external和nofollow按各自语义决定。- 没有
<base target>、核心/父主题直改或全局 DOM 重写。 - 没有跟踪参数、凭据、账号或内部标识泄漏。
- 键盘、屏幕阅读器、移动端、多语言和缓存场景已测试。
- 备份已验证,变更有负责人、允许列表和逐批回滚记录。
- 链接失效、被接管或行为改变时有撤下流程。
参考资料
- WordPress:链接控件与“在新标签页中打开”设置
- WordPress:编辑文件与避免修改核心文件
- WordPress:子主题与更新安全的定制
- MDN:创建链接与新标签页的设计取舍
- MDN:`rel=”noopener”`
- MDN:`rel=”noreferrer”`
- W3C WAI:G201,打开新窗口前给出提示
- W3C WAI:H83,按用户请求打开并在链接文字中说明
历史原文归档
以下是 source_export 中 2014 年可见正文的完整惰性归档。原文没有行尾空白,也没有需要脱敏的隐私、凭据、推荐或跟踪值,因此没有替换。围栏内的全局 <base>、核心文件编辑和旧 Links Manager 默认值修改均不安全且不可维护,只是历史证据,绝不能执行。
如何让wordpress 在新窗口打开链接?
这个问题开始也一直困扰着我,后来在网上找了找发现有很多的方法,大体上有这么几种:
第一种:wordpress在新窗口打开链接
只要在header.php文件中,标签之间加入以下代码即可:
<base target=”_blank”>
这种方法简单有效,暂时还没有发现什么问题,本博客也是采用的这种方法。
第二种:wordpress在新窗口打开链接
打开wp-admin文件夹,找到admin-header.php文件打开。找到以下代码:
<a href=“<?php echo trailingslashit( get_bloginfo( ‘url’ ) ); ?>” title=“<?php esc_attr_e(‘Visit Site’) ?>” >
在最后一个尖括号”>”前插入target=”_blank”。然后保存该文件。这样,在后台打开前台首页的链接就会在新窗口打开了。
添加之后的代码是:
<a href=“<?php echo trailingslashit( get_bloginfo( ‘url’ ) ); ?>” title=“<?php esc_attr_e(‘Visit Site’) ?>” target=”_blank” >
第三种:留言评论在新窗口打开链接
首页打开wp-includes文件夹,找到comment-template.php文件打开。找到以下代码:
$return = “<a href=’$url’ rel=’external nofollow’ class=’url’>$author</a>”;
在标签中插入一句[target=”_blank”]尖括号中的内容,然后保存。这样,访客昵称所指向的链接就会在新窗口打开了。
添加之后的代码为:
$return = “<a href=’$url’ target=”_blank” rel=’external nofollow’ class=’url’>$author</a>”;
第四种:友情链接在新窗口打开链接
打开wp-admin目录下的includes文件夹,找到meta-boxes.php文件打开。找到以下代码:
<input id=“link_target_blank” type=“radio” name=“link_target” value=“_blank” <?php echo
( isset( $link->link_target ) && ($link->link_target == ‘_blank’) ? ‘checked=“checked”‘ : ”); ?> />
将以上代码修改为:
<input id=“link_target_blank” type=“radio” name=“link_target” value=“_blank” checked=“checked” />
这样就可以了。或者是你在添加友情链接时,在最下面有一些选项,可以直接选在新窗口打开链接的。
