CSS 翻盖卡:如何通过选项卡激活翻盖,使其可以通过键盘访问?

CSS flip card: How can I activate the flip via tab, so it is keyboard accessible?

我发现了一些关于如何使用 CSS 制作翻转卡片的很棒的教程。不过,我的问题是如何使此键盘易于访问。换句话说,对于只使用键盘的残障用户,希望他们能够只使用选项卡按钮(从而获得焦点),并且卡片将翻转以显示背面内容并允许使用 Tab 键 select link 卡片背面。

我用谷歌搜索并找到了一些建议(请参阅下面我尝试过的 jsfiddle),但我没有成功。

这是一个具有此功能的很棒的网站,但我不知道他们是如何让它工作的: https://businessexpress.maryland.gov/

请注意,如果您在上面的页面上按住 Tab 键,最终您的卡片会翻转,然后您可以通过 Tab 键浏览卡片上的 link。例如,对于第一张翻转卡,有一个link“/plan”,然后它有子links,如“/plan/create-business-plan”等

请注意,我试图在第 21 行添加一些 CSS,这会影响 "active" 和 "focus" 伪 类。但只有悬停会使卡片翻转。我希望在任何 link 上按 Tab 键都能翻转卡片,就像上面的 maryland.gov 示例一样。

我在这里包含了一个 jsfiddle(有一个小输入元素,因此您可以从中开始使用 Tab 键): https://jsfiddle.net/anrbhcmv/

HTML:

    <div id="content">
        <h1>Small Business Resources</h1>

    <input type="text">
    <br><br>

        <div class="flip-card">
            <div class="flip-card-inner">
                <a href="#" id="flip-card-inner">
                    <div class="flip-card-front">
                        <div>Card-front content</div>
                    </div>
                </a>
                <div class="flip-card-back">
                    <a href="https://www.google.com">Google</a>
                    <div>Text</div>
                </div>
            </div>
        </div>

    </div><!-- end #content -->

CSS:

/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
    background-color: transparent;
    width: 300px;
    height: 200px;
    // border: 1px solid #f1f1f1;
    // perspective: 1000px; /* Remove this if you don't want the 3D effect */
}

/* This container is needed to position the front and back side */
.flip-card-inner {
    position: relative;
    width: 100%;
    height: 100%;
    text-align: center;
    transition: transform 0.8s;
    transform-style: preserve-3d;
}

/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner, .flip-card:active .flip-card-inner, .flip-card:focus .flip-card-inner{
    transform: rotateY(180deg);
}

/* Position the front and back side */
.flip-card-front, .flip-card-back {
    position: absolute;
    width: 100%;
    height: 100%;
    -webkit-backface-visibility: hidden; /* Safari */
    backface-visibility: hidden;
}

/* Style the front side (fallback if image is missing) */
.flip-card-front {
    background-color: #008CCC;
    background-color: azure;
    color: white;
    color: black;
}

/* Style the back side */
.flip-card-back {
    background-color: #99CC66;
    color: white;
    transform: rotateY(180deg);
}

您可以使用 :focus-within pseudo-class:

.flip-card:focus-within .flip-card-inner

/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */

.flip-card {
  background-color: transparent;
  width: 300px;
  height: 200px;
  // border: 1px solid #f1f1f1;
  // perspective: 1000px; /* Remove this if you don't want the 3D effect */
}


/* This container is needed to position the front and back side */

.flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: center;
  transition: transform 0.8s;
  transform-style: preserve-3d;
}


/* Do an horizontal flip when you move the mouse over the flip box container */

.flip-card:hover .flip-card-inner,
.flip-card:focus-within .flip-card-inner,
.flip-card:active .flip-card-inner,
.flip-card:focus .flip-card-inner {
  transform: rotateY(180deg);
}


/* Position the front and back side */

.flip-card-front,
.flip-card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  /* Safari */
  backface-visibility: hidden;
}


/* Style the front side (fallback if image is missing) */

.flip-card-front {
  background-color: #008CCC;
  background-color: azure;
  color: white;
  color: black;
}


/* Style the back side */

.flip-card-back {
  background-color: #99CC66;
  color: white;
  transform: rotateY(180deg);
}
<div id="content">
  <h1>Small Business Resources</h1>

  <input type="text">
  <br><br>

  <div class="flip-card">
    <div class="flip-card-inner">
      <a href="#" id="flip-card-inner">
        <div class="flip-card-front">
          <div>Card-front content</div>
        </div>
      </a>
      <div class="flip-card-back">
        <a href="https://www.google.com">Google</a>
        <div>Text</div>
      </div>
    </div>
  </div>

</div>
<!-- end #content -->

请不要只按照建议使用 focus-within(*)。

它有no support in Internet Explorer,这是一个大问题,因为这个问题被标记为“可访问性”。

虽然 Internet Explorer 支持通常不会成为问题,但 around 11% of screen reader users use IE 11 and a further 1.5% use IE 9 and 10.

另请注意 around 25% of screen reader users are not blind. 因此确保视觉体验与屏幕相匹配 reader 体验也很重要(如果您想知道为什么卡在屏幕上旋转很重要 reader 用户。)

下面是一个非常粗略的变通办法,它应该相当灵活,它确实依赖于 具有唯一 class 的父项,但是如果你有很多这样的东西,可以很容易地修复,这只是一个让你入门的例子。

下面的代码应该一直兼容到 IE9(请检查我可能犯了一个小错误),将你的浏览器覆盖率从 89% 提高到 97% 左右,提高了 10%。

CSS - 请同时检查对 CSS 的调整,我添加了两个单独的项目,一个是 .flip-card.focus-within .flip-card-inner 选择器class 我们添加到父级以执行旋转。

另一个是 @media (prefers-reduced-motion) 如果用户将他们的用户设置设置为 'reduced animation' 则关闭旋转动画,这是另一个辅助功能改进。

我并不经常提倡 JavaScript 解决方案而不是 CSS 解决方案,但在这种情况下,恐怕我们仍然受到旧浏览器的限制。

function addListeners(parentClass){
    var focusableItems = ['a[href]', 'area[href]', 'input:not([disabled])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', '[tabindex="0"]'];
    for (i = 0, leni = focusableItems.length; i < leni; i++) {
        var focusableElements = document.querySelectorAll("." + parentClass + " " + focusableItems[i]);
        for (j = 0, lenj = focusableElements.length; j < lenj; j++) {
            focusableElements[j].addEventListener("focus", function() {
              document.querySelector("." + parentClass).classList.add("focus-within");
            });
            focusableElements[j].addEventListener("blur", function() {
              document.querySelector("." + parentClass).classList.remove("focus-within");
            });
        }
    }
}
addListeners("flip-card");
/* The flip card container - set the width and height to whatever you want. We have added the border property to demonstrate that the flip itself goes out of the box on hover (remove perspective if you don't want the 3D effect */
.flip-card {
    background-color: transparent;
    width: 300px;
    height: 200px;
    // border: 1px solid #f1f1f1;
    // perspective: 1000px; /* Remove this if you don't want the 3D effect */
}

/* This container is needed to position the front and back side */
.flip-card-inner {
    position: relative;
    width: 100%;
    height: 100%;
    text-align: center;
    transition: transform 0.8s;
    transform-style: preserve-3d;
}

/* Do an horizontal flip when you move the mouse over the flip box container */
.flip-card:hover .flip-card-inner, .flip-card:active .flip-card-inner, .flip-card:focus .flip-card-inner{
    transform: rotateY(180deg);
}

/* Position the front and back side */
.flip-card-front, .flip-card-back {
    position: absolute;
    width: 100%;
    height: 100%;
    -webkit-backface-visibility: hidden; /* Safari */
    backface-visibility: hidden;
}

/* Style the front side (fallback if image is missing) */
.flip-card-front {
    background-color: #008CCC;
    background-color: azure;
    color: white;
    color: black;
}

/* Style the back side */
.flip-card-back {
    background-color: #99CC66;
    color: white;
    transform: rotateY(180deg);
}

/* New CSS selector */
.flip-card.focus-within .flip-card-inner{
    transform: rotateY(180deg);
}

@media (prefers-reduced-motion) {
    .flip-card-inner {
        transition: transform none;
    }

}
<div id="content">
        <h1>Small Business Resources</h1>

    <input type="text">
    <br><br>

        <div class="flip-card">
            <div class="flip-card-inner">
                <a href="#" id="flip-card-inner">
                    <div class="flip-card-front">
                        <div>Card-front content</div>
                    </div>
                </a>
                <div class="flip-card-back">
                    <a href="https://www.google.com">Google</a>
                    <div>Text</div>
                </div>
            </div>
        </div>

    </div><!-- end #content -->

(*) 使用 polyfill

的替代路线

我找到了一个 focus-within polyfill,我还没有检查它是否适用于 IE9 和 10,但我认为对大多数公司来说只支持 IE11 是一个合理的妥协,它似乎适用于 IE11。

我们仍然尽可能支持回到 IE9,因此我包含了上面的代码片段(加上它更少的 JS,因此性能更好)。