Why pressing TAB key (:focus effect) causes positioned off-the-screen <div> element with <input> field inside it to appear on the screen?

I would like to know, why after pressing TAB key on div container with negative margin-right (margin-right:-170px) that contains focusable element (input, hyperlink) is being shown on the screen? Any ideas?

In my case I need to prevent such a behaviour since I've sidebar menu (off the screen), which is shown after user press tab button several times. And it shouldn't. I want to show this sidebar only on mobile and tablet devices.

Note: What's more. The behaviour is different in Firefox and different in Google Chrome. In my example if you remove <input> element and leave only hyperlink <a>, the box will NOT show after pressing tab key. In Chrome it will.

Similar post: Chrome bug? or how do I prevent a form field to SCROLL the container when focused?

One of solutions (preventing TAB): May resolve the problem, but not recommended.

    $("body").on("keydown",  function (e) {
        if (e && e.keyCode === 9) {
            console.log('Tab was pressed', e);
            e.preventDefault();
        }
    });

>> Working example from the screenshot:

.box {
  width: 150px;
  height: 50px;
  display: block;
  right: 0;
  margin-right:-170px; /* Negative margin to set container off the screen*/
  padding:10px;
  background: #292929;
  color: #fff;
  position: absolute;
  -webkit-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;
  box-shadow:2px 2px 5px rgba(0, 0, 0, .4)
}

.box.input {
    top: 0;
}

.box.hyperlink {
    top: 100px;
}

body {
  background: lightgray;
}

a {
  color: white;
}
input {
  margin:10px 15px;
}
p {
  width:400px;
  }
<p>After you press TAB key, box containing input will appear from the right on the screen.... but why?</p>

<div class="box input">
  <label>Custom Input 1</label>
  <input type="text" placeholder="some input" />
</div>         

<div class="box hyperlink">
  <label>Custom hyperlink</label>
  <a href="http://www.apple.com" target="_blank">Some link</a>
</div>

Answers


Setting your .box to fixed instead of absolute prevents the behavior.

.box {
    /* ... */
    position: fixed; /* position the element relative to the viewport */
    /* ... */
}

I assume because the browser can't scroll "beyond the viewport". It's also the more intuitive semantic if your intention is to position the element off the screen.


If the sidebar is only meant for small devices I agree with the notion that it's more clean to not display it at all on other devices. e.g.

@media all and (min-width: 769px) { /* determining the correct size is up to you */
    .box {
        display: none;
    }
}

but please be aware that viewport with is actually not a very reliable way of detecting 'small devices'

Explanation

The box is placed inside your <body> which expands to hold the content (made obvious by the horizontal scrollbar). When pressing tab gives focus to the <input>, the browser scrolls the focused element into view. So actually not the box but the entire element content is moving left. Technically speaking the scrollLeft Property of the containing node (<body> in your case) is set such that the input is visible on the screen.

This is from a Chromium point of view, finer implementation details can vary between browsers.


Set a tabIndex of -1 to prevent tab focusability to elements that you don't want to gain focus with the tab key.


Need Your Help

Max size of pointer array to 2D array?

c arrays pointers

I'm using the following to allow me to choose which 2D array I use, dynamically.