JavaScript edge case: Max 5 row rule broken while pasting in text

JavaScript edge case Max 5 row rule broken while pasting in text

I will document an edge case that I encountered today. Namely, the rules set for the <textarea> field was a maximum of 180 characters and 5 rows. I tested it first by writing a text that contained 180 characters and making sure that it fit in the 5 lines. While writing the text manually, everything worked as expected. Still, when I’ve pasted a piece of text I’ve previously copied from another source in the field, it broke the 5-row rule + introduced a scroll in the text area field, which shouldn’t be the case. I’ve noticed that the pasted text contained a space at the end. When we paste text with space at the end in Microsoft Word we often have the same situation where some unexpected space is encountered. This is pretty much the same situation.

Still, we wouldn’t like any unexpected functionalities on our app, especially when it goes live. Especially when it comes to this app I was working on. Namely, the field would be used by users to insert a short message they would send to another person as a part of the virtual gift card. Now, I could already imagine people generate some text with ChatGPT or Gemini and paste in this text area field. Those could easily break the rules mentioned above. I’ve made sure that it won’t happen! Check out the solution below.

Here are the examples of HTML, CSS and JavaScript used. After that I will write down the JavaScript that proven to be the solution for this issue.

HTML

<textarea id="message" maxlength="180" rows="5" placeholder="Write your message..."></textarea>

CSS

input, select, textarea {
            width: 80%;
            padding: 8px;
            margin-bottom: 12px;
            border: 1px solid #ccc;
            border-radius: 5px;
            display: block;
            margin-left: auto;
            margin-right: auto;
		}

	textarea {
            max-height: 120px; /* Approximate height for 5 rows */
            resize: none; /* Prevents manual resizing */
            overflow-y: auto; /* Enables scrolling instead of expanding */
            line-height: 1.2; /* Adjusts spacing to fit 5 rows properly */
        }

JavaScript

document.getElementById('message').addEventListener('input', function () {
        let lines = this.value.split("\n"); // Split input into lines
        if (lines.length > 5) {
            this.value = lines.slice(0, 5).join("\n"); // Keep only the first 5 lines
        }
        document.getElementById('giftMessage').innerText = this.value || 'Your message here...';
    });

With this setup, the <textarea> component followed the max 180 characters and 5-row rule. Still, when I copied a piece of text that contained space at the end and pasted it in the text area field, it broke the 5-row rule, just as you can see on the thumbnail image. It broke it and triggered a scroll, allowing users to insert an infinite number of rows, which we wouldn’t like to happen. At least not for the app I was working on.

New JavaScript solution

Here is the JavaScript example I’ve used that successfully fix the issue described above:

    //Enforce the <textarea> field to max 180 character and 5 rows.
        document.getElementById('message').addEventListener('input', function (event) {
        let text = this.value;
        let lines = text.split("\n");

        // Enforce max characters (180)
        if (text.length > 180) {
            text = text.slice(0, 180);
            lines = text.split("\n");
        }

        // Enforce max 5 rows
        if (lines.length > 5) {
            lines = lines.slice(0, 5);
            text = lines.join("\n");
        }

        this.value = text;
        document.getElementById('giftMessage').innerText = text || 'Your message here...';
    });

    // Handle pasted text properly
    document.getElementById('message').addEventListener('input', function () {
        enforceTextAreaConstraints(this);
    });

    document.getElementById('message').addEventListener('paste', function (event) {
        event.preventDefault();
        let paste = (event.clipboardData || window.clipboardData).getData('text');
        let text = this.value + paste;
        this.value = text;
        enforceTextAreaConstraints(this);
    });

    function enforceTextAreaConstraints(textarea) {
        let text = textarea.value;
        let lines = text.split("\n");

        // Enforce max characters (180)
        if (text.length > 180) {
            text = text.slice(0, 180);
            lines = text.split("\n");
        }

        // Enforce max 5 rows
        if (lines.length > 5) {
            lines = lines.slice(0, 5);
            text = lines.join("\n");
        }

        textarea.value = text;
        
        // Reset height to prevent infinite growth
        textarea.style.height = 'auto';
        
        // Adjust height dynamically but restrict it to max 5 rows
        textarea.style.height = `${Math.min(textarea.scrollHeight, 120)}px`; // 120px is approx. 5 rows

        document.getElementById('giftMessage').innerText = text || 'Your message here...';
    }

Scroll to Top