微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正确隐藏键盘和屏幕阅读器中的内容 在皮革上实现动画的最佳方法是什么?一个粗略的示例,说明隐藏项目以管理tabindex并在再次显示时恢复tabindex的情况

如何解决正确隐藏键盘和屏幕阅读器中的内容 在皮革上实现动画的最佳方法是什么?一个粗略的示例,说明隐藏项目以管理tabindex并在再次显示时恢复tabindex的情况

我们在页面上有一个模式,在隐藏时,我们不想键盘用户能够跳到内容中,也不想让屏幕阅读器阅读。

解决这个问题,我在父DIV上进行了设置,以便在隐藏时具有以下内容

<div aria-hidden="true" tabindex="-1">
    [child HTML/content]
<div>

不幸的是,这不起作用。您仍然可以使用Tab键浏览内容,然后读取内容(至少通过Chrome和使用VoiceOver)。

想法,我们还可以设置display: none,我可以做到这一点,但是目前我们依赖某些CSS过渡动画,因此需要在动画之后以编程方式进行设置。 / p>

但是,在走这条路线之前,我对aria-hidden和tabindex应该解决这个问题的初衷尚不了解吗?

解决方法

如果无法实现由Graham Ritchie提早提供的解决方案,则需要确保:

    模态
  1. 所有可聚焦的子代在模态被隐藏时收到tabindex="-1"
  2. aria-hidden均已从父级中移除(设置为false),所有这些可聚焦子级均已移除tabindex

注意:避免为tabindex(即tabindex="1")使用正值,因为它会干扰页面的焦点顺序(通常遵循页面的焦点顺序) DOM,并且应遵循页面的阅读顺序)。最好的做法是只使用tabindex="0"来按自然焦点顺序添加元素,而使用tabindex="-1"从焦点顺序中删除元素(但仍然可以在其上使用JavaScript .focus()方法,如果需要)。

,

简短答案

在不进行过渡的情况下使用display:none是最佳选择,并且不需要aria-hidden

如果需要进行转换,请进行转换,然后在转换后设置display: none属性。

尽管过渡时间超过100毫秒,但请注意不要丢失焦点,您必须进行大量的焦点管理才能解决设置display:none的延迟。

更长的答案

aria-hidden="true"从可访问性树中删除项目及其子项。但是,这不会阻止能够获得焦点(即<input>)的孩子获得焦点。

tabindex="-1"不会从已经可以聚焦的子元素中移除焦点。

解决所有问题的最简单方法是删除过渡并只需切换display属性。这不仅解决了您的重点问题,而且消除了对aria-hidden的需求,使事情变得更简单。

话虽如此,过渡可能是您的规格之一,并且是不可避免的。如果是这种情况,则需要考虑一些事项。

在我们的评论讨论中以及您的问题中,您提到使用setTimeout将转换完成后的display属性设置为none。

这种方法取决于您的设计。

如果下一个制表位在要隐藏的区域内,则在过渡期间有人可以导航到要隐藏的区域内的元素是可行的。

如果发生这种情况,将失去对页面的关注。根据浏览器的不同,这可能导致焦点返回到页面顶部。在WCAG原则的逻辑制表符顺序/鲁棒性下,这将是非常令人沮丧的事情,并且也可能构成失败。

在皮革上实现动画的最佳方法是什么?

由于存在焦点问题,我建议采用以下过程来隐藏带有过渡的内容:-

  1. 第二个导致隐藏区域的按钮/代码被激活(淡出),在tabindex="-1"中所有要隐藏的交互式元素上设置了<div>(或者如果它们是设置disabled属性的输入)。
  2. 通过任何使用方式开始转换(即,将类添加到将触发转换的项目中)。
  3. 转换完成后,在项目上设置display: none
  4. 如果希望再次显示<div>,请执行相反的操作。

这样做可以确保没有人会偶然进入div并失去焦点。这可以帮助所有依靠键盘进行导航的人,而不仅仅是屏幕阅读器用户。

下面是一个如何实现此目标的非常粗糙的示例。可以根据容器的ID对其进行重用,因此希望可以为您提供一个好的起点,以便编写更加健壮(并且不那么丑陋!呵呵)的东西

我添加了评论以尽我所能解释。我已将过渡设置为2秒,因此您可以检查并查看事物的顺序。

最后,我加入了一些CSS和JS来说明那些表示由于运动敏感性而喜欢减少运动的人。在这种情况下,动画时间设置为0。

一个粗略的示例,说明隐藏项目以管理tabindex并在再次显示时恢复tabindex的情况。

var content = document.getElementById('contentDiv');
var btn = document.getElementById('btn_toggle');
var animationDelay = 2000;

//We should account for people with vestibular motion disorders etc. if they have indicated they prefer reduced motion. We set the animation time to 0 seconds.
var motionQuery = matchMedia('(prefers-reduced-motion)');
function handleReduceMotionChanged() {
  if (motionQuery.matches) {
    animationDelay = 0;
  } else { 
    animationDelay = 2000;
  }
}
motionQuery.addListener(handleReduceMotionChanged);
handleReduceMotionChanged();



//the main function for setting the tabindex to -1 for all children of a parent with given ID (and reversing the process)
function hideOrShowAllInteractiveItems(parentDivID){  
  //a list of selectors for all focusable elements.
  var focusableItems = ['a[href]','area[href]','input:not([disabled])','select:not([disabled])','textarea:not([disabled])','button:not([disabled])','[tabindex]:not([disabled])','[contenteditable=true]:not([disabled])'];
  
  //build a query string that targets the parent div ID and all children elements that are in our focusable items list.
  var queryString = "";
  for (i = 0,leni = focusableItems.length; i < leni; i++) {
    queryString += "#" + parentDivID + " " + focusableItems[i] + ",";
  }
  queryString = queryString.replace(/,\s*$/,"");
      
  var focusableElements = document.querySelectorAll(queryString);      
  for (j = 0,lenj = focusableElements.length; j < lenj; j++) {
            
    var el = focusableElements[j];
    if(!el.hasAttribute('data-modified')){ // we use the 'data-modified' attribute to track all items that we have applied a tabindex to (as we can't use tabindex itself).
            
      // we haven't modified this element so we grab the tabindex if it has one and store it for use later when we want to restore.
      if(el.hasAttribute('tabindex')){
        el.setAttribute('data-oldTabIndex',el.getAttribute('tabindex'));
      }
              
      el.setAttribute('data-modified',true);
      el.setAttribute('tabindex','-1'); // add `tabindex="-1"` to all items to remove them from the focus order.
              
    }else{
      //we have modified this item so we want to revert it back to the original state it was in.
      el.removeAttribute('tabindex');
      if(el.hasAttribute('data-oldtabindex')){
        el.setAttribute('tabindex',el.getAttribute('data-oldtabindex'));
        el.removeAttribute('data-oldtabindex');
      }
      el.removeAttribute('data-modified');
    }
  }
}



btn.addEventListener('click',function(){
  contentDiv.className = contentDiv.className !== 'show' ? 'show' : 'hide';
  if (contentDiv.className === 'show') {
     content.setAttribute('aria-hidden',false);
    setTimeout(function(){
      contentDiv.style.display = 'block';
      hideOrShowAllInteractiveItems('contentDiv');
    },0); 
  }
  if (contentDiv.className === 'hide') {
      content.setAttribute('aria-hidden',true);
      hideOrShowAllInteractiveItems('contentDiv');
    setTimeout(function(){
      contentDiv.style.display = 'none';
    },animationDelay); //using the animation delay set based on the users preferences.
  }
});
@keyframes in {
  0% { transform: scale(0); opacity: 0; visibility: hidden;  }
  100% { transform: scale(1); opacity: 1; visibility: visible; }
}

@keyframes out {
  0% { transform: scale(1); opacity: 1; visibility: visible; }
  100% { transform: scale(0); opacity: 0; visibility: hidden;  }
}

#contentDiv {
  background: grey;
  color: white;
  padding: 16px;
  margin-bottom: 10px;
}

#contentDiv.show {
  animation: in 2s ease both;
}

#contentDiv.hide {
  animation: out 2s ease both;
}


/*****We should account for people with vestibular motion disorders etc. if they have indicated they prefer reduced motion. ***/
@media (prefers-reduced-motion) {
  #contentDiv.show,#contentDiv.hide{
    animation: none;
  }
}
<div id="contentDiv" class="show">
  <p>Some information to be hidden</p>
  <input />
  <button>a button</button>
  <button tabindex="1">a button with a positive tabindex that needs restoring</button>
</div>

<button id="btn_toggle"> Hide Div </button>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?