
本文详解如何在页面加载时,根据 URL 中的 fragment(如 #faq-0)自动展开对应 FAQ 答案项,包括 DOM 定位、样式激活、无障碍属性同步及 Drupal 行为集成要点。
本文详解如何在页面加载时,根据 url 中的 fragment(如 `#faq-0`)自动展开对应 faq 答案项,包括 dom 定位、样式激活、无障碍属性同步及 drupal 行为集成要点。
在构建可访问、用户友好的 FAQ 页面时,支持通过 URL 锚点(fragment identifier)直接定位并展开指定问题的答案,是提升用户体验与 SEO 友好性的关键实践。例如,当用户访问 https://example.com/services/faq#faq-2 时,页面应自动显示 ID 为 faq-2 的答案内容,并同步更新其关联问题项的 aria-expanded 状态,确保符合 WCAG 2.1 标准。
✅ 正确实现逻辑
仅调用 $(hash).show() 通常无效,原因有三:
微信小程序公众号SaaS管理系统是一款完全开源的微信第三方管理系统,为中小企业提供最佳的小程序集中管理解决方案。可实现小程序的快速免审核注册(免300元审核费),可批量发布小程序模板,同步升级版本等功能。基础版本提供商城和扫码点餐两种小程序模板。商户端可以实现小程序页面模块化设计和自动生成小程序源代码并直接发布。
- .show() 会覆盖内联 style,但可能忽略自定义过渡动画;
- 它不设置 data-slide-toggle="true" 等业务所需属性;
- 更重要的是——它不会同步更新对应问题
- 元素的 aria-expanded="true" 和 aria-controls 关系
,导致屏幕阅读器无法正确播报展开状态。
因此,推荐采用显式 CSS 控制 + 属性同步 + 无障碍语义补全的组合方案:
(function ($, Drupal) {
'use strict';
Drupal.behaviors.faqAutoExpand = {
attach: function (context, settings) {
// 在 DOM 就绪后执行(确保 FAQ 元素已渲染)
$(document).ready(function () {
const hash = window.location.hash;
// 验证哈希值是否匹配 FAQ 答案 ID 模式(如 #faq-0, #faq-1...)
if (hash && /^#faq-\d+$/.test(hash)) {
const $answer = $(hash);
if ($answer.length) {
// 1. 强制设置 display: block 与过渡效果(复现 JS 动画行为)
$answer.css({
'display': 'block',
'transition': 'all 300ms ease-in'
}).data('slide-toggle', true);
// 2. 查找并更新对应的问题项:定位 aria-controls 值等于当前 hash 的 <li>
const controlId = hash.substring(1); // 移除 '#' → "faq-0"
const $question = $('li[aria-controls="' + controlId + '"]');
if ($question.length) {
// 同步 aria-expanded="true",并确保 tabindex 可聚焦(增强可访问性)
$question
.attr('aria-expanded', 'true')
.attr('tabindex', '0');
// 可选:滚动到问题项顶部,提升可见性
$question[0].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
}
});
}
};
})(jQuery, Drupal);⚠️ 注意事项与最佳实践
- 执行时机至关重要:务必在 $(document).ready() 或 Drupal 的 attach 回调中执行,避免因 DOM 未加载完成导致元素查找失败;
- 哈希校验不可省略:使用正则 /^#faq-\d+$/ 过滤非法哈希,防止 XSS 风险或 DOM 查询异常;
- 无障碍必须同步:aria-expanded 是 ARIA 必需属性,仅展开内容而不更新该属性将导致屏幕阅读器误读;
- 避免依赖 :target 伪类:虽然 CSS :target { display: block; } 简洁,但它无法触发 JavaScript 动画、设置 data-* 属性或更新 aria-*,且不兼容旧版 IE/部分移动浏览器;
- Drupal 集成提示:若 FAQ 内容由 Views 或 Paragraphs 动态生成,请确保该行为绑定在最外层容器(如 .list--faq)的 context 下,以支持 AJAX 加载后的二次初始化。
✅ 效果验证清单
| 检查项 | 预期结果 |
|---|---|
| 访问 #faq-1 | #faq-1 元素可见,且 display: block + transition 生效 |
| 对应问题项 | aria-controls="faq-1" 的 |
| 键盘导航 | 展开后问题项可被 Tab 聚焦,按 Enter/Space 应可收起(需额外实现 toggle 逻辑) |
| 屏幕阅读器 | 朗读“问题文本,已展开”(依赖正确 aria-expanded 和 role="button" 建议) |
通过以上方案,你不仅实现了锚点驱动的 FAQ 展开功能,更保障了功能的鲁棒性、可访问性与框架兼容性,为用户提供一致、可靠、符合标准的交互体验。









