Adjustable Form Text Area with the contenteditable Tag
How to create a dynamic text area without breaking form styles
Programming code by Pixnio is licensed under Creative Commons Zero
As developers, we have to deal with non-standard form inputs while creating new objects. One of the hurdles is handling a large amount of text in a single text area. The challenge is how should the form look given a great deal of text from the user. The standard textarea
tag is the typical go-to for this problem. Even that has its limitations if you want to maintain the styles of your form and also have a good user experience. We dealt with this exact problem on a recent project at Collective Idea. Here is the trail of research and the solution we landed on.
What we wanted was a textarea
that would expand as the user typed the content. This seemed easy enough, but as we began our research we found a large amount of seemingly “workaround” solutions. Basically lots and lots of JavaScript that was doing a bunch of calculations for height. Solutions that looked a whole lot like this one:
var span = $('<span>').css('display','inline-block') .css('word-break','break-all') .appendTo('body').css('visibility','hidden'); function initSpan(textarea){ span.text(textarea.text()) .width(textarea.width()) .css('font',textarea.css('font')); } $('textarea').on({ input: function(){ var text = $(this).val(); span.text(text); $(this).height(text ? span.height() : '1.1em'); }, focus: function(){ initSpan($(this)); }, keypress: function(e){ //cancel the Enter keystroke, otherwise a new line will be created //This ensures the correct behavior when user types Enter //into an input field if(e.which == 13) e.preventDefault(); } });
While this could have achieved what we wanted, this example has a lot of code and logic to wrap your mind around.
We then realized that adding contenteditable="true"
to a div
would achieve the user experience we desired. The obvious problem is this is not a form input. Because this accomplished what we were looking for from a user experience standpoint, we decided to travel further down this path. We ended up using a hidden input field for capturing the value of the div
. Using a little bit of JavaScript to set the value, this was achievable. It also requires a little bit of CSS to get the desired behavior.
JavaScript
$(document).ready(function() { $(document).on("submit", "form#new_expandable", function(e) { e.preventDefault(); var contents = $(".expandable-input").html(); $('input#expandable').val(contents); this.submit(); }); });
HTML
<form id="new_expandable"> <div contenteditable="true" class="expandable-input"></div> <input type="hidden" id="expandable"></input> <input type="submit"></input> </form>
CSS
.expandable-input { min-height: 18px; height: auto; width: 200px; border: 1px solid; }
Really, there are different ways to handle this scenario, but we thought this solutions was the most concise and easy to understand. Let us know of anyways you have solved this problem in the past.
Comments
The beauty of textarea is that it captures only the text of whatever is pasted into it, stripping out tags and attributes.
A contenteditable div will keep the formatting and tags of whatever is pasted into it, which may be a headache if it needs to be cleaned up to fit in with the styling of the rest of the site.
[face palm!!]
Silly me. Ignore what I wrote. I forgot that my POST handler routine always stripped out tags.
WARNING: Don’t leave your email address here, as it is exposed to Google search.
it would crash the textarea if the amount of text is large