如何让div的scrollTop值与textarea保持同步?
问题:textarea与同尺寸镜像div无法同步scrollTop值
我用一个div来格式化并显示textarea中的文本,要求二者始终保持同步,但当输入文本超出textarea底部后,无法同步它们的scrollTop值。我的实现思路参考了代码高亮编辑框的方案,但该方案在项目中不生效。
关键代码片段
HTML
<section> <div class="input-text__container"> <div id="input-text--mirror" class="input-text"></div> <textarea id="input-text--original" cols="30" rows="6" autofocus class="input-text" placeholder="Enter your text here" autocomplete="off" autocorrect="off" spellcheck="false" ></textarea> </div> <section>
CSS
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap'); html { font-size: 62.5%; box-sizing: border-box; scroll-behavior: smooth; } *, *::after, *::before { margin: 0; padding: 0; border: 0; box-sizing: inherit; vertical-align: baseline; } body { height: 100vh; } section { display: flex; flex-direction: column; min-height: 100%; padding: 1rem; } .input-text__container { width: 100%; position: relative; flex: 1; } .input-text { width: 100%; height: 100%; position: absolute; font-size: 3.2rem; overflow-wrap: break-word; font-family: "Inter"; } #input-text--mirror { background-color: #e9ecf8; color: #0a3871; overflow: hidden; } #input-text--original { background-color: transparent; -webkit-text-fill-color: transparent; resize: none; outline: none; -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ } #input-text--original::placeholder { color: #e9ecf8; -webkit-text-fill-color: #052051; } #input-text--original::selection { -webkit-text-fill-color: #ffffff; } .invalid { font-weight: 400; color: #ff0000; } #input-text--original::-webkit-scrollbar { display: none; }
JavaScript
let invalidInput = false; const patterns = { valid: "a-z ", invalid: "[^a-z ]", linebreaks: "\r|\r\n|\n", }; const textIn = document.querySelector("#input-text--original"); const mirror = document.querySelector("#input-text--mirror"); function validateInput(string, className) { let anyInvalidChar = false; // Generate regular expressions for validation const regExpInvalids = new RegExp(patterns.invalid, "g"); const regExpLinebreaks = new RegExp(patterns.linebreaks); // Generate innerHTML for mirror const mirrorContent = string.replace(regExpInvalids, (match) => { if (regExpLinebreaks.test(match)) { return "<br/>"; } else { anyInvalidChar = true; return `<span class=${className}>${match}</span>`; } }); // Update mirror mirror.innerHTML = mirrorContent; return anyInvalidChar; } textIn.addEventListener("input", (e) => { const plain = textIn.value; const newInputValidity = validateInput(plain, "invalid"); mirror.scrollTop = textIn.scrollTop; }); textIn.addEventListener( "scroll", () => { mirror.scrollTop = textIn.scrollTop; }, { passive: true } );
复现步骤
在桌面端输入前8个自然数并按列排列,即可复现scrollTop不同步的问题。
已尝试的无效方案
- 将换行符替换为
<br/> - 当最后一个字符是换行符时追加空格
- 给mirror div添加
overflow: scroll样式 - 尝试使用offsetTop、pageYOffset等相关属性
需要不依赖任何框架/库的原生JavaScript解决方案。
内容的提问来源于stack exchange,提问作者Ayxa Chaverra Renteria
相关产品推荐
相关产品推荐

