CSS Box Resize Generator
Make a box or textarea resizable by the user, or stop it being resized. Set the direction, the size limits and the overflow, drag the real handle to test it, and copy the CSS. For textareas there are ready-made fixes, including one that grows with its text.
Drag the corner to test it
Drag the cyan grip at the box's bottom-right corner up or down, or click it and use the arrow keys.
The grip is only for testing here; on your page users get the browser's small native handle, and none at all on iPhone and iPad.
.panel {
resize: vertical;
overflow: auto;
height: 200px;
min-height: 120px;
max-height: 480px;
box-sizing: border-box;
}What resize needs to work
The specification says resize applies to scroll containers. In practice that means three conditions, and missing any of them makes the handle silently not appear:
| Condition | Why |
|---|---|
| overflow is auto, scroll or hidden | visible (the default) and clip do not make a scroll container |
| The element is not display: inline | overflow does not apply to inline boxes such as span |
| resize is not none | none is the starting value for everything except textarea |
overflow: clip is the trap: it looks like hidden and is often swapped in to avoid creating a scroll container, and that is exactly why the handle disappears. Textareas already scroll, so they only need a resize value.
The six values
| Value | User can change | Support |
|---|---|---|
| both | Width and height | Chrome 1, Firefox 4, Safari 3 |
| vertical | Height only | Same |
| horizontal | Width only | Same |
| block | The block size: height in English, width in vertical text | Chrome 118, Firefox 63, Safari 16 |
| inline | The inline size: width in English, height in vertical text | Chrome 118, Firefox 63, Safari 16 |
| none | Nothing; no handle | All |
block and inline follow the writing direction, so a vertical-only notes panel keeps working if the page is later set in vertical Japanese text. For left-to-right pages they behave exactly like vertical and horizontal.
Limits, and the size the browser writes
The only limits on dragging are min-width, max-width, min-height and max-height. With the Notes panel preset (height 200px, min 120px, max 480px) the handle travels 80px up and 280px down and then stops; the readout under the preview says which limit stopped it. If a minimum is larger than the maximum, the minimum wins. Use max-width: 100% on a box that can be widened so it never pushes past its column.
When someone drags the handle, the browser writes the new size into the element's style attribute. From then on that inline width and height beat your stylesheet, including media queries, until the page reloads or a script clears them. If a layout needs to change size at a breakpoint, give the resizable element max-width: 100% so the inline width cannot overflow, or clear element.style.width when the breakpoint changes.
Textareas: lock, vertical only or auto-grow
| Goal | CSS | Notes |
|---|---|---|
| Stop people breaking the layout | resize: vertical | The usual choice: taller is fine, wider is not |
| No handle at all | resize: none | Set a height or rows so long text still has room |
| Grow as the user types | field-sizing: content | Add min-height and max-height; Chrome 123, Firefox 152, Safari 26.2 |
Browsers give textareas resize: both in their default styles, which is why a textarea can be dragged wider than its form. field-sizing: content makes the box size itself to its text, so a one-line comment field grows line by line; pair it with min-height: 3lh and max-height: 12lh (the lh unit is one line of text) so it starts at three lines and starts scrolling after twelve. Browsers without it fall back to the fixed size from rows or height.
Remembering the size
CSS forgets the user's size on reload. The optional script above uses ResizeObserver to notice size changes, waits 300ms after the last one so it is not writing on every pixel of a drag, and stores the inline width and height in localStorage. On the next visit it puts them back before the user notices. It only saves sizes the user set by dragging, because those are the ones the browser writes into the style attribute.
Phones, keyboards and accessibility
The handle is a mouse feature. Safari on iPhone and iPad does not support resize at all, Android browsers show a small handle that is hard to grab, and there is no keyboard way to use it. WCAG 2.2 criterion 2.5.7 (Dragging Movements) exempts the browser's own handle, because the browser provides it, but the practical lesson stands: resizing should be a convenience, not the only way to see the content. Give the box a sensible default size and scrolling, and if size really matters to the task, add buttons such as "Taller" and "Shorter".
When the handle does not appear
| Symptom | Cause | Fix |
|---|---|---|
| No handle on a div | overflow is visible or clip | overflow: auto |
| No handle on a span | Inline elements cannot scroll | display: block or inline-block |
| Handle will not move | width equals max-width (or min equals max) | Leave room between the limits |
| Box pushes past its column | No max-width | max-width: 100% |
| Breakpoint size ignored | The dragged size is now an inline style | Clear element.style.width, or reload |
| Works on desktop, not iPhone | iOS Safari has no resize support | Provide a default size or buttons |
Frequently asked questions
How do I stop a textarea from being resized?
textarea { resize: none; } removes the handle. resize: vertical is often better: users can still make it taller for long text without breaking the layout sideways.
Can I style the resize handle?
Not with standard CSS. Chrome and Safari allow a small change through ::-webkit-resizer, but most designs either leave the default or hide it and build their own handle in JavaScript.
Can I make an image resizable?
The specification allows browsers to support resize on images, videos and iframes, but support is patchy. Wrapping the image in a div with resize and overflow: hidden, and giving the image width: 100%, works everywhere the handle does.
Is there an event when the user resizes an element?
There is no resize event for elements (window has one). Use ResizeObserver, which also fires when the size changes for any other reason, such as the content or the window changing.
Why is my resizable box not resizable inside a flex container?
It usually is, but flex-grow or align-items: stretch keep setting its size and fight the handle. Give the item flex: none on the axis you want users to control.
What does the lh unit mean in the textarea preset?
One lh is the computed line height of the element, so 3lh is exactly three lines of text tall whatever the font size. It works in Chrome 109, Firefox 120 and Safari 16.4 onwards.
Sources
- CSS Basic User Interface Module Level 4: resize: values, what it applies to, and min/max as the only limits
- MDN: resize: browser support, including iOS Safari
- MDN: field-sizing: auto-growing form fields and support
- MDN: ResizeObserver: watching element size changes
- W3C WAI: Understanding SC 2.5.7 Dragging Movements: the user-agent exception
Related Tools
Build and preview common CSS Grid layout patterns.
Build linear and radial gradients with custom color stops.
Remove, replace, and export image metadata.
Generate and inspect solid background-color declarations.
Generate gradient and image background-image CSS.
Generate uniform or side-specific CSS border declarations.