
Jak udělat input s automatickou šířkou podle obsahu
Několik způsobů, jak dosáhnout toho, aby se textové pole rozšiřovalo a zužovalo podle délky zadaného textu.
Běžný <input> má pevnou šířku. Někdy je ale potřeba, aby se pole přizpůsobilo délce textu, který obsahuje – například v inline editoru, při úpravě tagů nebo v dynamických formulářích.
CSS řešení: field-sizing
Od roku 2024 prohlížeče podporují novou CSS vlastnost field-sizing, která tento problém řeší elegantně a bez JavaScriptu.
input {
field-sizing: content;
min-width: 50px;
max-width: 300px;
}
Vlastnost field-sizing: content způsobí, že se input automaticky rozšíří podle obsahu. Je vhodné přidat min-width a max-width pro rozumné limity.
Toto řešení funguje i pro <textarea> a <select>.
Podpora v prohlížečích
Vlastnost field-sizing podporují všechny moderní prohlížeče: Chrome 123+, Edge 123+, Firefox 132+ a Safari 18+.
Textarea
U <textarea> funguje field-sizing: content ještě lépe – element se automaticky zvětšuje jak na šířku, tak na výšku podle obsahu.
textarea {
field-sizing: content;
min-height: 1lh;
max-height: 10lh;
}
Jednotka lh odpovídá výšce řádku, takže max-height: 10lh omezí textarea na maximálně 10 řádků.
Tailwind CSS
V Tailwind CSS lze použít třídu field-sizing-content:
<input type="text" class="field-sizing-content min-w-12 max-w-xs" />
JavaScript řešení
Pro starší prohlížeče je potřeba použít JavaScript. Princip spočívá v měření šířky textu a nastavení šířky inputu.
Měření pomocí canvas
Nejpřesnější způsob je měřit text pomocí canvas:
function adjustInputWidth(input) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const style = getComputedStyle(input);
ctx.font = style.font;
const textWidth = ctx.measureText(input.value || input.placeholder).width;
const padding = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight);
const border = parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth);
input.style.width = Math.ceil(textWidth + padding + border + 2) + 'px';
}
// Použití
const input = document.querySelector('input');
input.addEventListener('input', () => adjustInputWidth(input));
adjustInputWidth(input);
Měření pomocí skrytého elementu
Alternativní způsob využívá skrytý <span> se stejným stylem:
function adjustInputWidth(input) {
const span = document.createElement('span');
span.style.cssText = `
position: absolute;
visibility: hidden;
white-space: pre;
font: ${getComputedStyle(input).font};
`;
span.textContent = input.value || input.placeholder || 'M';
document.body.appendChild(span);
input.style.width = span.offsetWidth + 'px';
span.remove();
}
const input = document.querySelector('input');
input.addEventListener('input', () => adjustInputWidth(input));
adjustInputWidth(input);
CSS jednotka ch
Pro jednoduché případy s monospace fontem lze využít CSS jednotku ch, která odpovídá šířce znaku „0”.
input {
font-family: monospace;
width: 10ch; /* šířka 10 znaků */
}
V kombinaci s JavaScriptem:
input.style.width = (input.value.length || 1) + 'ch';
Toto řešení nefunguje spolehlivě s proporcionálními fonty, kde mají znaky různou šířku („i” vs ”m").
Alternativa: contenteditable
Místo <input> lze použít element s atributem contenteditable, který se automaticky rozšiřuje:
<span contenteditable="true" role="textbox"></span>
[contenteditable] {
display: inline-block;
min-width: 50px;
padding: 4px 8px;
border: 1px solid #ccc;
border-radius: 4px;
}
Nevýhodou je, že contenteditable nepodporuje některé vlastnosti inputu jako placeholder, maxlength nebo validaci formuláře.
HTML atribut size
Nejjednodušší způsob je použít HTML atribut size, který určuje šířku v počtu znaků:
<input type="text" size="10">
V kombinaci s JavaScriptem:
input.addEventListener('input', () => {
input.size = Math.max(1, input.value.length);
});
Atribut size funguje podobně jako jednotka ch – počítá průměrnou šířku znaku. U proporcionálních fontů tak nebude kvůli různé šířce výsledek přesný.
CSS Grid trik
Čistě CSS řešení využívající display: grid a data-value atribut:
<label class="auto-input">
<input type="text" oninput="this.parentNode.dataset.value = this.value">
</label>
.auto-input {
display: inline-grid;
}
.auto-input::after,
.auto-input > input {
grid-area: 1 / 1;
}
.auto-input::after {
content: attr(data-value) ' ';
visibility: hidden;
white-space: pre;
}
.auto-input > input {
width: auto;
min-width: 1em;
}
Input a pseudo-element ::after sdílejí stejnou grid buňku. Pseudo-element je neviditelný, ale roztahuje kontejner podle obsahu.
Wrapper s absolutní posicí
Podobný princip – input překrývá span se stejným obsahem:
<span class="input-wrapper">
<span class="input-sizer"></span>
<input type="text">
</span>
.input-wrapper {
display: inline-block;
position: relative;
}
.input-sizer {
visibility: hidden;
white-space: pre;
padding: 0 2px;
}
.input-wrapper input {
position: absolute;
left: 0;
top: 0;
width: 100%;
}
const input = document.querySelector('input');
const sizer = document.querySelector('.input-sizer');
input.addEventListener('input', () => {
sizer.textContent = input.value || input.placeholder || 'M';
});
Výhodou je, že span používá přesně stejný font a velikost jako input, takže měření je přesné.
Doporučení
- Moderní prohlížeče – použijte
field-sizing: content(funguje ve všech). - Bez JavaScriptu – CSS Grid trik s
data-value. - Starší prohlížeče – přidejte JavaScript fallback (canvas nebo wrapper).
- Monospace fonty – stačí jednotka
chnebo atributsize. - Komplexní případy – zvažte
contenteditable.
/* Progresivní vylepšení */
input {
width: 150px; /* fallback */
}
@supports (field-sizing: content) {
input {
field-sizing: content;
min-width: 50px;
max-width: 300px;
}
}
Související články
HTTP metody GET a POST
Kdy použít metodu GET a kdy POST. Rozdíly mezi metodami, datové limity a doporučení pro správné použití.
Možnosti stylování <iframe>
Co lze a nelze u <iframe> ovlivnit pomocí CSS a jak na změnu textu nebo barev.
