4

I have a div that contains a textarea element. The div is fixed in size, but scroll bars will show if enough text is entered. Currently, the textarea height dynamically grows and shrinks correctly, but not the width.

I have been modifying the code given here: http://alistapart.com/article/expanding-text-areas-made-elegant and have gotten to this point (shown in jsfiddle): http://jsfiddle.net/fayu5sh2/2/

The way it currently works is that the textarea is set to 100% width and height of the div, and its content is feed into a hidden span, which changes the height (when enter is pressed) and width of the containing div. While the span operates correctly, the textarea doesn't maintain width: 100%. Is it possible to do this?

The hidden span is currently visible to show what its content is doing, the text in the textarea should lie directly on top of the text in the span.

Here is the html:

<div id="containing_box">
    <div class="expandingArea">
        <pre><span></span><br></pre>
        <textarea></textarea>
    </div>
</div>

Here is the javascript:

$(document).ready(

    function() {

        $('div.expandingArea').each(function() {
            var area = $('textarea', $(this));
            var span = $('span', $(this));

            area.bind('input', function() {
                span.text(area.val());
            });

            span.text(area.val());

            $(this).addClass('active');
        });    
    }
);

and the CSS:

#containing_box {
    width: 300px;
    height: 200px;
    overflow: auto;
    border: 1px solid;
}

textarea, 
pre, p {
  margin: 0;
  padding: 0;
  outline: 0;
  border: 0;
}

.expandingArea {
  position: relative;
  border: 1px solid #888;
  background: #fff;
}

.expandingArea > textarea,
.expandingArea > pre {
    padding: 5px;
    background: transparent;
    white-space: pre;
}

.expandingArea > textarea {
  /* The border-box box model is used to allow
   * padding whilst still keeping the overall width
   * at exactly that of the containing element. */

  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
      -ms-box-sizing: border-box;
          box-sizing: border-box;


  /* This height is used when JS is disabled  */
  height: 100px;
  width: 100px;
}

.expandingArea.active > textarea {
  /* Hide any scrollbars */
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  /* Remove WebKit user-resize widget */
  resize: none;
}

.expandingArea > pre {
  /* display: none;*/
  color: blue;
}
.expandingArea.active > pre {
  display: block;
  /* Hide the text; just using it for sizing */
  /* visibility: hidden; */
}
Ayb4btu
  • 3,208
  • 5
  • 30
  • 42
  • 1
    Check this thread. http://stackoverflow.com/questions/17772260/textarea-auto-height – sbjumani Sep 12 '14 at 23:00
  • @sbjumani All the threads that I have found seem to only deal with resizing textarea height, unfortunately not the width... – Ayb4btu Sep 12 '14 at 23:09
  • Do you want to avoid wrapping, or do you want width and height to always be equal, so the textarea is a square? – Rick Hitchcock Sep 12 '14 at 23:15
  • Put you text are a in a container and set max width as 100%. Allow width to be controlled by the parent and you manage the height. It sounds a bit weird that you need both to be calculated. – sbjumani Sep 12 '14 at 23:29
  • @RickHitchcock No, it doesn't need to maintain a square, and yes, I want to avoid wrapping. What I want is the textarea to grow in height if newlines are added, otherwise only width to grow if you keep typing on the same line. – Ayb4btu Sep 12 '14 at 23:46

2 Answers2

10

You can make a textarea dynamically resize by monitoring its scrollWidth and scrollHeight within an input event.

This code resizes all textareas while maintaining a minimum width and height of 50px:

$('textarea').on('input', function() {
  $(this)
    .width (50)
    .height(50)
    .width (this.scrollWidth)
    .height(this.scrollHeight);
});

Note that width and height are first set to their initial values to force a scroll.

Set the textarea's wrap attribute to "off":

<textarea wrap="off"></textarea>

And set its style to overflow: hidden:

textarea {
  overflow: hidden;
}

Snippet:

$('textarea').on('input', function() {
  $(this)
    .width (50)
    .height(50)
    .width (this.scrollWidth)
    .height(this.scrollHeight);
});
textarea {
  overflow: hidden;
  width: 50px;
  height: 50px;
  padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea wrap="off" autofocus></textarea>
Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79
  • This brings me closer to what I'm after. I've incorporated this approach and simplified my code ( [jsfiddle](http://jsfiddle.net/4qa58b9q/1/) ). though why would the textarea border disappear in the overflow? – Ayb4btu Sep 14 '14 at 09:57
  • Not sure if you're referring to my code or yours? Your fiddle explicitly hides the textarea border, but it should be visible in mine. – Rick Hitchcock Sep 14 '14 at 16:25
  • I see what you mean, the border I was seeing was the expandingArea div border, not the textarea border. – Ayb4btu Sep 14 '14 at 22:24
  • @Rick Hitchcock It is amazing...Btw, how to resize this textarea on change font-size of content inside ? – Ryan Tran Apr 25 '20 at 09:12
  • @RyanTran, should still work, but you may need to trigger the event, something like `$('textarea').trigger('input')` – Rick Hitchcock Apr 25 '20 at 12:02
  • @Rick Hitchcock I solved it, but i don't understand why after return load to edit, resize feature of textarea does not working when textarea had content before ? – Ryan Tran Apr 27 '20 at 02:28
  • @RyanTran, may be worth posting as a new question so people can see your code. – Rick Hitchcock Apr 27 '20 at 10:35
0

Add this in the javascript

$('textarea').on('keyup',function(){
  var spanwidth = $('span').css('width')
  $('textarea').css('width',spanwidth) 
})

Heres the fiddle http://jsfiddle.net/fayu5sh2/5/

If you have more than one of these on the page, you'll need to use IDs or Classes instead of the general 'span' and 'textarea'

Bradley4
  • 510
  • 1
  • 6
  • 13
  • I initially tried the fiddle and found that it didn't work as expected. The issue is that the contents of this function should be inside the each function that I already have. Working through a couple of other issues still, mostly related to borders not behaving. – Ayb4btu Sep 14 '14 at 22:21