Normally, the textarea
can be resized both ways by dragging a little triangular handle in the bottom right corner. Once I disable horizontal resizing by setting textarea { resize: vertical; }
, the textarea
can only be resized up or down while dragging the same little triangle-shaped handle. But it doesn't seem very intuitive as the trianglular handle suggests that I should be able to resize the textarea
along both axes.
I noticed that StackOverflow has a modified resize handle on this very textarea I am typing my question into. It intuitively implies only vertical resizing and it looks cute. If you click Ask Question, you will see it at the bottom of the textarea
box. My guess is it is modified using jQuery. But can the looks of the resize handle be changed using simple CSS?
Normally, the textarea
can be resized both ways by dragging a little triangular handle in the bottom right corner. Once I disable horizontal resizing by setting textarea { resize: vertical; }
, the textarea
can only be resized up or down while dragging the same little triangle-shaped handle. But it doesn't seem very intuitive as the trianglular handle suggests that I should be able to resize the textarea
along both axes.
I noticed that StackOverflow has a modified resize handle on this very textarea I am typing my question into. It intuitively implies only vertical resizing and it looks cute. If you click Ask Question, you will see it at the bottom of the textarea
box. My guess is it is modified using jQuery. But can the looks of the resize handle be changed using simple CSS?
- it's just a guess but I think they removed the handle and created their own.. From what I know you can't modify the default one since that is browser specific. – Spluf Commented Apr 20, 2016 at 13:13
- 2 I've just discovered that trying to right click the Stack Overflow rezise control is incredibly frustrating! – James Donnelly Commented Apr 20, 2016 at 13:18
- 1 kindly check jsfiddle/m81wkfe7 and replace the image and adjust the position as per your need – RRR Commented Apr 20, 2016 at 14:33
- A simple solution: stackoverflow./a/63398119/1405507 – Rich Commented Aug 14, 2020 at 8:11
2 Answers
Reset to default 3Actually, the HTML part for SO answer textarea is:
<div class="wmd-container">
<div class="wmd-button-bar" id="wmd-button-bar"> .... </div>
<textarea data-min-length="" tabindex="101" rows="15" cols="92" name="post-text" class="wmd-input processed" id="wmd-input"></textarea>
<div class="grippie" style="margin-right: 0px;"></div>
</div>
The div .grippie
is just a SVG image with an handler set to listen on your click&drag action, using the cursor offset in height to set the height of the textarea dinamically.
Check this if you want to know more about it
This is not pure CSS, but vanilla JavaScript function for making any textarea vertically resizable by dragging the bottom edge.
// make textareas resizable by dragging the bottom edge
function init_textareas() {
use_bottom_edge(document.getElementById("nonlorem"));
use_bottom_edge(document.getElementById("abitlorem"));
use_bottom_edge(document.getElementById("morelorem"));
}
var mouseup_listener = null;
var mousemove_listener = null;
var onresize_listener = null;
var initial_y_ergo_resizing = null;
var initial_height = null;
var extra = 0;
function use_bottom_edge(target_ta) {
resize = document.createElement("SPAN");
resize.classList.add("resize");
target_ta.parentNode.insertBefore(resize, target_ta.nextSibling);
target_ta.classList.add("resizeTarget");
target_ta.style.resize="vertical"; // try "none" to remove handle
cs = getComputedStyle(target_ta);
extra = 3 + (parseFloat(cs.getPropertyValue('margin-bottom')) + parseFloat(cs.getPropertyValue('padding-bottom')))/2;
resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
resize.addEventListener('mousedown', resize_onmousedown);
resize.addEventListener('pointerdown', resize_onpointerdown);
if (mouseup_listener == null)
document.addEventListener('mouseup', mouseup_listener=resize_onmouseup);
if (mousemove_listener == null)
document.addEventListener('mousemove', mousemove_listener=resize_onmousemove);
if (onresize_listener == null)
window.addEventListener('resize', onresize_listener=position_all_resizers);
}
function resize_onmousedown(e) {
e.preventDefault();
target_ta = e.target.previousSibling;
initial_y_ergo_resizing = e.pageY;
initial_height = target_ta.getBoundingClientRect().height;
}
function resize_onpointerdown(e) {
e.target.setPointerCapture(e.pointerId);
}
function resize_onmousemove(e) {
if (initial_y_ergo_resizing != null) {
e.preventDefault();
resize = e.target;
target_ta = resize.previousSibling;
current_height = initial_height + e.pageY - initial_y_ergo_resizing - 2*extra;
if (current_height > 20) {
target_ta.style.height = current_height + "px";
resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
}
}
}
function resize_onmouseup(e) {
if (e.target.classList.contains("resize")) {
e.preventDefault();
initial_y_ergo_resizing = null;
position_all_resizers();
} else if (e.target.classList.contains("resizeTarget")) {
position_all_resizers();
}
}
function position_all_resizers() {
resize_array = document.getElementsByClassName("resize");
for (resize of resize_array) {
target_ta = resize.previousSibling;
if (target_ta.offsetParent != null) {
resize.style.top = target_ta.offsetTop + target_ta.getBoundingClientRect().height - extra + 'px';
resize.style.display = "block";
} else {
resize.style.display = "none";
}
}
}
.resize, .resize:hover {
cursor: ns-resize;
width: 100%;
height: 7px;
background-color: transparent; /* try "red" for ghost bars */
position: absolute;
display: block;
opacity: 0.3;
}
p {
position: relative; /* to keep bars attached to textarea */
float: left;
clear: both;
}
<body onload="init_textareas()">
<p><textarea id="nonlorem">This is lorem ipsum free textarea.</textarea></p>
<p><textarea id="abitlorem">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</textarea></p>
<p><textarea id="morelorem">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea></p>
</body>
I simply add absolute positioned transparent "ghost bar" after each textarea, change mouse pointer on hover, lock it on mouse down and use mouse listeners to modify the size of textarea according to change of y-axis value. Since there can be more than one textarea, on page layout changes I have to go through all of them and modify positions of ghost bars.
There is some trickery in exactly positioning the ghost bars and I presume they always e in pairs with a textarea, so I can use nextSibling/previousSibling to address them. The code also supports adding ghost bars to textareas that are currently not visible (in collapsed region of the page, for example). I personally like keeping the handle in the bottom right corner as an indicator that textarea can be resized. In practice one quite quickly realizes from mouse cursor changes, that whole bottom edge can be used as resize handle.
You can find similar JavaScript solution with touch support and styled handle here.