【问题标题】:Focus outside of visible area聚焦在可见区域之外
【发布时间】:2020-08-24 07:10:42
【问题描述】:

WCAG 声明具有焦点的元素应始终对用户可见。在空间有限的聊天窗口中,如果不是不可能的话,这尤其困难。

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

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

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

另一个选项是将焦点从选定按钮移到输入字段或下一个/新可用按钮列表中的第一个按钮。但我觉得这对于盲人用户来说会删除所有参考点。

您是否可以想到任何其他选项或设计来以易于访问的方式解决此问题?

【问题讨论】:

  • 使用您的反馈并进一步研究焦点可见的示例:SC 2.4.7 焦点不应始终可见。这里的主要挑战是在切换到下一个按钮并向上滚动时迷失方向。正如其中一个答案所述,Slack 有一个我可以使用的可行解决方案。

标签: accessibility user-experience wcag wcag2.0 conversational-ui


【解决方案1】:

不是一个完整的答案

这是一个太大的问题,无法完整回答,需要考虑数百件事,并且仅通过 GIF 来查看我只能概括的行为。

屏幕外焦点

你已经把 WCAG 带到了绝对的字母上,而且有点过分了。这一点的目的是当我改变焦点时,焦点项目在屏幕上可见。

如果我滚动一个网页,您不能指望有焦点的项目会留在页面上(否则,如果页面长度超过屏幕长度,世界上没有任何页面符合要求!)。

只要我聚焦下一个项目,它就会滚动到视图中并且有一个聚焦指示器,我可以看到(正确的对比度,不依赖于颜色)你在这一点上被评为 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 &lt;div&gt; 和 JavaScript 中关注该 div 加载更多内容之前的随附行。

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

div 有tabindex="-1",因此它无法获得焦点。我还在其中添加了aria-hidden="true",并在单击选项按钮时将其关闭,就在赋予它焦点之前。

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

这不是“失败”的WCAG吗?

是的!在此示例中,我将不可聚焦的项目设为可聚焦,但它没有任何操作。我仍然认为这比将其设为&lt;button&gt; 更好,因为这意味着它有一个动作。显然并不完美。

然而,WCAG 的关键部分是“G”——它们是G准则。我建议的方式是“破解”或妥协,因为我对开发时间和技术限制持现实态度。

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

但鉴于您不必只考虑屏幕阅读器的 Tab 键(您可以通过链接、按钮、标题、部分等进行导航),这在尝试拦截击键,所以上面是我能想到的最简单的方法。

替代模式。

因为前面的示例“失败”WCAG,所以还有另一种选择,但我认为这会更糟,并且会带来很多问题。

每次将 div 中的文本替换为新文本。

缺点是您每次都需要提供“上一个项目”按钮并跟踪它们,优点是这将符合 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>

【讨论】:

    【解决方案2】:

    你的例子有点太复杂了。

    让我们来看一个标准的 HTML 页面:如果你用键盘聚焦一个元素,你仍然可以使用鼠标滚动页面(不修改键盘光标),并使元素从视口中消失。这不会使任何 WCAG 标准无效。

    textarea 上按一个字符键将使它再次在视觉上集中。对于按钮或链接,需要 tab 然后 shifttab 才能使按钮可见并再次获得焦点。

    视觉焦点和键盘焦点是两个不同的东西,但如果键盘焦点影响视觉焦点,那并没有相互影响

    您可能遇到的问题不是焦点问题,而是Time limits 的问题。

    1. 如果用户不在窗口底部,则不要滚动,

    2. 如果在最后 N 秒内执行了某个操作,则不要滚动,如果在滚动之前没有执行其他操作,请等待 P 秒。

    3. 如果窗口不滚动,则表明已收到新消息。

    我认为 Slack 很好地实现了“不要滚动并指示新消息”,如果你不在底部的话。

    【讨论】:

      猜你喜欢
      • 2014-08-01
      • 1970-01-01
      • 2011-02-06
      • 2019-05-10
      • 2013-01-31
      • 2021-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多