一些最佳实践分享
Tillreetree (99) 开发者 管理团队 4小时前

也许这些东西别人已经在其他地方(包括但不限于知乎、稀土掘金、博客园、CSDN等)讲过了,但似乎没有人在xiuno bbs里实施。

图标使用的无障碍规范

  • 在使用font awesome或任何图标库的时候,请仔细阅读图标库的文档。
  • 他们通常会要求类似这样的使用方法:<i class="fas fa-star" aria-hidden="true"></i> <span class="sr-only">收藏此主题</span>来满足可访问性要求
    • aria-hidden="true":确保图标不会被屏幕阅读器读出
    • sr-only 辅助文本:提供仅对屏幕阅读器可见的文字说明。可复用 Bootstrap 的 visually-hidden 类。
  • 如果你的图标有状态(如"已点赞"),请动态更新辅助文本: <i class="fas fa-heart" aria-hidden="true"></i> <span class="sr-only">取消点赞</span>

图片优化与无障碍

  • 写img标签的时候请务必带上:
    • alt:这是必须填写的属性,不再是可选项
      • 内容应描述图像本身,而非功能
      • 对于纯装饰性图片,使用 alt="" 明确告知屏幕阅读器忽略。
    • loading="lazy":这是浏览器为你提供的"懒加载"
      • 视频、iframe 也应设置 loading="lazy"
    • decoding="async":用于告诉浏览器"这张图不紧急,请异步解析,别阻塞页面渲染",特别适合包含大量图片的论坛页面。
  • 例如:<img src="avatar.png" alt="用户'七濑胡桃'的头像" loading="lazy" decoding="async" />

语义化HTML与ARIA角色

  • 在使用语义化HTML标签的同时,也要使用role属性来做无障碍(Bootstrap文档里给出的例子就是最好的)
  • 使用正确的HTML5语义化标签(如<nav>, <main>, <aside>等)
  • 通过role属性补充说明元素的用途,增强无障碍支持
  • 为自定义交互组件添加适当的ARIA属性
<nav role="navigation" aria-label="主导航"></nav>
<main role="main"></main>
<aside role="complementary"></aside>

<!-- 模态框 -->
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
    <h5 id="modal-title">确认删除</h5>
    ...
</div>

<!-- 警告提示 -->
<div class="alert alert-warning" role="alert">您的账户即将过期。</div>

<!-- 加载状态 -->
<div role="status" aria-live="polite">
    <span class="spinner-border"></span> 加载中...
</div>

表单无障碍设计

  • 每个表单控件都应有对应的label
  • 使用aria-describedby关联帮助文本
  • 单独的这个带ID的元素也利好HTMX的hx-swap-oob,这样当用户名有误的时候直接替换该元素即可达到显示错误信息的效果
<label for="username">用户名</label>
<input id="username" type="text" aria-describedby="username-help">
<div id="username-help" class="help-text">请输入您的用户名</div>

交互按钮的无障碍优化

<button 
    type="button" 
    class="btn btn-danger" 
    hx-delete="/post/123" 
    hx-confirm="确定要删除这篇回复吗?"
    hx-target="#post-123"
    hx-swap="outerHTML swap:1s"
    role="alertdialog"
    aria-labelledby="confirm-title"
    aria-describedby="confirm-desc">
    <i class="fas fa-trash" aria-hidden="true"></i>
    <span class="sr-only">删除回复</span>
</button>

<!-- 可选:隐藏的标题和描述 -->
<div id="confirm-title" class="sr-only">确认删除</div>
<div id="confirm-desc" class="sr-only">此操作无法撤销。</div>

这些实践虽然看起来繁琐,但对于构建一个真正包容、所有人都能使用的网站至关重要。

响应式与触控友好:为所有人设计

触摸友好的交互尺寸

  • 一个重要原则: 尽量不要认为用户和你一样:
    • 视力正常,或者戴了眼镜之后视力正常(据《全球近视报告》统计,中国成年人近视患病率约48.5%)
    • 没有色盲情况(中国色盲患者总数约占全国总人口的3%-5%)
    • 可以正常操控自己的手指和手腕(根据中国残联2021年数据,全国肢体残疾人数占总人口1.8%)
  • 最小点击区域 ≥ 44px × 44px (WCAG标准)
    • 使用正常的btn即可基本满足这个要求
    • 移动端手指操作的基本保障
  • 避免将功能按钮做得太小,文字也尽量不要太小
    • 不要为了视觉上的美观而用 small class,除非有合理的原因
    • 一些知名网站的参考值大约是14到16px
      • 据我所知,百度搜索13px,阿里系14px(阿里系不仅有Ant Design的因素),知乎15px,搜狐、B站、IT之家、DeepSeek、通义千问、文心一言、元宝等16px,百度百家号19px

非悬停依赖的交互设计

  • 避免只能用悬停的交互(例如不要把重要信息放在tooltip里,而tooltip本身的地位和title属性一样高,只是好看一些而已)
  • 如下拉菜单,必须能通过点击或 Tab 键激活
  • 使用 :focus-within 替代纯 CSS hover,例如可以写fieldset:hover,fieldset:focus-within { border-color: var(--primary) }

视觉可访问性

  • 提供足够的颜色对比度
  • 对于设计主题的人来说,文字与背景对比度至少 4.5:1(WCAG AA 标准)

语义化的按钮层次

  • 对于插件开发者来说,尽可能使用语义化的按钮class
  • 例如,页面里有两个主要操作按钮,和一个危险按钮,和四个次要操作按钮,那么:
    • 主要操作按钮(添加、保存)使用 btn-primary 来抓住用户注意力
    • 危险操作按钮(删除)使用 btn-danger 来警醒用户
    • 其他按钮可以使用 btn-secondarybtn-outline-primarybtn-outline-secondarybtn-link,弱化这些按钮的存在感
  • 这样用户才不会觉得晕头转向
<button class="btn btn-primary">发布帖子</button>
<button class="btn btn-primary">保存草稿</button>
<button class="btn btn-danger">删除草稿</button>
<button class="btn btn-secondary">预览</button>
<button class="btn btn-outline-secondary">添加标签</button>
<button class="btn btn-outline-secondary">上传附件</button>
<button class="btn btn-link">格式化帮助</button>

在这部分我说一个反例。这还是个知名的主题:

 

/* 字体尺寸过小且缺乏层次 */
body { font-size: 14px; } /* 但基础字号却似乎不是14px,请继续看 */

h1 { font-size: 35px; }    /* 2.5rem */
h2 { font-size: 28px; }    /* 2rem */
h3 { font-size: 24.5px; }  /* 1.75rem */
h4 { font-size: 21px; }    /* 1.55rem */
h5 { font-size: 17.5px; }  /* 1.25rem */
h6 { font-size: 14px; }    /* 1rem - 与正文相同 */

.lead { font-size: 17.5px; } /* 1.25rem - 和H5一样 */
.small, .card-body { font-size: 12.25px; } /* 0.875em - 难以阅读,但就是这个字号却被当作了普遍使用的字号! */
.card-body .small { font-size: 10px; } /* 0.875em - 在一些情况下,插件作者为了自己的需要会单独使用small,并假设正常字体大小是14px,导致两个小字号叠加,变得更小,完全不可接受! */

.blockquote { font-size: 11.2px; } /* 0.8em - 引用文字比小字还小! */
.blockquote cite { font-size: 9.8px; } /* 0.875em - 几乎无法辨认 */

/* 按钮尺寸违反触摸友好原则 */
.button {
    font-size: 12.25px; /* 0.875rem - 文字过小 */
    padding: 5.25px 10.5px;       
    /* 
    点击区域的高度太小:13.469px(文字本身+行间距)+ 5.25px(上内间距) + 5.25px(下内间距) = 23.969px(总高度) 
    作为对比:
    - 原装 Bootstrap 按钮高度是:21px(文字本身+行间距) + 5.25px(上内间距) + 5.25px(下内间距) = 31.5px(总高度) 
    - Stately主题的按钮高度是:22.938px(文字本身+行间距) + 7px(上内间距) + 7px(下内间距) = 36.938px(总高度);Stately会在移动端缩减左右间距但不会缩减上下间距来保证可点击性
    - WCAG标准要求的最小触摸目标:44px
    */
}

/* 组件内部字体似乎直接以12px为基准 */
.metric-number { font-size: 12px; }
.metric-label { font-size: 11px; }
.card-header { font-size: 14px; }
.card-body { font-size: 12.25px; }

这个反例告诉我们:美观不应以牺牲可访问性为代价。即使是最受欢迎的主题,如果忽视了基本的使用性准则,也会给大量用户带来使用障碍。插件开发者基于主题的错误假设进行开发时,问题会像雪球一样越滚越大。

最新回复 (1)
广告推荐
Tillreetree
开发者 管理团队
广告推荐