阅读 598

Textarea 高度自适应原理

前言

我们平时在使用组件库的时候,input 相关的组件一般会有 autosize 这样的属性,设置以后使得文本域的高度能够根据文本内容自动进行调整,下面我们来看下是怎么实现的。

<el-input
  type="textarea"
  autosize
  placeholder="请输入内容"
  v-model="textarea1">
</el-input>
复制代码

原理

实现文本域的高度能够根据文本内容自动进行调整的思路很简单:监听输入相关的事件,获取到元素的内容高度,修改 textarea 的固定高度。

1. scrollHeight

scrollHeight 是元素的一个只读属性,表示是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。

scrollHeight 的值等于该元素在不使用滚动条的情况下为了适应视口中所有内容所需的最小高度。 没有垂直滚动条的情况下,scrollHeight值与元素视图填充所有内容所需要的最小值clientHeight相同。包括元素的padding,但不包括元素的bordermarginscrollHeight也包括 ::before::after这样的伪元素。

但是直接将 scrollHeight 设置为 textarea 的高度,是不是就可以了?这样是不行的,因为元素的 box-sizing 属性会影响到元素内容区高度的计算方式。

2. box-sizing

  • content-box 告诉浏览器:如果你设置一个元素的宽为100px,那么这个元素的内容区会有100px 宽,并且任何边框和内边距的宽度都会被增加到最后绘制出来的元素宽度中。所以元素宽度width + border + padding
  • border-box 告诉浏览器:如果你将一个元素的width设为100px,那么这100px会包含它的borderpadding内容区的实际宽度width减去(border + padding)的值。大多数情况下,这使得我们更容易地设定一个元素的宽高。

注: border-box不包含margin

对于 box-sizing 的获取,有一种方式是:

document.getElementById('demo').style.boxSizing
复制代码

但是这种方式获取到的 box-sizing 大多数情况是空的,因为只能够获取行内样式,若元素的行内样式中没有使用 box-sizing 就获取不到。

不过还有一种更合适的方式,就是下面的 getComputedStyle

3. getComputedStyle

window.getComputedStyle(el) 可以获取元素最终的样式,然后使用 getPropertyValue() 方法获取相应的属性值。

  const style = window.getComputedStyle(el)
  style.getPropertyValue('box-sizing')
复制代码

简单实现

这只是计算高度,我们还需要监听input事件,然后动态修改textarea的高度,这些代码比较简单,这里就不再赘述。

function calcTextareaHeight (el) {
  if (typeof el === 'string') {
    el = document.querySelector(el)
  }
  const attrs = ['box-sizing', 'padding-top', 'padding-bottom', 'border-top', 'border-bottom']
  let heightOffset = 0
  const style = window.getComputedStyle(el)
  const [boxSizing, paddingTop, paddingBottom, borderTop, borderBottom] = attrs.map(item => style.getPropertyValue(item))
  if (boxSizing === 'content-box') {
    heightOffset = -(parseFloat(paddingTop)) - parseFloat(paddingBottom)
  } else {
    heightOffset = parseFloat(borderTop)  + parseFloat(borderBottom)
  }
  let height = el.scrollHeight + heightOffset
  return height;
}
复制代码

参考

文章分类
前端
文章标签