Tabindex无法在Chrome中运行(React app)

时间:2017-10-24 10:11:08

标签: javascript reactjs google-chrome tabindex react-modal

我使用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兼容的,但我也没有真正的好选择)。

2 个答案:

答案 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;