I am filling a textarea with content for the user to edit.
Is it possible to make it stretch to fit content with CSS (like overflow:show
for a div)?
I am filling a textarea with content for the user to edit.
Is it possible to make it stretch to fit content with CSS (like overflow:show
for a div)?
one line only
<textarea name="text" oninput='this.style.height = "";this.style.height = this.scrollHeight + "px"'></textarea>
Not really. This is normally done using javascript.
there is a good discussion of ways of doing this here...
Alternatively, you could use a contenteditable
element, this will fit to the text inside.
<div contenteditable>Try typing and returning.</div>
Please note that it's not possible to send this value along in a form, without using some javascript. Also contenteditable
will possibly generate HTML-content and allows styling, so this may need to be filtered out upon form submit.
Try typing and returning.
Not 100% related to the question as this is for Angular when using Angular Material Design only.
There is a npm package associated with Angular called @angular/cdk
(if using Angular Material Design). There is a property included in this package that can be associated to a textarea
called cdkTextareaAutosize. This automatically sets the textarea
to 1 line and stretches the textarea
to fit the content accordingly. If you are using this library, something like this should work.
<textarea
maxLength="200"
cdkTextareaAutosize
type="text">
</textarea>
Here is a function that works with jQuery (for height only, not width):
function setHeight(jq_in){
jq_in.each(function(index, elem){
// This line will work with pure Javascript (taken from NicB's answer):
elem.style.height = elem.scrollHeight+'px';
});
}
setHeight($('<put selector here>'));
Note: The op asked for a solution that does not use Javascript, however this should be helpful to many people who come across this question.
This is a very simple solution, but it works for me:
<!--TEXT-AREA-->
<textarea id="textBox1" name="content" TextMode="MultiLine" onkeyup="setHeight('textBox1');" onkeydown="setHeight('textBox1');">Hello World</textarea>
<!--JAVASCRIPT-->
<script type="text/javascript">
function setHeight(fieldId){
document.getElementById(fieldId).style.height = document.getElementById(fieldId).scrollHeight+'px';
}
setHeight('textBox1');
</script>
Answers here were good but were lacking a piece of code that I had to add to avoid a shrinking that is not welcome when you type for the first time :
var $textareas = $('textarea');
$textareas.each(function() { // to avoid the shrinking
this.style.minHeight = this.offsetHeight + 'px';
});
$textareas.on('input', function() {
this.style.height = '';
this.style.height = this.scrollHeight + 'px';
});
Another simple solution for dynamic textarea control.
<!--JAVASCRIPT-->
<script type="text/javascript">
$('textarea').on('input', function () {
this.style.height = "";
this.style.height = this.scrollHeight + "px";
});
</script>
There are a lot of answers here already, but I think some improvement can still be made to the textarea resizing code.
This script snippet will loop over ALL of the textareas on your page, and make sure they resize both on load and on change.
<script>
document.querySelectorAll("textarea").forEach(element => {
function autoResize(el) {
el.style.height = el.scrollHeight + 'px';
}
autoResize(element);
element.addEventListener('input', () => autoResize(element));
});
</script>
Vanilla JS only, no libraries needed.
A reliable, reusable, more complete answer that is responsive (watches for window resizes). You can place the code in a JavaScript module, refer to comments below on how it works:
// File: ui.mjs
/* Auto resize a <textarea>'s height to fit its content.
* Use the HTML attribute `rows` to set the min height of the element, e.g. rows="2"
*/
function runAutoHeight(el) {
el.style.height = 'auto';
const computedStyle = getComputedStyle(el)
const borderTop = parseFloat(computedStyle.getPropertyValue("border-top-width").replace('px',''));
const borderBottom = parseFloat(computedStyle.getPropertyValue("border-bottom-width").replace('px',''));
el.style.height = String(el.scrollHeight + borderTop + borderBottom) + 'px';
}
/* Sets up autoHeight for the given element for the following 2 situations:
* 1. When the user types in input
* 2. When the element is resized (e.g. window is resized)
*
* It also adds a function to the element called 'autoHeight', which can be manually called.
* This is useful when setting values to a <textarea> via JS, and hence the `input` event
* handler will not be run, e.g.:
* import * as ui from '/static/path/to/your/ui.mjs';
* ui.setupAutoHeight(el)
* el.value = "Manually setting value won't fire change event"
* el.autoHeight()
*/
export function setupAutoHeight(el) {
el.autoHeight = () => runAutoHeight(el);
el.style.resize = "none";
// Watch for window resizes
const observer = new ResizeObserver(el.autoHeight);
observer.observe(el);
// Watch for changes in text input
el.addEventListener('input', el.autoHeight)
}
If you are using ionic just add this attribute to the text area:
autoGrow="true"
See this answer: ion-textarea resize height dynamically in Ionic 5
<script>
document.querySelectorAll("textarea").forEach(element => {
function autoResize(el) {
if (el.scrollHeight > el.offsetHeight) {
el.style.height = el.scrollHeight + 'px';
}
}
autoResize(element);
element.addEventListener('input', () => autoResize(element));
});
</script>
Solution for the shrinking when typing input I experienced in dezman's fantastic function (see dezman above). I added a comparison to the property which FTW referenced in his post just above dezman's named .offsetHeight.
In dezman's function, when the scrollHeight is less than the offsetHeight—–e.g. 1 line of text in a 5 line size textarea––then the adjustment made to el.style.height after each keystroke was inadvertently reducing the size of the offsetheight. The offset kept shrinking toward the scrollHeight which gave the appearance of a shrinking textarea.
Firing the adjustment to style.height only when text entry causes an increase in the scrollHeight past the .offsetheight prevents the offsetHeight from shrinking with every keystroke.
THANK YOU dezman and FTW above...
Not quite a <textarea>
but you can always use:
<div contenteditable="true"></div>
which, in some contexts, works as an excellent drop-in replacement for <textarea>
.
Working Example:
.textbox {
width: 400px;
padding: 12px;
box-sizing: border-box;
outline: 1px solid red;
}
<div class="textbox" contenteditable="true">
This div is editable like a textarea. It expands when more words are typed into the available area... keep typing and you'll see how the more you type, the more it grows...
</div>
Further Reading:
Solution for React
I used the length of the text that was being displayed and divided that number by 30 (I adjusted this number until it felt right form my App)
{array.map((text) => (
<textarea
rows={text.length / 30}
value={text}
></textarea>
)}