自定义控件需要显式的键盘支持
别名: 自绘控件键盘 · ARIA widget keyboard · 自定义组件焦点
概念解释
浏览器和操作系统只给原生控件配齐键盘行为:button 能被 Tab 选中、空格和回车能激活,select 能用方向键改值。用 div、span、Canvas 或自绘组件冒充这些控件时,外观可以像按钮,键盘行为不会自动出现。这条叫自定义控件的显式键盘支持:角色、焦点和按键处理必须写出来,不能指望样式或补充属性代劳。
给元素加上角色名,不会让它开始响应方向键。补充属性改的是辅助技术怎么称呼它,不给它原本没有的按键行为。
机制
原生控件的键盘行为嵌在用户代理里:焦点可到达、激活键、复合控件内部的方向键,都是平台契约。自绘控件切断了这条契约。开发者若只同步了外观和点击监听,指针通路是通的,键盘通路是断的——元素甚至不在 Tab 序列里,或者在序列里但 Enter 无事发生。
复合控件还有第二层:Tab 只负责进出整件控件,内部选项靠方向键移动,这是漫游 tabindex(roving tabindex)一类模式。漏做内部键位时,用户能「到达」控件却不能在里面挑选,看起来像可达、用起来像死控件。菜单、选项卡、树、网格、日期选择器是重灾区,因为它们的键盘约定比「按一下」长得多。
怎么研究
对照测试:同一交互分别用原生元素和自绘实现,键盘走完选择、改值、取消。记录哪些键被吞掉、焦点是否进入内部、Escape 是否退出。
组合环境:桌面用键盘独占;移动端接外接键盘或系统开关控制,因为触控能点中的自绘控件在接上键盘后往往全部失效。
自动化能查出「可聚焦但没有角色」,查不出「有角色却没有方向键」。后者必须人工按键。
边界
原生元素已经带齐行为时,不要为了换皮再包一层自绘——那是在删除已经存在的键盘契约。画布游戏或可视化里,对象级操纵可以用一套应用内焦点模型,但那套模型必须自己实现到达、激活和离开,且不能把浏览器快捷键全部吞掉。只给阅读器报名字、不处理按键,对视障用户可能「听得到」,对只是没法用鼠标的人仍然不可用。
怎么落地
- 能用原生
button、a、input、select的,不要用div冒充。 - 必须自绘时,同时交付:可聚焦、可见焦点、激活键,以及该角色约定的方向键 / Escape;不要以为补了角色名就算完成。
- 复合控件用漫游 tabindex 或等效模式,让 Tab 只停一次,内部用方向键。
- 验证:键盘打开自定义下拉或日期选择器,改值并取消。只能点选、按键无效,就还没做显式支持。