高度自适应的输入框

  有时候我们需要一个高度能随内容自动增加的输入框,input 显然不行,因为 input 里的文字是不换行的。文本域 textarea 里的文字倒是换行的,可一旦文字内容超过其高度,textarea 就会增加一个烦人的滚动条,这是很影响视觉的,就如同下面:

  那么有没有办法制作一个高度能随文字内容自动增加的输入框呢?答案是肯定的,下面介绍两种方式。

方式一

  这种方式依然使用 textarea, 主要思想是我们将 textarea 放入一个容器中,同时在这个容器中放入一个隐藏的 div (visibility: hidden), 监听 textarea 的输入事件并将其中的文字动态的同步到隐藏的div中,这样div 就可以撑开容器,这时设置 textarea 的高度为 100% 并将其定位到容器的左上角,那么 textarea 的高度自然就是其中文字内容的高度了。

visibility 是一个CSS属性,用来在不更改文档的布局的前提下显示或隐藏元素,它有三个可能的取值:

  1. visible 元素正常显示(默认值);
  2. hidden 隐藏元素,但是其他元素的布局不改变,相当于此元素变成透明。
      若将其子元素设为 visibility: visible,则该子元素依然可见;
  3. collapse 用于表格的行、列、列组和行组,隐藏表格的行或列,并且不占用任何空间。
   

   

查看样例:https://mxsyx.site/archives/10/#demo-1

  你可能已经注意到了,当我们输入文字时,输入框的高度显然要比文字内容高许多,伴随着输入文字的增多。高度差会越来越大,这是因为隐藏 div 与 文本域 textarea 内字体的尺寸与行高是不同的, div 内的字体尺寸与行高要比 textarea 内的大,所以 div 撑开的容器高度自然要高于 textarea 内的文字内容高度。要解决这个问题,统一它们的字体尺寸与行高就可以了。(注:div 的字体尺寸与行高默认继承自父元素)

   

   

查看样例:https://mxsyx.site/archives/10/#demo-2

  这样一来高度就一致了。这种方式虽然可以较好的实现高度自适应的输入框,但实现起来总感觉很粗糙,下面这种方式就明显简单多了。

方式二

  像 div, p, blockquote 这样的元素默认是不可编辑的,但我们可以将其 contenteditable 属性设置为 true, 使其变为可编辑的。

contenteditable是一个全局属性,用于指示元素是否可被用户编辑,该属性必须采用以下值之一:

  1. true 或者 '空字符串', 表示该元素是可编辑的;
  2. false, 表示该元素是不可编辑的。
  3. 如果未设置此属性,则其默认值将从其父元素继承。
  

尝试输入一段文字吧:


  是不是很简单呢? 我们也可以使用CSS伪类 :empty, :focus, 实现placeholder 那样的效果

尝试输入一段文字吧:


  如果你使用 Vue.js, 我们也可以它封装为一个Vue组件:





接下来在父组件中引用这个组件:



  父组件为子组件使用 v-model 指令,将子组件的 value 与 父组件的 msg 双向绑定在一起。当输入事件发生后,子组件调用changeText方法,触发一个 input 事件,父组件监听到此事件,将事件传递过来的数据同步到 msg 上,由于数据是双向绑定的,子组件的 value 值也会相应发生变化。更过原理请参考 自定义组件的-v-model

该篇博客内的代码已同步到Github

参考资料:
[1]. MDN文档 https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes/contenteditable
[2]. MDN文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/visibility
[3]. MDN文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/:empty
[4]. MDN文档 https://developer.mozilla.org/zh-CN/docs/Web/CSS/:focus
[5]. Vue.js官方文档 https://cn.vuejs.org/v2/guide/components-custom-events.html#自定义组件的-v-model

你可能感兴趣的:(高度自适应的输入框)