焦点在可见区域之外

问题描述 投票:1回答:1

WCAG指出具有焦点的元素应始终对用户可见。在空间有限的聊天窗口中,即使不是没有可能,这也特别困难。

[当键盘或屏幕阅读器用户使用Tab键选择第一个按钮选项时,内容滚动且按钮不再可见,从而打破了“始终可见焦点” WCAG规则。同样,如果列表中有多个按钮,则焦点将停留在该按钮上,并且如果它们继续进行制表,则窗口将滚动到设置焦点的位置。这令人迷惑,并且可以争辩说,选择按钮时其他选项不相关,因为现在可以使用新选项。

示例:https://recordit.co/2jDDvqg98J

一种选择是在到达按钮时停止滚动,以使按钮可见。但是我觉得这不是很好的经验,也不是遵守WCAG规则的妥协。我进行了一些研究,所有对话UI均无一例外地在聊天中打印新内容时滚动到底部。如果我以上述方式偏离以保持在WCAG之内,那么我将破坏Jakobs Law.

另一个选项是将焦点从所选按钮移至输入字段或下一个/新的可用按钮列表中的第一个按钮。但是我认为这将为盲人用户消除所有参考点。

您是否可以想到其他任何选项或设计来解决此问题?

accessibility user-experience wcag wcag2.0 conversational-ui
1个回答
0
投票

不是完整答案

这是一个太大的问题,无法完全回答,有数百个问题需要考虑,只有一个GIF才能看到我只能概括的行为。

焦点不在屏幕上

您已将WCAG带到绝对字母,但距离太远了。这一点的目的是,当我change聚焦时,聚焦的项目在屏幕上可见。

如果滚动网页,您将无法期望焦点的项目停留在该页面上(否则,如果世界上的任何页面都超过屏幕长度,则该页面将不符合要求!]

只要我关注下一个项目,它就会滚动到视图中并且具有焦点指示器,我可以看到(正确的对比度,而不取决于颜色),您在这一点上的等级为WCAG AAA!

自动滚动内容

这是事情变得“模糊”的地方。在您的示例中,内容已添加到聊天框中,因此当前关注的项目从屏幕上滚动出来。

现在,如果我们将焦点移到最新选项(出现的按钮),我们会遇到一个问题,即它可能会中断屏幕阅读器的运行,因此他们无法听到所有先前的信息,因此必须返回并再次收听。

[如果我们不移动焦点,则您遇到的问题是您在我按Tab时所描述的(例如),并且页面跳回到了我刚才收听的内容之前。

假设我们没有其他选择,这仍然是更好的选择(不是集中精力,但是我们确实有选择。)>

一些解决方法的时间。

这是可访问性的乐趣所在,由于这里没有确定的模式,我们需要找到一些解决方法。

我会争辩说,这里最大的问题是一旦说出新文本,当我们按下Tab

或其他焦点快捷键时,我们会跳回到页面顶部。

一个解决方法是创建一个特殊的div,第二个我选择一个选项时将其聚焦。

此div应该有tabindex="-1",所以不能通过键盘访问(只能通过编程方式访问。)>

第二个我选择一个选项,我们将重点放在此div上,然后开始插入文本。

这样,当我按下<kbd>Tab</kbd>或下一个按钮的快捷方式时,它将跳到第一个新选项。

我在下面创建了一个基本的小提琴,它需要进行一些改进,但是为您提供了一种测试/使用的模式。

var hasLoadedMore = 0;
$('.loadMore').on('click', function(e){
    if(hasLoadedMore == 0){ //just a horrible hack to simluate content only loading once when you click an option.
    console.log("option chosen");
    $('#focusAdjuster').attr('aria-hidden', false);
    $('#focusAdjuster').focus();
    console.log("focus adjusted");
    loadContent();
    }
});   



function loadContent(){
    ///ugly way of simulating the content being added dynamically.
    $('#chat').append('<p>additional text</p>');
    $('#chat').append('<p>more text</p>');
    setTimeout(function(){
    $('#chat').append('<p>more text</p>');
    $('#chat').append('<button>Option 1 new</button>');
    $('#chat').append('<button>Option 2 new</button>');
    }, 500);
    hasLoadedMore = 1;
}
.visually-hidden { 
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
    white-space: nowrap; /* added line */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chat">
<p>initial text</p>
<button class="loadMore">Option 1</button>
<button class="loadMore">Option 2</button>
<button class="loadMore">Option 3</button>
<div tabindex="-1" aria-hidden="true" id="focusAdjuster" class="visually-hidden">loading</div>
</div>

小提琴的解释

因此,它们的关键点是visually-hidden <div>以及JavaScript中用于突出显示div的伴随行之前

加载更多内容。

div让我们在单击按钮后更改焦点。我还向该div中的文本添加了“加载”功能,以增加其他用途,因为您的应用程序将使用AJAX技术。

div具有tabindex="-1",因此无法获得焦点。我还添加了aria-hidden="true"并在单击选项按钮时将其切换为关闭状态,就在将其聚焦之前。

当焦点离开现实世界中的这个div时,我会切换回去,但我并没有在快速的演示小提琴中这样做。

这不是“失败”的WCAG吗?

是的!在此示例中,我使不可聚焦的项目可聚焦,并且没有任何动作。我仍然认为这比将其设置为<button>更可取,因为这意味着它可以执行操作。显然这并不完美。

但是WCAG的关键部分是'G

'-它们是G准则。基于我对开发时间和技术局限性的看法,我建议的方式是“ hack”或妥协。

您可以在没有div的情况下完成上述操作的“正确”方法是进行一些仔细的焦点管理。有了无限的时间和预算,我一定会做到的。

但是考虑到您不必只用屏幕阅读器来考虑Tab

键(您可以通过链接,按钮,标题,部分等进行导航),当尝试截取按键和因此,以上是我可以想到的最简单的方法。

替代模式。

因为前面的示例“失败”了WCAG,所以还有另一种选择,但是我认为这更糟,并引入了许多问题。

每次用新文本替换div中的文本。

缺点是您每次都需要提供'previous item'按钮并进行跟踪,其好处是这符合WCAG(尽管我认为即使您'通过'该标准也不太实用)。

还提供那些“上一个”按钮再次在焦点管理中引入了许多问题(当我们使它们可见时,它们是否获得焦点,它们是否会增加混乱?)。>

像表单向导模式那样思考,每组问题都是一个“步骤”,因此您可以返回上一步,并且只能在屏幕上看到当前步骤。

我加入了此模式,因为可以通过一些思考来扩展此模式,并向OP /其他人提供一些想法,请不要按原样使用它]]] >>

var hasLoadedMore = 0;
var optionChosen = "";
$('.loadMore').on('click', function(e){
    if(hasLoadedMore == 0){ //just a horrible hack to simluate content only loading once when you click an option.
    optionChosen = $(this).text();
    console.log("option chosen", optionChosen);
    loadContent();
    }
});   




function loadContent(){
    
    $('#chat').html('<button class="previousQuestion">You chose ' + optionChosen + '<span class="visually-hidden">(click here to go back and chose a different option)</span></button>');
    $('#chat').append('<h3>' + optionChosen + '</h3>');
    ///ugly way of simulating the content being added dynamically.
    $('#chat').append('<p>additional text</p>');
    $('#chat').append('<p>more text</p>');
    setTimeout(function(){
    $('#chat').append('<p>more text</p>');
    $('#chat').append('<button>Option 1 new</button>');
    $('#chat').append('<button>Option 2 new</button>');
    }, 500);
    hasLoadedMore = 1;
    
    
$('.previousQuestion').on('click', function(){
    console.log("now you would restore the previous question");
});   

    
}
.visually-hidden { 
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
    white-space: nowrap; /* added line */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chat">
<p>initial text</p>
<button class="loadMore">Option 1</button>
<button class="loadMore">Option 2</button>
<button class="loadMore">Option 3</button>
<div tabindex="-1" aria-hidden="true" id="focusAdjuster" class="visually-hidden">loading</div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.