首页 > 解决方案 > 在 div 上复制输入滚动

问题描述

我正在尝试在 div 元素上复制输入水平滚动,因此每当用户沿输入移动时,div 元素的滚动与输入完全相同。

我的问题在于 Chrome,因为输入似乎具有不同的滚动行为,导致两个元素中的 scrollLeft 值不同。在 Firefox 中,它按预期工作。

有没有办法在不使用 jQuery 或其他库的情况下在 Chrome 中实现这一点?还是我在问不可能?

var theTextDiv = document.getElementById("the-text");
var theText = document.getElementById("the-text-input");

function keepScroll(txt) {
		theTextDiv.scrollLeft = theText.scrollLeft;
}

theText.addEventListener("blur", function() { keepScroll("blur"); });
theText.addEventListener("change", function() { keepScroll("change"); });
theText.addEventListener("focus", function() { keepScroll("focus"); });
theText.addEventListener("input", function() { keepScroll("input"); });
theText.addEventListener("keydown", function() { keepScroll("keydown"); });
theText.addEventListener("keyup", function() { keepScroll("keyup"); });
theText.addEventListener("scroll", function() { keepScroll("scroll"); });
theText.addEventListener("select", function() { keepScroll("select"); });
#the-text {
    border: 1px solid red;
    max-width: 98px;
    font-size: 14px;
    overflow-x: scroll;
    word-wrap: break-word;
    white-space: nowrap;
    font-family: "Times New Roman", Times, serif;
    padding: 1px;
    margin-right: 10px;
}

#the-text-input {
    border: 1px solid red;
    width: 100px;
    font-size: 14px;
    font-family: "Times New Roman", Times, serif;
}
<div id="the-text">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>

<input type="text" id="the-text-input" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />

编辑:

我在 Mac 上的 Chrome 77 上尝试了上面的代码,它按预期工作,两个元素之间没有差距,我开始认为这是 Windows 问题而不是 Chrome 问题

编辑(2):

重新启动我的电脑后,所有工作都按预期(严重)可能是某些 chrome 缓存导致出现奇怪的行为

标签: javascripthtmlcssgoogle-chromefirefox

解决方案


input这可能与和/或上的填充和边框有关div,并且看起来它在 Chrome 77 中运行良好,您要么忘记在发布的示例中添加一些代码,要么这些元素的默认样式也在播放这里的一个角色。

在任何情况下,我的建议是从两个元素中删除边距、填充和边框,并div用它们添加一个包装(红色示例)。

您也可以使用box-sizing: border-box,保留这些样式并避免使用包装器,但padding在 中的行为不同input,因为填充区域中的内容不可见(蓝色示例)。

最后,您更新滚动的代码在模糊上无法正常工作,因为当事件触发输入时滚动尚未重置为 0。包装它setTimeoutwindow.requestAnimationFrame解决问题。此外,后者还将使更新更加流畅和同步。

const text = document.getElementById('text');
const input = document.getElementById('input');

function updateScroll() {
  // Scroll not updated on blur without requestAnimationFrame
  // or setTimeout:
  requestAnimationFrame(() => text.scrollLeft = input.scrollLeft);
}

input.addEventListener('blur', updateScroll);
input.addEventListener('change', updateScroll);
input.addEventListener('focus', updateScroll);
input.addEventListener('input', updateScroll);
input.addEventListener('keydown', updateScroll);
input.addEventListener('keyup', updateScroll);
input.addEventListener('scroll', updateScroll);
input.addEventListener('select', updateScroll);

const textAlternative = document.getElementById('text-alternative');
const inputAlternative = document.getElementById('input-alternative');

function updateScrollAlternative() {
  // Scroll not updated on blur without requestAnimationFrame
  // or setTimeout:
  requestAnimationFrame(() => textAlternative.scrollLeft = inputAlternative.scrollLeft);
}

inputAlternative.addEventListener('blur', updateScrollAlternative);
inputAlternative.addEventListener('change', updateScrollAlternative);
inputAlternative.addEventListener('focus', updateScrollAlternative);
inputAlternative.addEventListener('input', updateScrollAlternative);
inputAlternative.addEventListener('keydown', updateScrollAlternative);
inputAlternative.addEventListener('keyup', updateScrollAlternative);
inputAlternative.addEventListener('scroll', updateScrollAlternative);
inputAlternative.addEventListener('select', updateScrollAlternative);
body {
  margin: 0;
}

.box {
  position: relative;
  display: block;
  width: 50%;
  box-sizing: border-box;
  
  /* Moved styles here: */
  border: 3px solid red;
  padding: 8px;
  margin: 8px auto 0;
}

#text,
#input,
#text-alternative,
#input-alternative {
  display: block;
  width: 100%; 
  font-size: 14px;
  font-family: monospace;
  outline: none;
}

#text,
#input {  
  /* Removed margin, padding and borders: */
  border: 0;
  padding: 0;
  margin: 0;
}

#text-alternative,
#input-alternative {
  width: 50%;
  box-sizing: border-box;
  
  /* Keep styles here thanks to box-sizing, but behaves differently: */
  border: 3px solid blue;
  padding: 8px;
  margin: 8px auto 0;
}


#text,
#text-alternative {
  word-wrap: break-word;
  white-space: nowrap;
  
  /* No need to keep it visible unless you want to scroll manually too: */
  overflow-x: hidden;
}
<div class="box">
  <div id="text">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
  </div>
</div>

<label class="box">
  <input id="input" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />
</label>

<div id="text-alternative">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>

<input id="input-alternative" value="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." />


推荐阅读