巧妙實(shí)現(xiàn)自適應(yīng)寬度的內(nèi)容輸入框
本文由閱文大佬 XBOXYAN 授權(quán)原創(chuàng)轉(zhuǎn)發(fā)?
原文鏈接:https://juejin.cn/post/7035819149016170510
通常我們見(jiàn)到的輸入框都是寬度固定的,但有時(shí)也會(huì)碰到自適應(yīng)內(nèi)容寬度的,像這樣

目前我所知道的有兩種方式,相信不難找到
給普通 div 標(biāo)簽設(shè)置 contenteditable="true",設(shè)置 inline-block 以后,就可以自適應(yīng)內(nèi)容寬度了 將 input 的輸入內(nèi)容同步到一個(gè)透明的 div ,父級(jí)寬度跟隨 div 的寬度,然后設(shè)置 input 為絕對(duì)定位并覆蓋在上面,設(shè)置寬度為 100%
都是很不錯(cuò)的方案。這次帶來(lái)一個(gè)全新的純 CSS 實(shí)現(xiàn)方案,相信能帶來(lái)不一樣的感受
一、可替換元素
首先,input 不同于普通的 div 元素,它是一個(gè)可替換元素
在 CSS 中,**可替換元素**(**replaced element**)[1]的展現(xiàn)效果不是由 CSS 來(lái)控制的。這些元素是一種外部對(duì)象,它們外觀的渲染,是獨(dú)立于 CSS 的。
正常情況下,如果希望一個(gè)元素寬度由內(nèi)部決定,可以設(shè)置
div{
??display:?inline-block;
}
在 CSS3 中,還可以通過(guò)另一種方式實(shí)現(xiàn)
div{
??width:?fit-content;
}
還不太了解這個(gè)屬性的可以參考這篇文章:理解CSS3 max/min-content及fit-content等width值 ? 張?chǎng)涡?鑫空間-鑫生活 (zhangxinxu.com)[2]
但是,在 input 中,這些都不好使了,從開(kāi)發(fā)者工具也可以看到,input 還有一層 shadow-root

并且瀏覽器也沒(méi)有暴露出相關(guān)的選擇器供開(kāi)發(fā)者使用,因此,僅僅通過(guò)常規(guī)方式是不能實(shí)現(xiàn)自適應(yīng)內(nèi)容寬度的
二、下劃線樣式
看到效果圖中的輸入框能想到什么?沒(méi)錯(cuò),就是下劃線。下劃線是文本修飾[3]的一種,是跟隨文字走的,所以去除 input 的邊框后,加上下劃線
input{
??border:?0;
??outline:?0;
??text-decoration:?4px?solid?underline;
}
效果如下

下劃線確實(shí)出來(lái)了,而且也是跟隨輸入內(nèi)容的,不過(guò)有點(diǎn)貼的太緊了
三、下劃線偏移
為了解決上述這個(gè)問(wèn)題,需要用到一個(gè)新的 CSS 屬性 text-underline-offset,表示下劃線偏移位置。目前來(lái)說(shuō),兼容性還算不錯(cuò),除了 IE,主流瀏覽器均支持了

現(xiàn)在,給下劃線偏移一點(diǎn)距離
input{
??/*?*/
??text-underline-offset:?10px;
}
下劃線居然不見(jiàn)了!如下text-underline-offset 從 0px → 10px 的變化

這是由于內(nèi)部尺寸的問(wèn)題,下劃線已經(jīng)偏移出容器之外了,試著給 input 添加高度,比如
input{
??/*?*/
??height:?60px;
??text-underline-offset:?10px;
}
但是,沒(méi)什么效果

從開(kāi)發(fā)者工具中可以看到,外面設(shè)置的高度并不能影響到內(nèi)部尺寸,所以內(nèi)部仍然是默認(rèn)的高度

那么,還有什么辦法可以改變高度呢?
答案就是行高line-height!
input{
??/*?*/
??line-height:?2;
??text-underline-offset:?10px;
}
行高屬于文本屬性,可以繼承到內(nèi)部,這樣內(nèi)部尺寸就直接被撐開(kāi)了,下劃線也可見(jiàn)了

四、默認(rèn)最小寬度
由于使用的是下劃線,當(dāng)輸入框沒(méi)有內(nèi)容時(shí),或者僅僅只有 placeholder,下劃線是不存在的,比如
<input?placeholder="請(qǐng)輸入...">
效果如下

可能覺(jué)得有些不好看,希望加上一個(gè)最小寬度的下劃線(當(dāng)然需要設(shè)計(jì)來(lái)定奪)
這時(shí),可以用線性漸變畫(huà)一條下劃線就可以了
input{
??background:?linear-gradient(currentColor,currentColor)?center?bottom?6px?no-repeat;
??background-size:?10rem?4px;
}
這樣就有一個(gè)類(lèi)似最小寬度的效果了

需要注意的是,下劃線的位置和線性漸變的位置要保持一致
五、聚焦的樣式
現(xiàn)在加上一點(diǎn)聚焦的樣式,看起來(lái)更像一個(gè)輸入邊框,下劃線需要改變顏色,然后剛才的線性漸變也需要改變顏色
input:focus{
??text-decoration-color:?dodgerblue;
??background-image:?linear-gradient(dodgerblue,dodgerblue)
}
這樣就實(shí)現(xiàn)了文章開(kāi)頭的效果

完整代碼可以訪問(wèn):auto input (codepen.io)[4]
六、總結(jié)和說(shuō)明
以上介紹了一種全新的可以實(shí)現(xiàn)自適應(yīng)內(nèi)容寬度的純 CSS 方案,用到了平時(shí)不太起眼的下劃線相關(guān)樣式,如果你的項(xiàng)目不用兼容 IE,也剛好有這方面的需求,就可以放心用起來(lái)了,不過(guò),就算用不上,也可以學(xué)習(xí)一下思路。下面總結(jié)一下要點(diǎn):
input 是一個(gè)可替換元素 下劃線是跟隨文本的,而不是容器 現(xiàn)在有一個(gè)全新的 text-underline-offset可以用來(lái)控制下劃線的偏移輸入內(nèi)容為空時(shí)下劃線也就不存在了 利用 CSS 漸變可以繪制一個(gè)下劃線 下劃線顏色可以通過(guò)文本修飾顏色 text-decoration-color修改
還有一個(gè)小細(xì)節(jié)時(shí),input 其實(shí)是設(shè)置了寬度為 100% 的,也就是整行都可以輸入,只是視覺(jué)上看著好像是下劃線那一部分是輸入框而已,算是一個(gè)小小的障眼法。如果覺(jué)得還不錯(cuò),對(duì)你有幫助的話,歡迎點(diǎn)贊、收藏、轉(zhuǎn)發(fā)???
參考資料
可替換元素(replaced element): https://developer.mozilla.org/zh-CN/docs/Web/CSS/Replaced_element
[2]理解CSS3 max/min-content及fit-content等width值 ? 張?chǎng)涡?鑫空間-鑫生活 (zhangxinxu.com): https://www.zhangxinxu.com/wordpress/2016/05/css3-width-max-contnet-min-content-fit-content/
[3]文本修飾: https://developer.mozilla.org/zh-CN/docs/Web/CSS/text-decoration
[4]auto input (codepen.io): https://codepen.io/xboxyan/pen/gOGYWRG

