Explain Codes LogoExplain Codes Logo

Auto-scaling input

javascript
responsive-design
performance
best-practices
Nikita BarsukovbyNikita Barsukov·Dec 8, 2024
TLDR

Easily adapt an <input type="text"> size using:

document.getElementById('input').oninput = function() { this.style.width = ((this.value.length + 1) * 8) + 'px'; };

This is linked to <input id="input">. The input width expands with the content due to multiplying the value's length by character pixel width. Adjust '8' to suit your preferred font size.

The JavaScript Method

const input = document.querySelector('#input'); input.oninput = function() { // Measuring text width like a savant here with a span const textWidth = getTextWidth(this.value, window.getComputedStyle(this).font); // Because protocol isn't anything without a + 4 buffer this.style.width = (textWidth + 4) + 'px'; };

Font, Padding, and Borders

Adjusting for Styles

Consider padding and borders:

input.oninput = function() { const style = window.getComputedStyle(this); const padding = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight); const border = parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth); // padding & border have entered the chat this.style.width = (getTextWidth(this.value, style.font) + padding + border + 4) + 'px'; };

Font Size Adjustment

When space becomes a premium, adjust the font size to fit content:

const minWidth = 100; const maxWidth = 600; input.oninput = function() { this.style.width = Math.max(minWidth, Math.min(maxWidth, (getTextWidth(this.value, style.font) + padding + border + 4))) + 'px'; this.style.fontSize = ((this.offsetWidth >= maxWidth) ? '75%' : '100%'); // 75% when we're outta space };

CSS Markup and Hidden Divs

Percentage Width with CSS

Pure CSS enthusiasts, here's an approach for you:

.input-wrapper { width: 100%; } .input-wrapper input { width: 100%; }

Nest the <input> inside a div tagging along a percentage width. It'll happily grow and shrink with the div.

The Hidden Div Trick

Copy the input's styles onto a concealed div:

input.oninput = function() { const ghostDiv = document.getElementById('ghost'); ghostDiv.innerHTML = this.value.replace(/ /g, "&nbsp;"); const newWidth = ghostDiv.offsetWidth + 4; // Ghost whispering width this.style.width = newWidth + 'px'; };
<div id="ghost" style="display: none; white-space: pre;"></div>

An All-Out Plugin War and Contenteditable

Using jQuery Plugin for Auto-resize

Also, jQuery plugins like Autosize could come in handy. Best suited for those currently employing jQuery.

Be Wise with Contenteditable

Alternatively, dare to venture into the contenteditable span land:

<span contenteditable="true" oninput="resizeSpan(this)"></span>

But remember, sanitize your input to avoid unwanted XSS battles.

Fine-tuning and Balancing Acts

Care for Trailing Space

Consider trailing whitespace:

ghostDiv.innerHTML = this.value.replace(/ /g, "&nbsp;") + "&nbsp;";

Placeholder Styling

Match your placeholder's style to the actual input. This ensures a smooth transition:

input::placeholder { color: #ccc; opacity: 1; /* Wonderful Firefox */ }

Focus Styling and Browsers Quirks

Implement :focus-visible for improved input UX.

Lastly, brace for browser-specific differences— don’t let those padding and rendering differences catch you off-guard!