I want to create a textbox with the following requirements:

width: 16 columns (characters) height: 3 lines max chars: 48 lines should always break after 16 characters, no matter what char has been entered

The best I have come up with is this solution:

.text-input { font-family: monospace; font-size: 2em; border: 1px solid black; resize: none; padding: 0.4em; width: calc(1ch * 16); height: calc(1.4em * 3 + 2px); white-space: break-spaces; word-break: break-all; } <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>1234567812345678</textarea> <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>1234567812345678 </textarea> <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>this is some random text</textarea>

However, I am facing a problem. If exactly 16 characters followed by a space character are entered, the last two chars (in my example the 8 and the space) jump down to the next line (see middle box in the snippet). I want the "8" (the 16th char) to remain on the first line, whereas the space (the 17th char) breaks down to the next line. This problem occurs with most browsers, however Firefox 147.0.2 is behaving correctly. Any ideas?

KIKO Software's user avatar

KIKO Software

17.5k3 gold badges33 silver badges53 bronze badges

g000ze's user avatar

4

To achieve this enforces a 16×3 character grid in a <textarea> by using overflow-wrap: anywhere to allow breaks at any point, combined with box-sizing: content-box so the width matches exactly 16 characters. maxlength="48" limits input, and spellcheck="false" prevents browser highlights from shifting alignment. Manual newlines are blocked to maintain consistent character flow.

const textarea = document.getElementById('fixed-textarea'); textarea.addEventListener('input', (e) => { // Remove any manual line breaks the user might press // to keep the 16-character flow strictly automatic const start = textarea.selectionStart; const end = textarea.selectionEnd; const currentVal = textarea.value; const sanitizedVal = currentVal.replace(/\r?\n|\r/g, ''); if (currentVal !== sanitizedVal) { textarea.value = sanitizedVal; // Reset cursor position after sanitization textarea.setSelectionRange(start - 1, end - 1); } }); .text-input { font-family: monospace; font-size: 2em; border: 1px solid black; resize: none; padding: 0.4em; /* Use content-box so width is exactly 16 characters */ box-sizing: content-box; width: 16ch; /* Height based on line-height * 3 */ line-height: 1.2; height: 3.6em; /* Force breaks */ white-space: pre-wrap; word-break: break-all; overflow-wrap: anywhere; overflow: hidden; } <textarea class="text-input" id="fixed-textarea" rows="3" cols="16" maxlength="48" spellcheck="false" autofocus>1234567812345678</textarea> <textarea class="text-input" id="fixed-textarea" rows="3" cols="16" maxlength="48" spellcheck="false" autofocus>1234567812345678 </textarea> <textarea class="text-input" id="fixed-textarea" rows="3" cols="16" maxlength="48" spellcheck="false" autofocus>this is some random text</textarea>

lester's user avatar

New contributor

lester is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Changing whitespace:break-spaces to whitespace:break-word seems to work. I also removed, the width attribute, since in my Chrome it's showing 14 characters.

.text-input { font-family: monospace; font-size: 2em; border: 1px solid black; resize: none; padding: 0.4em; height: calc(1.4em * 3 + 2px); white-space: break-word; word-break: break-all; } <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>1234567812345678</textarea> <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>1234567812345678 </textarea> <textarea class="text-input" rows="3" cols="16" maxlength="48" autofocus>this is some random text</textarea>

Eddi's user avatar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.