やりたいこと
値の長さに応じて幅が変わる input 要素を実装したい。
実装
/*
* fromElement から toElement にスタイルをコピーする。
*/
const copyComputedStyle = (fromElement, toElement, except = []) => {
const computedStyle = getComputedStyle(fromElement);
Array.from(computedStyle).forEach((key) => {
if (!except.includes(key)) {
const value = computedStyle.getPropertyValue(key);
const priority = computedStyle.getPropertyPriority(key);
toElement.style.setProperty(key, value, priority);
}
});
};
/*
* 文字列を HTML エスケープする。
*/
const escapeHTML = (text) => {
if (typeof text !== 'string') {
return text;
}
return text.replace(/[&'`"<> ]/g, (match) => {
return {
'&': '&',
"'": ''',
'`': '`',
'"': '"',
'<': '<',
'>': '>',
' ': ' '
}[match]
});
};
/*
* 仮の span 要素の innerHTML に input 要素の値を設定して width を計測する。
*/
const getTextWidth = (input) => {
// span 要素はなるべく input 要素と同じスタイルにする。
const span = document.createElement('span');
copyComputedStyle(input, span, ['display', 'width']);
span.style.maxWidth = '100vw';
span.innerHTML = escapeHTML(input.value);
document.body.appendChild(span);
const width = span.getBoundingClientRect().width;
document.body.removeChild(span);
return width;
};
const adjustWidth = (input) => {
input.style.width = `${getTextWidth(input)}px`;
};
const input = document.querySelector('input');
adjustWidth(input);
input.addEventListener('keyup', adjustWidth.bind(null, input));
デモ
デモ用画面の幅に余裕を持たせるため 0.5x で試すことをおすすめします。
See the Pen 伸び縮みするテキストボックス by QUANON (@quanon) on CodePen.
参考
-
Adjust width of input field to its input
- 全体的なアイディアとして参考にした。
-
Set / Copy javascript computed style from one element to another
- CSS によるスタイルを別の要素に適用する方法を参考にした。
-
JavaScriptでHTMLエスケープ処理
- Vanilla JS で文字列を HTML エスケープする方法を参考にした。
- MDN Web Docs
- Element.getComputedStyle()
- CSSStyleDeclaration
- [Element.getBoundingClientRect()] (https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect)