资讯专栏INFORMATION COLUMN

编写自适应高度的 textarea

wenzi / 2316人阅读

摘要:但是现在产品经理说了需要这个文本框可以根据用户输入内容自适应其高度。想法很简单,当用户输入的文本超过了文本框自身高度时不是会出现滚动条嘛,那么自然而然就能想到这个属性。就应该是用户输入文本的真实高度,至少超过文本框既定高度时是这样。

文本框是很常见的输入控件,我相信只要写过表单的肯定接触过 textarea 这个元素。

OK。但是现在产品经理说了:需要这个文本框可以根据用户输入内容自适应其高度。

height: auto

有些初学者可能会想:自适应高度不就是 height: auto 么?可是你想一下,一个 textarea 没有手工给它指定过样式,不应该就默认是 height: auto 么?但是它还是有自己的初始高度,并没有像一个 div 那样高度为 0。

div 不同,textarea 的默认高度不是根据其内容自适应,而是由属性 rows 指定,其默认值是 2rows 这个属性(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(" ")

DOM 属性靠不住,那我自己算文本高度不行吗?说我拿出所有文本,按换行符拆分,看有多少行,行数 * 行高 不就是最终文本高度吗?

额。。。当文本没有折行的情况下是这样。。。

contenteditable

contenteditable 确实是一个(相对)可行的方案,但是作为一个踩过坑的先行者劝解你:不到万不得已,contenteditable 不要碰。这个玩意各个浏览器实现都不一样,各种奇葩行为,光一个换行符就足够折磨你半天。

当然这里还没有到那么复杂的地步,但是你得先会把“复制——粘贴”过去的样式去掉才行

笔者的方法

说了那么多废话,那么究竟该怎么办呢?这里笔者提供一种方法。

当然首先声明:笔者的方法未必是最简单的,如有其它更简单的方案欢迎留言提出。

我们想一下,textarea 不能按照内容自适应高度,div 可以啊,能不能先把文本填到一个 div 里,div 的高度就应该是文本框所需高度(当 paddingline-height 等样式都一致的情况下),这时获取 div 的高度赋值给文本框高度不就行了吗。

就是这样的思路。我们也不需要专门使用 JS 获取,只要让 div 把父元素撑起来,绝对定位 textarea 元素让文本框占满整个父元素大小就好了。

直接上代码:


这里查看运行结果:https://codepen.io/CarterLi/p...

三个要点:

字体相关样式 #dummytextarea 两元素必须完全一致,差一点就可能出现两者高度对不上的情况。

#dummywhite-space: pre-wrap 醒目。否则会出现 HTML 中吞空格、换行符的情况。

就算有了 white-space: pre-wrap,HTML 仍然会吞掉最后的换行符。解决方案是在 #dummy 最后插入一个换行符元素。可以是
,也可以是一个伪元素。伪元素中换行符的写法是 A(即换行符的 ASCII 码 10 的十六进制表示。不能写

代码中是用 JS 给 #dummy 赋值。项目中如果你用 vuejsangular 等 MVVM 框架,直接把文本框的值绑定到 div 上就好,非常方便。

如果你要限制文本框的最大最小高度,在 #dummy 上直接设置 min-height max-height 即可。

最后说一句:把 textarea 盖到一个 div 上的做法还可以简单的实现文本框的语法高亮,读者可以想想怎么做。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/53721.html

相关文章

  • 编写适应高度 textarea

    摘要:但是现在产品经理说了需要这个文本框可以根据用户输入内容自适应其高度。想法很简单,当用户输入的文本超过了文本框自身高度时不是会出现滚动条嘛,那么自然而然就能想到这个属性。就应该是用户输入文本的真实高度,至少超过文本框既定高度时是这样。 文本框是很常见的输入控件,我相信只要写过表单的肯定接触过 textarea 这个元素。 OK。但是现在产品经理说了:需要这个文本框可以根据用户输入内容自适...

    only_do 评论0 收藏0
  • 编写适应高度 textarea

    摘要:但是现在产品经理说了需要这个文本框可以根据用户输入内容自适应其高度。想法很简单,当用户输入的文本超过了文本框自身高度时不是会出现滚动条嘛,那么自然而然就能想到这个属性。就应该是用户输入文本的真实高度,至少超过文本框既定高度时是这样。 文本框是很常见的输入控件,我相信只要写过表单的肯定接触过 textarea 这个元素。 OK。但是现在产品经理说了:需要这个文本框可以根据用户输入内容自适...

    yeooo 评论0 收藏0
  • 创建一个高度适应textarea

    摘要:今天的任务是生成一个高度自适应的而且也可以设置最小高度和最大高度。但是有一个问题当想从大变到小的时候,这个不能反映文字的实际高度,所以这个方法不是很适合。高度跟着文字的多少走的,而且不需要动画。用的方式生成一个无用的用来计算的高度。 今天的任务是生成一个高度自适应的textarea,而且也可以设置最小高度和最大高度。最简单的方法textarea的属性是overflow:auto;那么如...

    BLUE 评论0 收藏0
  • 使用contenteditable+div模拟textarea文本域实现高度适应

    摘要:使用该组件注意一个问题就是不要在可视化区域的节点上使用样式,否则会出现当鼠标焦点小时光标和小水滴无法消失的情况地址项目地址参考链接模拟文本域轻松实现高度自适应如何让元素只能输入纯文本 使用contenteditable+div模拟textarea文本域实现高度自适应 开发过程中由于需要在发送消息的时候需要有一个可以高度自适应的文本域,一开始是使用textarea并搭配auto-size...

    seasonley 评论0 收藏0
  • 使用contenteditable+div模拟textarea文本域实现高度适应

    摘要:使用该组件注意一个问题就是不要在可视化区域的节点上使用样式,否则会出现当鼠标焦点小时光标和小水滴无法消失的情况地址项目地址参考链接模拟文本域轻松实现高度自适应如何让元素只能输入纯文本 使用contenteditable+div模拟textarea文本域实现高度自适应 开发过程中由于需要在发送消息的时候需要有一个可以高度自适应的文本域,一开始是使用textarea并搭配auto-size...

    Olivia 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<