Monaco-editor: Can editor stretch to fit its content? .editor{height: auto}

Created on 2 Apr 2018  路  11Comments  路  Source: microsoft/monaco-editor

monaco-editor version: 0.10.1
image
div.editor{height: auto}
It seems like the monaco-eidtor's height depends on its container's height,
but its container's height is auto, I want the container(div.editor)'s height could be stretched by its content.

feature-request

Most helpful comment

In 0.19.3 the following seems to work without touching DOM to guess what the editor size is:

editor.onDidChangeModelDecorations(() => {
    updateEditorHeight() // typing
    requestAnimationFrame(updateEditorHeight) // folding
})

let prevHeight = 0

const updateEditorHeight = () => {
    const editorElement = editor.getDomNode()

    if (!editorElement) {
      return
    }

    const lineHeight = editor.getOption(monaco.editor.EditorOption.lineHeight)
    const lineCount = editor.getModel()?.getLineCount() || 1
    const height = editor.getTopForLineNumber(lineCount + 1) + lineHeight

    if (prevHeight !== height) {
      prevHeight = height
      editorElement.style.height = `${height}px`
      editor.layout()
    }
  }

All 11 comments

A specific height is needed for container. Code could be hundreds of lines, and makes no sense to stretch editor by its content.
btw, you could use editor.layout() to re-layout the editor

@troy351 it is possible to get the size of the editor and then maybe decide to resize the container up to a certain limit, much like this github comment works ?

const contentHeight = editor.getModel().getLineCount() * 19 ; // 19 is the line height of default theme.
then you can set your container's height with contentHeight and run editor.layout()

@troy351 This will give incorrect results if you have collapsed content

@David-Mulder Good catch.
I did a lot of search but didn't find a onDidFoldingChange listener or a getFoldedLineCount method.
After trying for a long time, I figured out a hacky way to make it work.

// disable scroll beyond last line
editor.updateOptions({ scrollBeyondLastLine: false });

const LINE_HEIGHT = 18;
const CONTAINER_GUTTER = 10;

const el = editor.domElement;
const codeContainer = el.getElementsByClassName('view-lines')[0];

let prevLineCount = 0;

editor.onDidChangeModelDecorations(() => {
  // wait until dom rendered
  setTimeout(() => {
    const height =
      codeContainer.childElementCount > prevLineCount
        ? codeContainer.offsetHeight // unfold
        : codeContainer.childElementCount * LINE_HEIGHT + CONTAINER_GUTTER; // fold
    prevLineCount = codeContainer.childElementCount;

    el.style.height = height + 'px';

    editor.layout();
  }, 0);
});

BTW, a debounce is suggested for the listener.

I added an extra check that if codeContainer.offsetHeight === 0 to reschedule the wait until dom timeout again.

@abersnaze Could you provide the complete code sample? Thanks

@troy351 this actually works with word wrap enabled as well, nice job

In 0.19.3 the following seems to work without touching DOM to guess what the editor size is:

editor.onDidChangeModelDecorations(() => {
    updateEditorHeight() // typing
    requestAnimationFrame(updateEditorHeight) // folding
})

let prevHeight = 0

const updateEditorHeight = () => {
    const editorElement = editor.getDomNode()

    if (!editorElement) {
      return
    }

    const lineHeight = editor.getOption(monaco.editor.EditorOption.lineHeight)
    const lineCount = editor.getModel()?.getLineCount() || 1
    const height = editor.getTopForLineNumber(lineCount + 1) + lineHeight

    if (prevHeight !== height) {
      prevHeight = height
      editorElement.style.height = `${height}px`
      editor.layout()
    }
  }

Starting with 0.20.x, there is editor.getContentHeight(). This can be queried and the outer container height can be set to this value: e.g.

At https://microsoft.github.io/monaco-editor/playground.html

const width = 300;
const container = document.getElementById('container');
container.style.border = '1px solid #f00';
const editor = monaco.editor.create(container, {
    value: "function hello() {\n\talert('Hello world!');\n}",
    language: "javascript",
    scrollBeyondLastLine: false,
    wordWrap: 'on',
    wrappingStrategy: 'advanced',
    minimap: {
        enabled: false
    },
    overviewRulerLanes: 0
});
let ignoreEvent = false;
const updateHeight = () => {
    const contentHeight = Math.min(1000, editor.getContentHeight());
    container.style.width = `${width}px`;
    container.style.height = `${contentHeight}px`;
    try {
        ignoreEvent = true;
        editor.layout({ width, height: contentHeight });
    } finally {
        ignoreEvent = false;
    }
};
editor.onDidContentSizeChange(updateHeight);
updateHeight();

Kapture 2020-09-08 at 17 34 24

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aarinsmith picture aarinsmith  路  3Comments

Kedyn picture Kedyn  路  3Comments

andreymarchenko picture andreymarchenko  路  3Comments

akosyakov picture akosyakov  路  3Comments

chengtie picture chengtie  路  3Comments