ARIA输入字段无可用名称问题排查与解决求助
解决ARIA输入字段无访问名称的问题
问题重现
测试网站时,这两个select字段一直报「ARIA输入字段没有可访问名称」的错误。试过给select加display:none的label(带for关联),但没用。排查后发现问题大概率出在jquery-ui.js里的_drawButton方法。
原HTML代码:
<div class="form-group col-lg-3 col-md-6 col-sm-12"> <select class="custom-select-box select2 " name="mainCatID" id="category"> <option value="">@lang('language.HEADING_SELECT_CATEGORY')</option> @foreach ($RecipeMainCategory as $val) <option value="{{ base64_encode(base64_encode($val->id)) }}"> {{ $val->category_name }}</option> @endforeach </select> </div> <div class="form-group col-lg-3 col-md-6 col-sm-12"> <select class="custom-select-box select2 " name="subCatID" id="sub_category"> <option value="">@lang('language.HEADING_SELECT_SUB_CATEGORY')</option> @foreach ($RecipeSubCategory as $val) <option value="{{ base64_encode(base64_encode($val->id)) }}"> {{ $val->category_name }}</option> @endforeach </select> </div>
怀疑有问题的jquery-ui.js代码段:
_drawButton: function() { var that = this; // Associate existing label with the new button this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button ); this._on( this.label, { click: function( event ) { this.button.focus(); event.preventDefault(); } }); // Hide original select element this.element.hide(); // Create button this.button = $( "<span>", { "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all", tabindex: this.options.disabled ? -1 : 0, id: this.ids.button, role: "combobox", "aria-expanded": "false", "aria-autocomplete": "list", "aria-owns": this.ids.menu, "aria-haspopup": "true" }) .insertAfter( this.element ); $( "<span>", { "class": "ui-icon " + this.options.icons.button }) .prependTo( this.button ); this.buttonText = $( "<span>", { "class": "ui-selectmenu-text" }) .appendTo( this.button ); this._setText( this.buttonText, this.element.find( "option:selected" ).text() ); this._resizeButton(); this._on( this.button, this._buttonEvents ); this.button.one( "focusin", function() { // Delay rendering the menu items until the button receives focus. // The menu may have already been rendered via a programmatic open. if ( !that.menuItems ) { that._refreshMenu(); } }); this._hoverable( this.button ); this._focusable( this.button ); },
修复方法
1. 换一种隐藏label的方式
别用display:none,屏幕阅读器经常会忽略这种元素。改用视觉隐藏但仍能被辅助技术识别的样式:
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0; }
然后给每个select加上对应的label:
<div class="form-group col-lg-3 col-md-6 col-sm-12"> <label for="category" class="sr-only">选择主分类</label> <select class="custom-select-box select2" name="mainCatID" id="category"> <!-- 选项内容不变 --> </select> </div> <div class="form-group col-lg-3 col-md-6 col-sm-12"> <label for="sub_category" class="sr-only">选择子分类</label> <select class="custom-select-box select2" name="subCatID" id="sub_category"> <!-- 选项内容不变 --> </select> </div>
2. 修改jquery-ui的_drawButton方法
原代码只把label的for属性改成了生成的按钮ID,但没给按钮加aria-labelledby关联,导致屏幕阅读器找不到名称。修改代码如下:
_drawButton: function() { var that = this; // Associate existing label with the new button this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button ); this._on( this.label, { click: function( event ) { this.button.focus(); event.preventDefault(); } }); // Hide original select element this.element.hide(); // 新增:给label加个唯一ID(如果没有的话) let labelId = this.label.attr('id') || `ui-label-${this.ids.button}`; if (!this.label.attr('id')) { this.label.attr('id', labelId); } // Create button - 新增aria-labelledby关联label的ID this.button = $( "<span>", { "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all", tabindex: this.options.disabled ? -1 : 0, id: this.ids.button, role: "combobox", "aria-expanded": "false", "aria-autocomplete": "list", "aria-owns": this.ids.menu, "aria-haspopup": "true", "aria-labelledby": labelId // 关键:关联label的ID }) .insertAfter( this.element ); $( "<span>", { "class": "ui-icon " + this.options.icons.button }) .prependTo( this.button ); this.buttonText = $( "<span>", { "class": "ui-selectmenu-text" }) .appendTo( this.button ); this._setText( this.buttonText, this.element.find( "option:selected" ).text() ); this._resizeButton(); this._on( this.button, this._buttonEvents ); this.button.one( "focusin", function() { if ( !that.menuItems ) { that._refreshMenu(); } }); this._hoverable( this.button ); this._focusable( this.button ); },
3. 快速备选方案:直接加aria-label
如果不想折腾label,也可以在生成按钮时直接指定aria-label,用select的默认选项文本当标签:
this.button = $( "<span>", { // 其他属性不变 "aria-label": this.element.find("option:first").text() })
内容的提问来源于stack exchange,提问作者Evolution-Team
相关产品推荐
相关产品推荐

