html5 textarea高度自适应,textarea 高度自适应的两种方案

原标题:textarea 高度自适应的两种方案

本文转载于 SegmentFault 社区

社区专栏:前端学习路-郭盖

作者: 郭盖

阅读全文你将获得以下解决方案:

1. 点击长文本编辑textarea,自动获得焦点

2. 随着输入值自动伸缩高度

3. 可复制添加信息

4. 可粘贴文本

5. 可粘贴图片

以下实例代码执行环境为 Chrome80

方案一

HTML5 Textarea 元素

1. 自动获得焦点

点击编辑自动获得焦点后光标跳转到了最前面,why?

75907227eb39845a36a78e22aad80c79.png

查文档 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`;

});

0003bd71e84e2eb1d0d45566ef3ee17e.gif

为什么每次输入都会使得高度增加(每次增加 4px),经过测试Safari同样也是这个效果,Firefox符合预期高度不异常增加,查看Chrome控制台发现(查看 chromium)textarea内置了很多样式,尝试将去掉padding后,可以正常随着内容增加高度自适应了。

chromium:

https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css

textarea{

padding: 0;

}

<>

consttextarea = document.( "textarea");

textarea.addEventListener( "input", function(e) {

this.style.height = ` ${ this.scrollHeight}px`;

});

>

为什么去掉padding值,输入后高度就不增加了?(未找到合理的解释,欢迎留言讨论解答)

但是删除文本的情况下height并未能自动缩放,分析原因, 当删除文本换行的时候scrollHeight的大小并未发生改变,scrollHeight作为只读属性(MDN-文档),如何让scrollHeight高度重新计算哪?只有改变高度,于是:

MDN-文档:

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/scrollHeight

textarea.addEventListener( "input", function(e) {

this.style.height = "inherit";

this.style.height = ` ${ this.scrollHeight}px`;

});

到此高度自适应输入内容完成,但是每次换行的闪动很难受,transition走一波

textarea{

overflow: hidden; // 防止换行出现滚动条闪动

padding: 5px10px;

box-sizing: border-box;

transition: all 0.2slinear;

}

结果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;

constrange = document.createRange;

// range 包含的内容

range.selectNodeContents(textarea);

// range.setStart(textarea.firstChild, 0);

// range.setStart(textarea.lastChild, textarea.innerHTML.length);

// 起始位置是否相同

range.collapse( false);

constsel = window.getSelection;

// 将所有的区域都从选区中移除。

sel.removeAllRanges;

// 一个区域(Range)对象将被加入选区。

sel.addRange(range);

});

2. 自适应高度

div contenteditable天然支持根据输入来自适应高度。

3. 粘贴图片,文本等

textarea.addEventListener( "paste", function(e) {

e.preventDefault;

constclipboardData = e.clipboardData || e.originalEvent.clipboardData;

// 获取纯文本

lettext = clipboardData.getData( "text/plain");

letfile = clipboardData.getData( "text/plain");

// console.log(clipboardData.items, clipboardData.getData("text/Files"));

// 插入img,可以做一些上传图片的一些操作

insertImg(clipboardData);

// 只输入纯文本

document.execCommand( "insertText", false, text);

});

此方法可以限定只能上传文本或者图片。

欢迎留言讨论其他 textarea高度自适应的方案。 返回搜狐,查看更多

责任编辑:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值