htmlcssmobile-websitemobile-browsermobile-chrome

Mobile browser textarea height change issue on focus


I'm a bit stuck with this mobile-only issue I can also reproduce on Google Chrome (even on desktop, when the developer tools are set to mobile view).

The problem is pretty simple. I have a basic form on the site, containing a textarea and a submit button underneath it. When I tap on the textarea, so it gains focus, and then type anything into it, the mobile browser changes the height of the textarea and it covers my submit button, and users are not able to use it anymore. The problem here is, that chrome enlarges the height of the text field to make the text bigger, but doesn't relayout the website, and so it just covers the button. If I leave any text in the text field, it stays enlarged even after it loses its focus. I'm not sure whether this is a bug, or a feature, but it doesn't seem very clever to me.

It seems like chrome enlarges the font of the textarea as soon as it sees any text entered into it, and because the height is computed based on the number of rows, it changes and is reflected, but for some reason it doesn't affect the other parts of the page.

I know that using the viewport tag would fix this problem, and am planning on making the website mobile-friendly in the future, but it will take a lot of work and so I can't just use it right now.

Setting the height (e.g. height: 50px;) also fixes the problem, but there are some sections of the website in which I really need to define it by the number of rows.

It's not such a big problem that the textarea gets enlarged, and anything that would make the site fully functional would be a solution for now. I would also be interested in the root cause of this issue, if anyone knows more on this topic.

I couldn't reproduce this on codepen.io, as they're using the viewport tag, so I've prepared a simple example like this:

<html>
<head>
    <style>
        textarea { width: 990px; background: red; }
        input { background: blue; }
    </style>
</head>
<body>

<textarea name="test" cols="40" rows="5"></textarea><br />
<input type="submit" name="Button" value="Button" />

</body>
</html>

After a bit of trying I managed to find a way to workaround it using JS, but am sure there is a better solution to it:

    <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var textarea = $('textarea');
            var originalRows = parseInt(textarea.attr('rows'));
            textarea.on('input', function() {
                textarea.attr('rows', originalRows+1);
                textarea.attr('rows', originalRows);
            });
        });
    </script>

Thank you guys for your time, any help will be appreciated!


Solution

  • I didn't manage to find a proper solution, as it really seems to be a bug in chrome itself. But I found a pretty nice and non-invasive workaround I'll be using.

    $(document).ready(function() {
        $('textarea').each(function() {
            var textarea = $(this);
            var lastHeight = textarea.css('height');
    
            textarea.on('beforeinput', function() {
                // not yet available in ff and edge where the issue is not reproducible
                lastHeight = textarea.css('height');
            });
    
            textarea.on('input', function() {
                var height = textarea.css('height');
    
                if (height !== lastHeight) {
                    var inlineHeight = textarea.get(0).style.height;
                    textarea.css('height', height);
                    $(document).height();  // force reflow
                    textarea.css('height', inlineHeight);
                }
    
                lastHeight = height;
            });
        });
    });