为什么按下TAB键(:focus效果)会导致带有<input>字段的定位在屏幕外的<div>元素出现在屏幕上?

8

enter image description here

我想知道为什么在具有负边距(margin-right:-170px)的div容器上按下TAB键后,包含可聚焦元素(输入、超链接)的屏幕会显示出来?有什么想法吗?
在我的情况下,我需要防止这种行为,因为我有一个侧边栏菜单(在屏幕外),用户按下tab键几次后才会显示。但它不应该这样。我只想在移动设备和平板电脑上显示这个侧边栏。 注意:更重要的是,在Firefox和Google Chrome中,这种行为是不同的。在我的例子中,如果你删除<input>元素,只留下超链接<a>,那么在按下tab键后,框将不会显示。但在Chrome中会显示。 类似的帖子:Chrome bug? or how do I prevent a form field to SCROLL the container when focused? 其中一种解决方案(防止TAB):可能可以解决问题,但不建议使用。
    $("body").on("keydown",  function (e) {
        if (e && e.keyCode === 9) {
            console.log('Tab was pressed', e);
            e.preventDefault();
        }
    });

>> 从截图中的工作示例:

.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>

>> 工作示例 #2

http://jsfiddle.net/pndz/yy9kzp3e/


按下 Tab 键会将焦点放在链接上,浏览器会滚动/移动元素,以便用户可以看到该链接,否则将其聚焦没有意义。可能有几种方法可以避免这种情况,但我认为主要问题是您正在使用负边距来隐藏元素。您使用这种方法而不是像 display: none 这样的东西,是否有特殊原因? - RoToRa
  1. 我可以看到浏览器滚动/移动到输入框,但具体是如何实现的(在幕后发生了什么)?浏览器是否添加了任何特殊样式,如果有,应用了哪些样式?
  2. 在我的情况下,我使用了负边距右侧,以获得从右侧滑入/关闭的漂亮动画。如果我使用“display:none;”,它将无法工作。
- Michael Money
如果你让它滑入,当链接获得焦点时,它可以滑入。 - RoToRa
当然我可以...但我仍然很好奇为什么这一开始会发生。有几种解决方法可以解决这个问题,但我希望有人能够解释这种奇怪的浏览器行为... - Michael Money
是的,如果您设置:position: absolute;right: -150px;,则会产生相同的效果。 - Michael Money
显示剩余2条评论
3个回答

6

将您的.box设置为fixed而不是absolute可以防止此行为。

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

我认为这是因为浏览器无法滚动“超出视口”。如果您的意图是将元素定位在屏幕之外,则这也是更直观的语义。


如果侧边栏只适用于小型设备,那么不在其他设备上显示它会更加清晰。例如:

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

请注意,使用视口宽度来检测“小设备”并不是非常可靠。

解释

该框位于您的<body>中,该元素会扩展以容纳内容(通过水平滚动条明显)。当按下tab键将焦点放在<input>上时,浏览器会将焦点元素滚动到视图中。因此实际上移动的不是框而是整个元素内容向左移动。从技术上讲,包含节点(在您的情况下为<body>)的scrollLeft属性被设置为使输入在屏幕上可见。

这是从Chromium的角度来看的,细节实现可能因浏览器而异。


固定布局对移动设备不利,可能会导致多个错误,甚至在iOS 10上也是如此。 - Made in Moon

4

将元素的tabIndex设置为-1可防止通过Tab键聚焦到您不想让其获得焦点的元素上。


呵呵,谢谢这个快速的�技巧,这暂时解决了我的问题。� - Gregordy
这不是黑客攻击,@Gregordy,这是一种HTML功能,允许工程师控制可以聚焦标签和不能聚焦的内容。 - John Mutuma
是的,我明白。整个故事是,对于我的情况来说,这有点像一个hack,因为在特定元素上进行制表会应用破坏我的设计的样式。由于我不知道这些样式来自哪里,也无法弄清楚如何删除它们,所以我只是“防止在我的元素上制表”。 - Gregordy

0

处理这个问题的一种简单而最佳的方式是使用CSS的display属性。 例如:

 .slider-content .items:not(.active) {
    display: none;
}

对于其他未激活的幻灯片。 谢谢 ~RDaksh


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接