我使用react和react-modal在网站上创建叠加层。此叠加层包含各种元素以及表格(下面的概述)。我希望能够使用TAB键引导用户浏览表单。我将tabindex=0
分配给所需的元素,以便按外观顺序列表。
我的问题是:它在Chrome(版本61.0.3163.100)中不起作用,而它在Firefox中可以使用。我读到如果DOM树中的任何元素不可见或者高度/宽度为0,就会发生这种情况。我做了一些样式更改来修复它但没有效果。
<div class="ReactModalPortal">
<div data-reactroot="" class="ReactModal__Overlay" style="position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px;">
<div class="ReactModal__Content" tabindex="-1" aria-label="Questionnaire" style="position: absolute; top: 0px; left: 0px; right: 0px; height: 100%; background: transparent none repeat scroll 0% 0%; overflow: auto;">
<!-- Some other stuff and nested elements -->
<div id="...">
<form>
<input tabindex="0">
<button tabindex="0">
</form>
</div>
</div>
</div>
正如您所见,其中一个父元素有tabindex="-1"
。当通过Chrome中的inspect功能进行更改或使用JS以编程方式更改问题时,问题仍然存在(或者如果元素最初使用此索引进行渲染会有所不同吗?)。
更新
我意识到其他因素导致了这些问题。我在我的模态的根节点上使用CSS属性initial: all
来阻止我的内部CSS与外部的一切。出于某种原因,这阻止了tabindex工作。如果你能帮助我理解,我会奖励这个赏金。我的解决方法是不使用all: initial
(它不是IE兼容的,但我也没有真正的好选择)。
答案 0 :(得分:4)
import UIKit
import WebKit
class ViewController: UIViewController {
private var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
webView = WKWebView(frame: view.bounds, configuration: configuration)
view.addSubview(webView)
}
}
使用初始属性重置节点的所有CSS属性。
对于all: initial
属性,初始值为display
。
因此,将inline
设置为根div会将all: initial
属性设置为内联。 display
元素没有高度或宽度,因此它们是0x0。
这也是因为inline
只包含固定的,绝对定位的元素。
React Modal通过运行模态内所有元素的循环来检查元素是否可聚焦。但是,对于要聚焦的元素,它必须是可见的。对于每个元素,我们必须迭代直到body元素以确保它的可见性。
这是检查元素是否可见的函数。
div
正如您所看到的,我们的div没有function hidden(el) {
return (
(el.offsetWidth <= 0 && el.offsetHeight <= 0) || el.style.display === "none"
);
}
或offsetHeight
,并且会被视为隐藏。因此,模态不能不集中。
答案 1 :(得分:0)
我遇到了同样的问题,无法让其他解决方案快速生效,所以我想出了蛮力方法。对容器元素进行引用,该容器元素包含您希望设置为可选项卡的可聚焦元素。
const formRef = useRef();
<ReactModalTabbing containerRef={formRef}>
<form ref={formRef} onSubmit={handleSubmit} >
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
</form>
</ReactModalTabbing>
这是组件
import React, { useState, useEffect } from 'react';
const ReactModalTabbing = ({ containerRef, children }) => {
const [configuredTabIndexes, setConfiguredTabIndexes] = useState(false);
const focusableElements = () => {
// found this method body here.
//https://zellwk.com/blog/keyboard-focusable-elements/
return [...containerRef?.current?.querySelectorAll(
'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"]):not([type="hidden"]):not([disabled])'
)];
}
const isTabbable = (element) =>{
if(element.getAttribute('tabindex')){
return true;
}
return false;
}
const findElementByTabIndex = (tabIndex) => {
return containerRef?.current?.querySelector(`[tabindex="${tabIndex}"]`);
}
const moveFocusToTabIndex = (tabIndex) => {
findElementByTabIndex(tabIndex)?.focus();
}
const handleKeyDownEvent = (event) => {
if(!isTabbable(event.target)){
return;
}
const tabIndex = parseInt(event.target.getAttribute('tabindex'));
if(event.shiftKey && event.key === 'Tab'){
moveFocusToTabIndex(tabIndex - 1);
}else if(event.key === 'Tab'){ //should probably make sure there is no other modifier key pressed.
moveFocusToTabIndex(tabIndex + 1);
}
}
useEffect(() => {
if(!configuredTabIndexes && containerRef.current){
setConfiguredTabIndexes(true);
focusableElements().forEach((el, index) => el.setAttribute('tabindex', index + 1));
containerRef?.current?.addEventListener('keydown', handleKeyDownEvent);
}
});
return children;
}
export default ReactModalTabbing;