輸入框跟隨文字內容適配寬實現示例

實現源碼

// 常見一個輔助元素
const fakeEle = document.createElement('div');
// 隱藏輔助元素
fakeEle.style.position = 'absolute';
fakeEle.style.left = '-9999px';
fakeEle.style.visibility = 'hidden';
fakeEle.style.whiteSpace = 'nowrap';
// 獲取輸入框元素的樣式
const textboxEle = document.getElementById('textbox');
const styles = window.getComputedStyle(textboxEle);
// 將輸入框的字體樣式賦給輔助元素
fakeEle.style.font = styles.font;
// 將輔助元素添加到頁面
document.body.appendChild(fakeEle);
const setWidth = function () {
    const string = textboxEle.value || textboxEle.getAttribute('placeholder') || '';
    fakeEle.innerHTML = string.replace(/\s/g, ` `);
    // 獲取輔助元素的樣式
    const fakeEleStyles = window.getComputedStyle(fakeEle);
    // 將輔助元素的寬度賦給輸入框元素
    textboxEle.style.width = fakeEleStyles.width;
};
setWidth();
// 監聽輸入框元素內容變化,輸入框寬度跟隨文字內容數量適配
textboxEle.addEventListener('input', function (e) {
    setWidth();
});

大概思路

其實核心點就是,如何獲取輸入框元素內文字內容的寬度值?

直接通過輸入框元素肯定是無法獲取到其文字內容寬度的,我們需要跳出輸入框的限制,將文字內容獨立出來。

首先,我們肯定是能夠拿到輸入框的文字內容的,使用 input.value 即可獲取文字內容。

OK,文字內容有瞭,如何計算文字內容的寬度呢?

文字內容寬度

實現方案其實有 2 種,一種是使用 Canvas 的能力,另一種是使用輔助的 div 元素。

可能大部分同學還不是很瞭解 Canvas,所以本文就使用 div 元素的方式進行講解。

首先,先定義好最基礎的 HTML 和 CSS,代碼如下:

<input id="textbox" type="text" />
input {
  padding: 8px;
}

此時,我們會得到一個最基礎的輸入框元素,沒有任何文字內容。當我們往輸入框元素內輸入內容時,輸入框元素的寬度也不會跟隨變化。

然後通過 JavaScript 創建一個輔助的 div 元素,我們先將它添加到 body 元素內。

需要註意的是,文字內容的寬度會各被字體樣式、大小、行間距等等因素所影響。本文作為講解,暫時不考慮這麼多影響因素,但會通過影響因素之一 “字體” 相關做個相關示例,提供各位同學作為參考。

const fakeEle = document.createElement('div');
const textboxEle = document.getElementById('textbox');
// 獲取輸入框元素樣式
const styles = window.getComputedStyle(textboxEle);
// 將輸入框元素的 font 屬性賦給輔助的 div 元素
fakeEle.style.font = styles.font;
document.body.appendChild(fakeEle);

監聽輸入框元素的 input 事件,將文字內容同步給 div 輔助元素。

然後再反向的,獲取 div 輔助元素的寬度,賦值給輸入框元素,這樣是不是就實現瞭啦瞭?

const setWidth = function () {
  const string = textboxEle.value || '';
  fakeEle.innerHTML = string;
  // 獲取輔助元素的樣式
  const fakeEleStyles = window.getComputedStyle(fakeEle);
  // 將輔助元素的寬度賦給輸入框元素
  textboxEle.style.width = fakeEleStyles.width;
};
textboxEle.addEventListener('input', function (e) {
  setWidth();
});

我們來看看效果。

當我們在輸入框元素內隨便輸入一個內容,會發現輸入框就撐滿瞭整個頁面。

這是因為 div 輔助元素是塊級元素,寬度默認是 100% 所導致的。那如何要獲取文字內容寬度的話,要將它設置為行內元素嘛?

答案是不需要的,隻要給 div 輔助元素添加絕對定位,使其脫離正常文檔流即可。

// ...
fakeEle.style.position = 'absolute';
// ...

此時,我們會發現已經基本實現瞭我們想要的效果。

是的,我們已經解決瞭最核心的問題,但仍然還存在一些問題,需要我們進行處理。

細節處理

比如,輸入多個空格的時候,寬度計算就錯誤瞭。

這就需要我們將空格進行一下處理,將它替換成 &nbsp 即可,代碼如下:

// fakeEle.innerHTML = string;
fakeEle.innerHTML = string.replace(/\s/g, ` `);

還有,輔助元素不應該出現在界面上,所以我們要將他隱藏掉。

// ...
fakeEle.style.left = '-9999px';
fakeEle.style.visibility = 'hidden';
fakeEle.style.whiteSpace = 'nowrap';
// ...

還有一些其它小細節,有興趣的話,自己嘗試一下吧。

以上就是輸入框跟隨文字內容適配寬實現示例的詳細內容,更多關於輸入框文字內容寬度適配的資料請關註WalkonNet其它相關文章!

推薦閱讀: