必须用 contenteditable="true" 的 div 替代 textarea 才能正确插入和渲染 emoji,因其支持 unicode 字符及富文本节点,而原生 textarea 仅支持纯文本。

用 contenteditable 替代 textarea 才能插入 emoji
原生 textarea 只支持纯文本,无法渲染 emoji 图片或富文本节点,粘贴 emoji 会变成乱码或被过滤。必须改用 div[contenteditable="true"],它允许插入 <img> 或直接 Unicode emoji 字符,并保持光标定位和编辑连续性。
实操建议:
- 设置
div的contenteditable="true"、spellcheck="false"(避免右键菜单干扰)和role="textbox"(可访问性) - 禁用默认样式:用
white-space: pre-wrap保留换行,overflow-wrap: break-word防止长 emoji 行溢出 - 监听
input事件而非change(后者不触发于 contenteditable)
点击 emoji 按钮时,用 document.execCommand 插入到光标位置
document.execCommand('insertHTML', false, '?') 是最轻量的插入方式,兼容所有现代浏览器(包括 Safari 15+),且不会破坏当前光标位置或选区。
注意点:
- 必须在用户点击后立即执行,不能异步延迟(否则光标可能已移走)
- 插入前先调用
window.getSelection()+getRangeAt(0)确保有有效选区;若无(如 div 刚聚焦),需手动创建 Range 并定位到末尾 - 避免对 emoji 做额外 HTML 转义——直接传入 Unicode 字符串即可,例如
'?',不是'🚀'
输入框内 emoji 显示异常?检查字体和编码设置
部分系统(尤其是 Windows + Chrome)默认用 Segoe UI Emoji 渲染 emoji,但若页面指定了 font-family: sans-serif 且未 fallback 到 emoji 字体,会导致方块或问号。
解决方法:
- CSS 中显式声明 emoji 字体栈:
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif; - 确保 HTML 文档声明 UTF-8:
<meta charset="utf-8">(缺省会导致 emoji 解析失败) - 服务端返回响应头含
Content-Type: text/html; charset=utf-8,否则某些代理会强制转码
移动端 emoji 键盘唤起后光标错位?需要手动 focus + scrollIntoView
iOS Safari 在软键盘弹出后常把 contenteditable 元素滚动到视口外,导致光标不可见;Android 部分机型则根本没触发 focus。
补救逻辑:
- 监听
focusin事件,在回调中加setTimeout(() => el.scrollIntoView({ block: 'nearest' }), 100) - 点击 emoji 面板时,先
el.focus()再插入,防止 iOS 忽略插入目标 - 避免在
touchend后立刻操作 DOM,改用requestAnimationFrame延迟一帧再 focus
src 或 base64。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











