33

Does anybody know how to make a codemirror textarea resizable like text-area ?

So that the codemirror textarea can be resized by dragging their bottom down grabber corner.

I know it's possible for html divs (see div resizable like text-area) but I have not managed to achieve the same thing on code mirror.

Community
  • 1
  • 1
Zo72
  • 14,593
  • 17
  • 71
  • 103
  • Following up on [this comment](https://github.com/albertgasset/dokuwiki-plugin-codemirror/issues/28#issuecomment-109812800) (from a now archived GitHub repo) revealed that it *does work* out-of-the box with Firefox (58, but it apparently did 3 years ago, too). Still no luck with the latest Chrome (the handle is there, but can't grab it) or Edge (no handle either...). – Sz. Mar 12 '18 at 00:32

8 Answers8

34

WITHOUT JQUERY , CSS only

.CodeMirror {
      resize: vertical;
      overflow: auto !important;
    }

After some struggle, this simple code actually worked for me. I got a resizable Codemirror Instance vertically with scroll working properly.

Tadeu Marques
  • 804
  • 8
  • 10
  • 1
    It can be so simple :) Thanks, so simple and it works! – Roland Mar 26 '19 at 08:45
  • 2
    Perfect! This should be the Best Answer IMHO. – J. Scott Elblein Dec 31 '19 at 21:24
  • 1
    It doesn't work. If I resize the editor then I get empty lines where code should be displayed until I click it. editor.refresh() has to be called somehow. – Karol Lewandowski May 08 '20 at 13:09
  • 3
    Just `resize: vertical` worked for me on CodeMirror 5.54 (without the problem @KarolLewandowski described) . Setting `overflow` to `auto` added a second horizontal scroll bar, so I left that off. – Gabriel Luci Jun 03 '20 at 15:02
  • @KarolLewandowski Actually, I do see this but only after the first resize, and as soon as I scroll the code, it goes back to normal. After that, everything works just fine. – Gabriel Luci Jun 03 '20 at 15:38
30

Some Googling suggests that it is not supported in CodeMirror but you can achieve it with jQuery UI:

var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
  lineNumbers: true,
});
$('.CodeMirror').resizable({
  resize: function() {
    editor.setSize($(this).width(), $(this).height());
  }
});
brianpeiris
  • 10,735
  • 1
  • 31
  • 44
10

I made this little example.

Note that this resizes vertically only, which is probably what you really want? The horizontal resize ability of a normal textarea tends to break layouts - it's usually much easier to come up with a layout where the editor has a fixed width and the content below it gets pushed down if you resize.

I haven't seen the design in which you intend for this to fit, so I'm guessing.

It shouldn't be too hard to modify this and get a working resize widget that works in both directions though, if that's what you wanted.

Alternatively, consider trying this plugin by @Sphinxxx which was derived from this example.

mindplay.dk
  • 7,085
  • 3
  • 44
  • 54
  • How elegant and clean looking.. I really like this ! – Matt Wohler Apr 19 '17 at 13:29
  • BTW, let's connect the answer here and your interesting conversation with Marijn on this very subject under [CM issue 850](https://github.com/codemirror/CodeMirror/issues/850), complete with @Sphinxxx's example there, too -- it's such a small world! :) (And I do agree with your "not so simple" and "should not remove TEXTAREA features" remarks there...) Thanks again for your machete work on this! ;) – Sz. Mar 12 '18 at 00:42
  • what kind of link is anon.to? it's blocked on my network. – Nathan Goings Oct 04 '18 at 18:06
  • Hey thanks thanks thanks man, exactly what I needed! Just integrated it into my Vue project with minimal adjustments and it works like a charm! – elveti Jul 02 '19 at 08:28
1

If jQuery is not an option, and you can live without resizing in IE (and Edge, until it catches up with CSS resize:...), here's a proof-of-concept example of a pleasantly simple & light technique that doesn't require the drag-and-drop hack pioneered by @mindplay.dk.

Instead, here:

  1. a container DIV is used, with
  2. a plain CSS resize handle, and
  3. the resize events are proxied over to CM via ResizeObserver/MutationObserver (since onResize only fires for window, just to make web programming that much more miserable ;) ).

One issue to iron out (in CM? in WebKit? or as a workaround I haven't had the patience + time to distill...) is the extra bottom padding added for the "CM on WebKit" scenario, where the CSS resize handle would get overlapped by CM's own pots and pans. OTOH, Firefox draws it on top of all else, so despite CM is unaware of the handle and draws its various (several!) rectangles there, Firefox still manages to win rescuing it, and resizing would work, albeit the handle would get pasted over the scrollbar arrows. (Playing with z-index or styling the crap out of CM didn't help for me.)

BTW, note: this means that plain CSS overflow: hidden; resize: both;, directly applied on the main .CodeMirror DIV, almost works in Firefox without any magic (no extra frame, no geometry tweaks etc.). Hooking the resize events (the same way as noted above) for a cm.setSize(cm_div.clientWidth, cm_div.clientHeight) would still be needed, though.

But detecting Firefox vs. Chrome to optimize it out would probably make the code much more complicated than just leaving it the same for both...

document.addEventListener("DOMContentLoaded", function(event) {
  
  fr = document.querySelector("#cm-resize-frame")
  
  // This 5-6 lines below is only for the WRAP/NOWRAP demo switch:
  cm = null
  reset = document.getElementById("wrap").onclick = function() {
    cm && cm.toTextArea() // clean up previous CM instance
    cm = CodeMirror.fromTextArea(document.getElementById("cm"),
        {lineWrapping: document.getElementById("wrap").checked,
         lineNumbers: true } // just to see if CM is actually alive & resizing
    )

    function cm_resize() {
        cm.setSize(fr.clientWidth + 2,   // chrome needs +2, others don't mind...
                   fr.clientHeight - 10) // and CM needs room for the resize handle :-/
    }

    // Needed (on FF, Edge & IE11, but not Chrome) for the scrollbars to properly initialize:
    cm_resize()

    // This is the actual "business logic" of the whole thing! ;)
    if (window.ResizeObserver) // Chrome 64+
        new ResizeObserver(cm_resize).observe(fr)
    else if (window.MutationObserver) // others
        new MutationObserver(cm_resize).observe(fr, {attributes: true})
  }
  reset()
})
#cm-resize-frame {
  overflow: hidden; /* CM will manage its own scrollbars. */
  resize: both;
  
  height: 10em; /* A fixed initial height is required in Chrome both for the resize handle to appear and to not fall into a shrinking loop due to the neg. offset in cm_resize()! */

  /* Optional... */
  border: 1px solid lightgrey;
  width: 20em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.29.0/codemirror.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.29.0/codemirror.min.js"></script>

<div id="cm-resize-frame">
<textarea id="cm">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nunc rhoncus ornare diam eget consequat. Suspendisse potenti.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 
  
Sed scelerisque, ex nec pharetra ultrices, ipsum mi aliquam arcu, sit amet pulvinar erat mauris sit amet mi.
Fusce pulvinar vel ex semper imperdiet. Quisque dapibus purus eu commodo volutpat.

Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. 
  
Sed scelerisque, ex nec pharetra ultrices, ipsum mi aliquam arcu, sit amet pulvinar erat mauris sit amet mi.
Fusce pulvinar vel ex semper imperdiet. Quisque dapibus purus eu commodo volutpat.</textarea>
</div>

WRAP: <input id="wrap" type="checkbox" checked>

(Again: this is just an example, demonstrating that the technique works. The JS snippet is meant to be read as pseudocode. ;) A real, polished implementation, provided that the simplicity of the approach is preserved, is very welcome, though!)

(See also on CodePen...)

Sz.
  • 3,342
  • 1
  • 30
  • 43
1
.CodeMirror__wrapper {
    resize: both;
    overflow: auto !important;
}

Tried adding resize to .CodeMirror but that didn't work. Adding the resize to the wrapper worked for me though.

J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
Skip
  • 11
  • 2
0
let CodeMirrorCustomResize = (params) => {
    var start_x, start_y, start_h,
        minHeight = params && params.minHeight ? params.minHeight : 150,
        resizableObj = params && params.resizableObj ? params.resizableObj : '.handle'

    let onDrag = (e) => {
        sqlEditor.setSize(null, `${Math.max(minHeight, (start_h + e.pageY - start_y))}px`);
    }

    let onRelease = (e) => {
        $('body').off("mousemove", onDrag);
        $(window).off("mouseup", onRelease);
    }

    $('body').on("mousedown", resizableObj, (e) => {
        start_x = e.pageX;
        start_y = e.pageY;
        start_h = $('.CodeMirror').height();

        $('body').on("mousemove", onDrag);
        $(window).on("mouseup", onRelease);
    });
}

If someone is interested in shorter and more jQuery version of @mindplay.dk answer ( btw. thanks for this ).

TH3C120W
  • 11
  • 2
-1

This worked for me. Nothing else did (including "resize: vertical").

.CodeMirror {
    resize: auto;
}
Steve
  • 93
  • 1
  • 9
-4

What have you tried?

I just downloaded the development snapshot of CodeMirror from http://codemirror.net/

Running complete.html from the demo directory has a nice resizeable text area (in my Chrome browser). In fact at least some other demos also have resizeable textareas.

If this does not answer your question, please update it with more specific information about what you have tried and what does not work.

HBP
  • 15,685
  • 6
  • 28
  • 34
  • No resize handles visible here: https://codemirror.net/demo/complete.html – Matthew Simon Cavalletto Oct 11 '16 at 17:26
  • FYI: I wondered why so many downvotes for this, so checked it, and found the answer might have been based on a misunderstanding: those textareas were resizable likely because CM actually failed to initialize; That was my case, at least. When it did run: no more resize handles. – Sz. Mar 11 '18 at 23:21