HTML5 textarea高度自适应的两种方案
阅读全文你将获得以下解决方案。
- 点击长文本编辑textarea,自动获得焦点
- 随着输入值自动伸缩高度
- 可复制添加信息
- 可粘贴文本
- 可粘贴图片
以下实例代码执行环境为chrome80
方案一
html5 textarea 元素
1. 自动获得焦点
点击编辑自动获得焦点后光标跳转到了最前面,why?
查文档 mdn,textarea
元素存在selectionend
和selectionstart
的属性用来表示选中的文本开始位置和结束位置,dom接口实例是 htmltextareaelement
, 它具有 setselectionrange
方法,用来选中输入框中的文本,用法:textareaelement.setselectionrange(selectionstart, selectionend, [optional] selectiondirection);
那么我们只要做到selectionstart === selectionend === value.length
, 这样光标就选中到最末尾。
edit.addeventlistener("click", function() { txt.classlist.add("hidden"); document.body.insertbefore(textarea, edit); textarea.innerhtml = "这是需要编辑的信息"; textarea.focus(); // textarea.selectionend = textarea.innerhtml.length; textarea.setselectionrange( textarea.innerhtml.length, textarea.innerhtml.length ); });
2. 自适应高度
当不设置高度时换行会出现滚动条,所以只要让textarea
滚动条消失,让其height = scrollhieght
, 那么如何监听textarea的变化,则需要input
事件,让textarea
高度动态等于它的scrollheight
即可,代码如下:
textarea.addeventlistener("input", function() { this.style.height = `${this.scrollheight}px`; });
为什么每次输入都会使得高度增加(每次增加4px),经过测试safari
同样也是这个效果,firefox
符合预期高度不异常增加,查看chrome控制台发现textarea
内置了很多样式,尝试将去掉padding
后,可以正常随着内容增加高度自适应了。
<style> textarea { padding: 0; } </style> <textarea></textarea> <script> const textarea = document.createelement("textarea"); textarea.addeventlistener("input", function(e) { this.style.height = `${this.scrollheight}px`; }); </script>
为什么去掉padding值,输入后高度就不增加了?(未找到合理的解释,欢迎留言讨论解答)
但是删除文本的情况下height
并未能自动缩放,分析原因, 当删除文本换行的时候scrollheight
的大小并未发生改变,scrollheight
作为只读属性( mdn-文档),如何让scrollheight
高度重新计算哪?只有改变高度,于是:
textarea.addeventlistener("input", function(e) { this.style.height = "inherit"; this.style.height = `${this.scrollheight}px`; });
到此高度自适应输入内容完成,但是每次换行的闪动很难受,transition
走一波,
textarea { overflow: hidden; // 防止换行出现滚动条闪动 padding: 5px 10px; box-sizing: border-box; transition: all 0.2s linear; }
结果transition
并没效果,原因height
初始值或者参考值必须为数值过渡动画才会生效,height
设置为auto
或者inherit
动画不会生效, 所以折中的办法就是当删除的时候重新重置高度,输入时不需要重置,这样输入时动画生效, 删除没有动画, 暂时没想到更好的办法。
textarea.addeventlistener("keyup", function(e) { if (e.keycode === 8) { this.style.height = "inherit"; this.style.height = `${this.scrollheight}px`; } else { this.style.height = `${this.scrollheight}px`; } });
3. 支持粘贴文本,图片等
textarea只能输入文本,无法实现粘贴图片。
textarea.addeventlistener( "paste", function(e) { e.preventdefault(); console.log( "paste", e.clipboarddata.items, e.clipboarddata.types, e.clipboarddata.getdata("text/html"), e.clipboarddata.getdata("text/plain"), e.clipboarddata.getdata("text/files") ); }, false );
方案二
div contenteditable
替换textarea
1. 自动获得焦点
编辑div contenteditable
为true
,然后利用range
和selection
光标移动到最后的效果。
edit.addeventlistener("click", () => { textarea.setattribute("contenteditable", true); textarea.focus(); const range = document.createrange(); // range 包含的内容 range.selectnodecontents(textarea); // range.setstart(textarea.firstchild, 0); // range.setstart(textarea.lastchild, textarea.innerhtml.length); // 起始位置是否相同 range.collapse(false); const sel = window.getselection(); // 将所有的区域都从选区中移除。 sel.removeallranges(); // 一个区域(range)对象将被加入选区。 sel.addrange(range); });
2. 自适应高度
div contenteditable
天然支持根据输入来自适应高度。
3. 粘贴图片, 文本等
textarea.addeventlistener("paste", function(e) { e.preventdefault(); const clipboarddata = e.clipboarddata || e.originalevent.clipboarddata; // 获取纯文本 let text = clipboarddata.getdata("text/plain"); let file = clipboarddata.getdata("text/plain"); // console.log(clipboarddata.items, clipboarddata.getdata("text/files")); // 插入img,可以做一些上传图片的一些操作 insertimg(clipboarddata); // 只输入纯文本 document.execcommand("inserttext", false, text); });
此方法可以限定只能上传文本或者图片。
欢迎留言讨论其他textarea
高度自适应的方案。
到此这篇关于html5 textarea高度自适应的两种方案的文章就介绍到这了,更多相关textarea高度自适应内容请搜索以前的文章或继续浏览下面的相关文章,希望大家以后多多支持!