文本框是很罕见的输入控件,我置信只需写过表单的一定打仗过 textarea 这个元素。
OK。然则如今产物司理说了:须要这个文本框能够依据用户输入内容自适应其高度。
height: auto
有些初学者能够会想:自适应高度不就是 height: auto
么?但是你想一下,一个 textarea
没有手工给它指定过款式,不应该就默许是 height: auto
么?然则它照样有本身的初始高度,并没有像一个 div
那样高度为 0。
与 div
差别,textarea
的默许高度不是依据其内容自适应,而是由属性 rows 指定,其默许值是 2
。rows
这个属性(Attribute)只接收正整数,指定其他值浏览器会疏忽掉其值,比方你写 rows="auto"
那末 rows
就是 2,rows="0"
也是 2。
所以指定 height: auto
是行不通的,height
属性必需人工指定其值。
scrollHeight
遇到过这个题目的同砚(比方当初的笔者),一定想到过 scrollHeight
这个 DOM 属性。主意很简朴,当用户输入的文本凌驾了文本框本身高度时不是会涌现滚动条嘛,那末自然而然就可以想到 scrollHeight 这个属性。scrollHeight
就应该是用户输入文本的实在高度,最少凌驾文本框既定高度时是如许。
那末题目来了:假如没凌驾呢?
OK 我晓得你会先指定 rows="1"
让文本框默许高度只要一行。然则斟酌这类状况:用户先输入了许多行文本
然后删除了一段:
scrollHeight
值没有变化。MDN 上说了:
没有垂直滚动条的状况下,scrollHeight值与元素视图添补一切内容所须要的最小值clientHeight雷同
scrollHeight
确切会跟着用户输入内容若干而增减,然则仅限于涌现滚动条的状况,关于题设这个状况必定不实用,由于需求就是不能涌现滚动条(严格来说是超越可视地区)。你能够在猎取 scrollHeight
的值之前先把文本框高度设为 0 强迫让滚动条涌现,然则如许能够使页面发作闪灼,而且机能也低。
split(‘\n’)
DOM 属性靠不住,那我本身算文本高度不行吗?说我拿出一切文本,按换行符拆分,看有若干行,行数 * 行高
不就是终究文本高度吗?
额。。。当文本没有折行的状况下是如许。。。
contenteditable
contenteditable 确切是一个(相对)可行的计划,然则作为一个踩过坑的先行者劝慰你:不到万不得已,contenteditable 不要碰。这个玩意各个浏览器完成都不一样,种种奇葩行动,光一个换行符就充足熬煎你半天。
固然这里还没有到那末庞杂的田地,然则你得先会把“复制——粘贴”过去的款式去掉才行
笔者的要领
说了那末多空话,那末终究该怎么办呢?这里笔者供应一种要领。
固然起首声明:笔者的要领未必是最简朴的,若有别的更简朴的计划迎接留言提出。
我们想一下,textarea
不能根据内容自适应高度,div
能够啊,能不能先把文本填到一个 div
里,div
的高度就应该是文本框所需高度(当 padding
、line-height
等款式都一致的状况下),这时候猎取 div
的高度赋值给文本框高度不就行了吗。
就是如许的思绪。我们也不须要特地运用 JS 猎取,只需让 div
把父元素撑起来,相对定位 textarea
元素让文本框占满全部父元素大小就好了。
直接上代码:
<style>
#parent {
width: 500px;
font: 12px monospace;
position: relative;
}
#dummy {
padding: 2px;
border: 1px solid;
visibility: hidden;
}
#dummy::after {
content: "\A";
}
#textarea {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
resize: none;
width: 100%;
font: inherit;
}
</style>
<div id="parent">
<div id="dummy"></div>
<textarea id="textarea"
oninput="document.getElementById('dummy').textContent = this.value"></textarea>
</div>
这里检察运转效果:https://codepen.io/CarterLi/p…
三个要点:
- 字体相干款式
#dummy
和textarea
两元素必需完全一致,差一点就可以够涌现二者高度对不上的状况。 -
#dummy
中white-space: pre-wrap
能干。不然会涌现 HTML 中吞空格、换行符的状况。 - 就算有了
white-space: pre-wrap
,HTML 仍然会吞掉末了的换行符。解决计划是在#dummy
末了插进去一个换行符元素。能够是<br />
,也能够是一个伪元素。伪元素中换行符的写法是\A
(即换行符的 ASCII 码 10 的十六进制示意。不能写\n
)
代码中是用 JS 给 #dummy
赋值。项目中假如你用 vuejs
或 angular
等 MVVM 框架,直接把文本框的值绑定到 div
上就好,异常轻易。
假如你要限定文本框的最大最小高度,在 #dummy
上直接设置 min-height
max-height
即可。
完
末了说一句:把 textarea
盖到一个 div
上的做法还能够简朴的完成文本框的语法高亮,读者能够想一想怎么做。