10

I like Chrome's nifty textarea resize control. However, the one exception is that the textarea appears to have a hard min-height/min-width setting that's not changeable via custom css, even with !important qualifiers.

textarea#myTextArea{min-height:0 !important;min-width:0 !important}

Is it possible to override this via jQuery perhaps?

js-newb
  • 421
  • 6
  • 16
  • If you add those two by applying a class/id to an element and setting those on the class/id, that should do the trick. – Mathew Thompson Feb 28 '13 at 22:13
  • The thing is, once the initial size is set at document.load, lets say to 400px by 100px, Chrome will not accept a min-height/min-width (runtime css) that's less than the initial size, regardless. – js-newb Feb 28 '13 at 22:31
  • The same problem happens with elements with `resize` property: http://stackoverflow.com/q/18178301/1529630 – Oriol Aug 12 '13 at 01:34

3 Answers3

5

These "min-height/min-width" rely on cols and rows attributes. Eg. if cols is missing or less than 1, its default value is 20, so the minimum width will be 20 characters width.

(cf. http://www.w3.org/TR/html5/forms.html#the-textarea-element)

The fact you cannot resize a textarea under its initial dimensions is reported as a bug (https://code.google.com/p/chromium/issues/detail?id=94583) although

The user agent may restrict the resizing range to something suitable, such as between the original formatted size of the element, and large enough to encompass all the element's contents.

http://www.w3.org/TR/css3-ui/#resize

Unfortunately it seems there's no way for now to change this behaviour.

MatTheCat
  • 18,071
  • 6
  • 54
  • 69
3

Here's the answer you're looking for. This is my original solution, so you've seen it here first!!

The code I've done below is in its most basic form. I've simplified it to remove the Javascript library I'd normally use along with other custom stuff I'd have to explain. This is the solution without needing any external libraries etc.

HOW IT WORKS?

It adds an interval that checks to see if the textarea size has changed whilst the mouse cursor is over it. If it changes we know the user dragged so we force the textarea size to be 1px by 1px. This creates a very slight flicker for the user, but because they are dragging the size instantly goes back to the size they are dragging it to, only now, it will shrink all the way down to 1px by 1px.

THE CODE

Demo: http://jsfiddle.net/greatbigmassive/zJ4z5/5/

function TA_start(id){
var ta = document.getElementById(id);
if(typeof(ta.resizeCheckStarted) == "undefined"){
    ta.resizeCheckStarted = true;
    ta.resizeUpdated = false;
    var cs = window.getComputedStyle(ta,null);
    ta.originalH   = cs.getPropertyValue("height");
    ta.originalW   = cs.getPropertyValue("width");
    ta.originalM   = cs.getPropertyValue("margin");
    ta.style.width = ta.originalW;
    ta.style.height= ta.originalH;
    ta.style.margin= ta.originalM;
    ta.resizeCheck = setInterval("TA_checkMe('"+id+"')",100);
 }
 }

function TA_checkMe(id){
 var ta = document.getElementById(id);
 if(ta.originalW != ta.style.width || ta.originalH != ta.style.height){
    ta.resizeUpdated = true;
    ta.originalW = ta.style.width;
    ta.originalH = ta.style.height;
    ta.style.width="1px";
    ta.style.height="1px";
    clearInterval(ta.resizeCheck);
 }
}

function TA_stop(id,init){
 var ta = document.getElementById(id);
 if(typeof(init)=="undefined"){
    if(typeof(ta.stopResizeCheck)=="undefined"){
        ta.stopResizeCheck = setTimeout("TA_stop('"+id+"',true)",500);
    }
 } else {
    clearInterval(ta.resizeCheck);
    if(ta.resizeUpdated != true){
        delete ta.resizeCheckStarted;
    }
 }
}

Fixes:

a). It doesn't shrink first time b). You don't need any additional CSS with it

Adam
  • 359
  • 3
  • 5
  • I have made a jsfiddle with your code: http://jsfiddle.net/GLVHc/. It works, but the first time I mouseover the element, it becomes tiny! And just a note: never use `setTimeout`/`setInterval` with a string, because then they use the devil `eval`! – Oriol Aug 13 '13 at 15:02
  • Thanks for the feedback. I've overcome the "goes tiny" issue. The reason was because the textarea didn't have any style width or height to begin with. Applied computed width, height and margin to it first time in. All good now :) See my fiddle! – Adam Aug 16 '13 at 14:43
3

Another javascript solution:

Demo: http://jsfiddle.net/nz8ut/2/

function resizableStart(e){
    this.originalW = this.clientWidth;
    this.originalH = this.clientHeight;
    this.onmousemove = resizableCheck;
    this.onmouseup = this.onmouseout = resizableEnd;
}
function resizableCheck(e){
    if(this.clientWidth !== this.originalW || this.clientHeight !== this.originalH) {
        this.originalX = e.clientX;
        this.originalY = e.clientY;
        this.onmousemove = resizableMove;
    }
}
function resizableMove(e){
    var newW = this.originalW + e.clientX - this.originalX,
        newH = this.originalH + e.clientY - this.originalY;
    if(newW < this.originalW){
        this.style.width = newW + 'px';
    }
    if(newH < this.originalH){
        this.style.height = newH + 'px';
    }
}
function resizableEnd(){
    this.onmousemove = this.onmouseout = this.onmouseup = null;
}

var els = document.getElementsByClassName('resizable');
for(var i=0, len=els.length; i<len; ++i){
    els[i].onmouseover = resizableStart;
}

The solution above uses mouseover and mouseout to trigger resizableStart and resizableEnd. The problem is that if the element being resized has childs, when the mouse is placed over a child, the element receives a mouseout event and, just after that, it receives a mouserover event which bubbles from child.

To avoid those events I have implemented another solution with mouseenter and mouseleave events:

Demo: http://jsfiddle.net/nz8ut/3/

Oriol
  • 274,082
  • 63
  • 437
  • 513