【问题标题】:Why does calling focus() break my CSS transition?为什么调用 focus() 会破坏我的 CSS 过渡?
【发布时间】:2015-01-03 04:01:38
【问题描述】:

This html 文件显示 3 面板布局。当我更改面板时,“left”属性上的 css 过渡给了我很好的滑动效果。一切正常,但是当我更改面板时,我想将焦点放在新面板中的输入上。谁能告诉我为什么对 focus() 的调用会中断 css 转换,并让我在两个面板之间处于中间位置?它只会在未来发生。如果我注释掉转换,它会起作用,如果我用超时延迟对 focus() 的调用,它就会起作用。

问题出现在 Chrome、IE 和 Firefox 中。

var panelContainer;
var panels = new Array();
var numPanels;
var currentPanel = 0;

window.addEventListener('load', init, false);

function init() {
  setTimeout(function() {
    window.scrollTo(0, 1);
  }, 10); //hiding the browser address bar in iPhone/Android

  panelContainer = document.getElementById("panelContainer");
  panels = document.getElementsByClassName("panel");
  numPanels = panels.length;
  sizeResize();
}

function sizeResize() {
  panelContainer.style.width = (numPanels * window.innerWidth) + "px";
  panelContainer.style.height = window.innerHeight + "px";
  for (var i = 0; i < numPanels; i++) {
    panels[i].style.width = window.innerWidth + "px";
    panels[i].style.height = window.innerHeight + "px";
  }
  slide();
}
window.onresize = sizeResize;

function slide(panel) {
  if (panel != undefined)
    currentPanel = panel;
  panelContainer.style.left = -(window.innerWidth * currentPanel) + "px";
  if (panel >= 0) {
    panels[panel].getElementsByTagName("input")[0].focus(); //shows problem
    //window.setTimeout(function () { panels[panel].getElementsByTagName("input")[0].focus() }, 100);//no problem

  }
}
#wrapper {
  width: 100%;
  height: auto;
  overflow: hidden;
}

#panelContainer {
  position: relative;
  transition: left 1000ms ease;
}

.panel {
  float: left;
}
<div id="wrapper">
  <div id="panelContainer">
    <div id="panel0" class="panel" style="background-color: #888;">
      panel zero
      <input id="btn0" class="focussable" type="button" onclick="slide(1);" value="forward" />
    </div>
    <div id="panel1" class="panel" style="background-color: #AAA;">
      panel 1
      <input id="btn1" class="focussable" type="button" onclick="slide(2);" value="forward" />
      <input type="button" onclick="slide(0);" value="back" />
    </div>
    <div id="panel2" class="panel" style="background-color: #CCC;">
      panel 2
      <input id="btn2" class="focussable" type="button" onclick="slide(1);" value="back" />
    </div>
  </div>
</div>

【问题讨论】:

  • 您能提供一个现场演示供我们编辑吗?
  • 无论出于何种原因,我尝试将其复制为 jsfiddle 都没有成功。您可以将代码保存在本地,然后从文件系统在浏览器中打开它。抱歉,我手边没有面向 Web 的服务器。
  • 这不是一个完整的答案,但可能有用......浏览器有将活动元素滚动到视图中的规则。这些规则优先于您可能尝试编写脚本的任何行为。在上面的例子中,标签也给我带来了问题。目前的解决方法是始终管理焦点。页面上的某些内容必须始终保持焦点,并且在 setTimeout() 中调用 focus() 以便有机会完​​成转换。
  • 这是一个有效的jsFiddle 显示问题。
  • 谢谢你完美地显示了这个问题。我已将超时更改为 300 毫秒,现在超时版本显示了所需的行为。这是一个棘手的问题。

标签: javascript html css-transitions


【解决方案1】:

正如@user1585345 正确指出的那样,浏览器会立即滚动到焦点元素,以便将其带到当前视图中,而不是进一步的 px!

这里发生的情况如下:您更改元素的相对位置,但立即更改焦点,因为事件触发时焦点元素不可见,内容也滚动(结束突然动画)。

您应该仅在动画完成时显式触发焦点,以便浏览器识别不需要滚动。

【讨论】:

  • 这让我在 3 年后免于发疯。不过这很痛苦,因为这意味着您必须使用超时,并希望您是否使用 CSS 过渡,或者切换到脚本动画以便知道它们何时结束。
  • false,有两个事件监听器 'ontransitionend' 和 'onanimationend' 你可以添加一个事件然后触发你的 focus() 函数。
  • 这是实现我建议的一种方法。我不明白这如何使我的回答错误。您能详细说明一下,以便我们可以更详细地解决答案吗?
猜你喜欢
  • 2015-11-17
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 2013-06-25
  • 2013-06-07
  • 1970-01-01
相关资源
最近更新 更多