思路:监听textarea的input事件获取到value值,将value值展示的内容添加到div中,将div的高度给到textarea元素以实现高度自适应。
注意:div元素对于空格和换行于输入框存在不同,需要对value值做处理(可以通过JSON.stringify()可检验value值); textarea与div容器的样式需要保持一致
思路一:div中创建span完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>输入框高度自适应</title>
<style>
/* 取消滚动条的样式带来的影响 */
::-webkit-scrollbar {
width: 0px;
height: 0px;
}
#textarea,
#textareaSpan {
width: 500px;
font-size: 20px;
font-weight: 40;
font-family: monospace;
padding: 0;
resize: none;
word-break: break-all;
white-space: normal;
overflow-y: auto;
border-radius: 5px;
background: pink;
/* 去掉点击输入框时的默认边框 */
outline: none;
/* 边框颜色变化过渡效果 */
transition: border-color 0.3s;
}
#textarea:focus {
border: 1px solid #168fd4;
}
#textareaSpan span {
/* 开启块级元素实现内容换行 */
display: block;
}
</style>
</head>
<body>
<textarea id="textarea" rows="1"></textarea>
<div id="textareaSpan"></div>
</body>
<script>
// 获取元素对象
let inputEl = document.getElementById('textarea');
let inputSpan = document.getElementById('textareaSpan');
// 监听输入事件
inputEl.addEventListener('input', function () {
// 对输入框内容进行处理
let text = this.value.replaceAll(' ', '1').replaceAll('\n$', '\n1') || '1';
// 将文本分割成数组
let textList = text.split('\n');
// 创建span标签组
let spanList = textList.map(item => `<span>${item}</span>`);
// 将span标签组转化为html语言并插入到div中
inputSpan.innerHTML = spanList.join('');
// 修改输入框的的高度为div容器的高度
this.style.height = inputSpan.scrollHeight + 'px';
// 清空div容器组--(如果想测试可以注释以下代码)
inputSpan.innerHTML = '';
})
// 给String原型上添加replaceAll方法-全部替换(部分浏览器不自带)
String.prototype.replaceAll = function (s1, s2) {
return this.replace(new RegExp(s1, "gm"), s2)
}
</script>
</html>
思路二:div开启富文本编辑完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>输入框高度自适应</title>
<style>
/* 取消滚动条的样式带来的影响 */
::-webkit-scrollbar {
width: 0px;
height: 0px;
}
#textarea,
#inputDiv {
width: 500px;
font-size: 20px;
font-weight: 40;
font-family: monospace;
padding: 0;
resize: none;
word-break: break-all;
white-space: normal;
overflow-y: auto;
border-radius: 5px;
background: pink;
/* 去掉点击输入框时的默认边框 */
outline: none;
/* 边框颜色变化过渡效果 */
transition: border-color 0.3s;
}
#textarea:focus {
border: 1px solid #168fd4;
}
</style>
</head>
<body>
<textarea id="textarea" rows="1"></textarea>
<div id="inputDiv" contenteditable="true"></div>
</body>
<script>
// 获取元素对象
let inputEl = document.getElementById('textarea');
let inputDiv = document.getElementById('inputDiv');
// 监听输入事件
inputEl.addEventListener('input', function () {
// 对输入框内容进行处理
let text = this.value.replaceAll(' ', '1').replaceAll('\n$', '\n1') || '1';
// 将处理后的内容赋值给div容器
inputDiv.innerText = text;
// 设置输入框高度与div容器的高度一致
textarea.style.height = inputDiv.clientHeight + 'px';
// 清空div容器组--(如果想测试可以注释以下代码)
inputDiv.innerText = '';
})
// 给String原型上添加replaceAll方法-全部替换(部分浏览器不自带)
String.prototype.replaceAll = function (s1, s2) {
return this.replace(new RegExp(s1, "gm"), s2)
}
</script>
</html>
我看也有推荐直接使用div直接开启富文本来实现高度自适应,但是遇到的情况是粘贴的是元素内容,会保留复制时的样式,需要处理。类似于文档编辑类型的输入区域带有原本样式可能会方便点
对于直接使用div富文本方法可以对输入框的粘贴事件进行监听
<div class="inputDiv" contenteditable="true"></div>
<script>
let inputDiv = document.querySelector('.inputDiv');
// 监听输入框的粘贴事件
inputDiv.addEventListener('paste', function inputText(event) {
// 阻止默认粘贴行为
event.stopPropagation();
event.preventDefault();
// 获取粘贴的文本内容
let clipboardData = event.clipboardData || window.clipboardData;
let pastedData = clipboardData.getData('Text');
console.log('Pasted text: ', pastedData);
// 将粘贴的文本内容插入到输入框中
inputDiv.innerHTML = pastedData.replace(/\n/g, '<br>').replace(/\s/g, ' ');
});
</script>