3

CSS 自适应内容宽度的输入框

 2 years ago
source link: https://segmentfault.com/a/1190000041032322
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

通常我们见到的输入框都是宽度固定的,但有时也会碰到自适应内容宽度的,像这样

Kapture 2021-11-25 at 19.58.26

目前我所知道的有两种方式,相信不难找到

  1. 给普通 div 标签设置 contenteditable="true",设置 inline-block 以后,就可以自适应内容宽度了
  2. 将 input 的输入内容同步到一个透明的 div ,父级宽度跟随 div 的宽度,然后设置 input 为绝对定位并覆盖在上面,设置宽度为 100%

都是很不错的方案。这次带来一个全新的纯 CSS 实现方案,相信能带来不一样的感受

一、可替换元素

首先,input 不同于普通的 div 元素,它是一个可替换元素

在 CSS 中,可替换元素replaced element的展现效果不是由 CSS 来控制的。这些元素是一种外部对象,它们外观的渲染,是独立于 CSS 的。

正常情况下,如果希望一个元素宽度由内部决定,可以设置

div{
  display: inline-block;
}

在 CSS3 中,还可以通过另一种方式实现

div{
  width: fit-content;
}

还不太了解这个属性的可以参考这篇文章:理解CSS3 max/min-content及fit-content等width值 « 张鑫旭-鑫空间-鑫生活 (zhangxinxu.com)

但是,在 input 中,这些都不好使了,从开发者工具也可以看到,input 还有一层 shadow-root

image-20211127162956868

并且浏览器也没有暴露出相关的选择器供开发者使用,因此,仅仅通过常规方式是不能实现自适应内容宽度的

二、下划线样式

看到效果图中的输入框能想到什么?没错,就是下划线。下划线是文本修饰的一种,是跟随文字走的,所以去除 input 的边框后,加上下划线

input{
  border: 0;
  outline: 0;
  text-decoration: 4px solid underline;
}

Kapture 2021-11-28 at 11.53.35

下划线确实出来了,而且也是跟随输入内容的,不过有点贴的太紧了

三、下划线偏移

为了解决上述这个问题,需要用到一个新的 CSS 属性 text-underline-offset,表示下划线偏移位置。目前来说,兼容性还算不错,除了 IE,主流浏览器均支持了

image-20211128120100256

现在,给下划线偏移一点距离

input{
  /* */
  text-underline-offset: 10px;
}

下划线居然不见了!如下text-underline-offset 从 0px → 10px 的变化

Kapture 2021-11-28 at 12.40.08

这是由于内部尺寸的问题,下划线已经偏移出容器之外了,试着给 input 添加高度,比如

input{
  /* */
  height: 60px;
  text-underline-offset: 10px;
}

但是,没什么效果

image-20211128124645027

从开发者工具中可以看到,外面设置的高度并不能影响到内部尺寸,所以内部仍然是默认的高度

image-20211128121523848

那么,还有什么办法可以改变高度呢?

答案就是行高line-height

input{
  /* */
  line-height: 2;
  text-underline-offset: 10px;
}

行高属于文本属性,可以继承到内部,这样内部尺寸就直接被撑开了,下划线也可见了

Kapture 2021-11-28 at 12.21.05

四、默认最小宽度

由于使用的是下划线,当输入框没有内容时,或者仅仅只有 placeholder,下划线是不存在的,比如

<input placeholder="请输入...">

Kapture 2021-11-28 at 12.24.29

可能觉得有些不好看,希望加上一个最小宽度的下划线(当然需要设计来定夺)

这时,可以用线性渐变画一条下划线就可以了

input{
  background: linear-gradient(currentColor,currentColor) center bottom 6px no-repeat;
  background-size: 10rem 4px;
}

这样就有一个类似最小宽度的效果了

Kapture 2021-11-28 at 12.28.41

需要注意的是,下划线的位置和线性渐变的位置要保持一致

五、聚焦的样式

现在加上一点聚焦的样式,看起来更像一个输入边框,下划线需要改变颜色,然后刚才的线性渐变也需要改变颜色

input:focus{
  text-decoration-color: dodgerblue;
  background-image: linear-gradient(dodgerblue,dodgerblue)
}

这样就实现了文章开头的效果

Kapture 2021-11-25 at 19.58.26

完整代码可以访问:auto input (codepen.io)

六、总结和说明

以上介绍了一种全新的可以实现自适应内容宽度的纯 CSS 方案,用到了平时不太起眼的下划线相关样式,如果你的项目不用兼容 IE,也刚好有这方面的需求,就可以放心用起来了,不过,就算用不上,也可以学习一下思路。下面总结一下要点:

  1. input 是一个可替换元素
  2. 下划线是跟随文本的,而不是容器
  3. 现在有一个全新的 text-underline-offset 可以用来控制下划线的偏移
  4. 输入内容为空时下划线也就不存在了
  5. 利用 CSS 渐变可以绘制一个下划线
  6. 下划线颜色可以通过文本修饰颜色 text-decoration-color 修改

还有一个小细节时,input 其实是设置了宽度为 100% 的,也就是整行都可以输入,只是视觉上看着好像是下划线那一部分是输入框而已,算是一个小小的障眼法。如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK