Skip to content

Tabbing not possible inside display: contents #905

Closed
@aloker

Description

@aloker

Summary:

Within a modal, it is not possible to tab through elements inside an element with display: contents

Steps to reproduce:

  1. Create a modal with an element that has display: contents
  2. Put focus-able elements inside that element (eg inputs)
  3. Try to tab through the inputs
  4. No focus change on tab

Expected behavior:

Focus switches to the next input element on tab

Link to example of issue:

See https://codesandbox.io/s/flamboyant-sunset-t3pbm
Open the dialog, then try to tab through the inputs - it won't work. Then change display: "contents" to display: "block" - tabbing no works.

Additional notes:

This is caused by the fact that elements with display: "contents" have a size of 0x0 and tabbable assumes the content is invisible:

function hidesContents(element) {
const zeroSize = element.offsetWidth <= 0 && element.offsetHeight <= 0;
// If the node is empty, this is good enough
if (zeroSize && !element.innerHTML) return true;
try {
// Otherwise we need to check some styles
const style = window.getComputedStyle(element);
return zeroSize
? style.getPropertyValue("overflow") !== "visible" ||
// if 'overflow: visible' set, check if there is actually any overflow
(element.scrollWidth <= 0 && element.scrollHeight <= 0)
: style.getPropertyValue("display") == "none";
} catch (exception) {
// eslint-disable-next-line no-console
console.warn("Failed to inspect element style");
return false;
}
}

It can be fixed by checking for display: contents, like so:

diff --git a/node_modules/react-modal/lib/helpers/tabbable.js b/node_modules/react-modal/lib/helpers/tabbable.js
index c72bf54..0e8a07a 100644
--- a/node_modules/react-modal/lib/helpers/tabbable.js
+++ b/node_modules/react-modal/lib/helpers/tabbable.js
@@ -27,6 +27,10 @@ function hidesContents(element) {
   try {
     // Otherwise we need to check some styles
     var style = window.getComputedStyle(element);
+    if(style.getPropertyValue("display") === "contents"){
+      // display === "contents" does not hide its contents even if its size is (always) 0x0
+      return false;
+    }
     return zeroSize ? style.getPropertyValue("overflow") !== "visible" ||
     // if 'overflow: visible' set, check if there is actually any overflow
     element.scrollWidth <= 0 && element.scrollHeight <= 0 : style.getPropertyValue("display") == "none";

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions