初步实现代码以下:javascript
textarea { width: 100%; height: 92px; padding: 20px; line-height: 50px; resize: none; outline: none; border: 1px solid #ccc; background: #eee; font-size: 32px; box-sizing: border-box; } 复制代码
<textarea id="textarea"></textarea> 复制代码
var $textarea = document.getElementById('textarea'); $textarea.addEventListener('input', function() { // 总高度 = scrollHeight + 上下边框的宽度(1px * 2) $textarea.style.height = $textarea.scrollHeight + 2 + 'px'; }); 复制代码
然而,当内容高度缩减时,输入框的高度并无跟随缩减。css
因为根据scrollHeight设置的元素高度的存在,即便内容高度缩减,此时scrollHeight也不会低于元素高度。因此,在作自适应高度缩减时就没法直接经过同步scrollHeight来实现,而是要先清掉高度样式:html
$textarea.addEventListener('input', function() { // 清除原来高度 $textarea.style.height = ''; $textarea.style.height = $textarea.scrollHeight + 2 + 'px'; }); 复制代码
实现后发现,输入到临近换行处,内容高度提早增高了。java
调试后发现,清掉高度样式后,textarea恢复到原来的高度,此时内容超过textarea高度,所以会出现滚动条。滚动条会占据必定的空间,致使一行能容纳的字符减小,因而就提早换行了(以下图所示)。而由于在清理高度样式后,又马上把高度设为新的scrollHeight,因此在界面上没有体现出现。web
要解决这个问题,只须要把滚动条隐藏掉。post
textarea { overflow: hidden; } 复制代码
虽然功能是作出来了,可是性能上还有优化的余地。由于当前的作法,至关于每次输入都要同步高度。若是高度没有发生变化,这个同步操做是没有意义的。因此,优化的思路就在于如何检查内容高度是否发生了变化:性能
实现代码以下:优化
var $textarea = document.getElementById('textarea'); var lastLength = 0; var lastHeight = 0; $textarea.addEventListener('input', function() { var currentLength = $textarea.value.length; // 判断字数若是比以前少了,说明内容正在减小,须要清除高度样式,从新获取 if (currentLength < lastLength) { $textarea.style.height = ''; } var currentHeight = $textarea.scrollHeight; // 若是内容高度发生了变化,再去设置高度值 if (lastHeight !== currentHeight || !$textarea.style.height) { $textarea.style.height = currentHeight + 2 + 'px'; } lastLength = currentLength; lastHeight = currentHeight; });