无法在contenteditable元素上检测scroll事件的问题求助
问题:contenteditable元素绑定scroll事件无效
我尝试了多种方式给contenteditable元素绑定scroll事件,但handleScrollToUpdateRect函数始终不触发。wheel事件可以生效,但响应性达不到需求——我需要在div滚动时持续更新矩形位置。
相关代码
- textField定义:
textField = document.activeElement;
- 尝试过的事件绑定代码:
$(textField).on('scroll click keyup', handleScrollToUpdateRect); $('[contenteditable]').on('scroll keyup click', handleScrollToUpdateRect); $(textField).on('mousemove scroll keyup click', handleScrollToUpdateRect); textField.addEventListener('scroll', function () { setTimeout(() => { handleScrollToUpdateRect(); }, 0); }); textField.addEventListener('scroll', handleScrollToUpdateRect, true); Array.from(textField.children).forEach(function (child) { child.addEventListener('scroll', handleScrollToUpdateRect); }); textField.onscroll = function (e) { //console.log('scrolling'); handleScrollToUpdateRect(e); };
- 需要触发的函数(滚动时无控制台输出):
function handleScrollToUpdateRect(e) { requestAnimationFrame(() => { updateRect('rect-before-prompt'); updateRect('rect-after-prompt'); checkRectWithinTextField('rect-before-prompt'); checkRectWithinTextField('rect-after-prompt'); }); console.log(' scrolling update rect'); }
- HTML结构:
<div contenteditable="true" aria-multiline="true" role="textbox" class="notranslate IZ65Hb-YPqjbf fmcmS-x3Eknd h1U9Be-YPqjbf" tabindex="0" spellcheck="true" dir="ltr">"..."</div>
解决思路与方案
1. 确认contenteditable元素具备触发scroll事件的条件
scroll事件仅在元素自身出现滚动条时触发,需满足:
- 元素设置固定高度/最大高度
overflow属性设为auto或scroll- 内容高度超过元素高度
如果未满足,添加样式:
[contenteditable] { height: 300px; overflow-y: auto; }
2. 定位实际滚动的容器
有时滚动条属于contenteditable的父容器(如body、外层div),而非元素本身。此时需给父容器绑定事件:
const scrollContainer = textField.parentElement; scrollContainer.addEventListener('scroll', handleScrollToUpdateRect);
3. 结合input事件覆盖编辑场景
部分浏览器中,contenteditable的scroll事件不会在光标移动、内容编辑时触发,可搭配input事件补充:
textField.addEventListener('input', handleScrollToUpdateRect); textField.addEventListener('scroll', handleScrollToUpdateRect);
4. 替代方案:用Intersection Observer监听可视区域
若scroll事件仍无法触发,可通过Intersection Observer监听矩形元素是否在contenteditable可视范围内,实现更新逻辑:
const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { updateRect(entry.target.id); checkRectWithinTextField(entry.target.id); }); }, { root: textField }); observer.observe(document.getElementById('rect-before-prompt')); observer.observe(document.getElementById('rect-after-prompt'));
内容的提问来源于stack exchange,提问作者Ky Nam Nguyen
相关产品推荐
相关产品推荐

