mermaid-js/mermaid

Huge white margins on img/png output of large diagrams

Closed this issue ยท 7 comments

PNG output of non-trivial diagrams has huge top/bottom margin

Screenshots
Mermaid img output

ambrt commented

I noticed that such margins appear when .mermaid element is set to width:100%.
When forcing 200% .mermaid {width:200% !important} huge top margin goes away.

I found that by setting useMaxWidth to false also removes the top and bottom margins. By default it is set to true. See https://mermaid-js.github.io/mermaid/#/Setup?id=mermaidapi-configuration-defaults.

For me the the CSS trick didn't work. But the useMaxWidth did. The doc is confusing written so I wasn't sure where I needed to put the config. But I finally figured out it was in the chart options.

{
    "theme": "default",

    "logLevel": "debug",

    "securityLevel": "loose",

    "flowchart": {
        "htmlLabels": true,
        "curve": "basis",
        "useMaxWidth": false
    }
}

Since mermaid 8.6.0, you can use directives straight into the diagram, without fiddling with JavaScript and CSS. For this particular case, I used:

%%{init: {"flowchart": { "useMaxWidth": false } }}%%
graph LR
...
Loading

Here's a workaround if you want to keep useMaxWidth:

mermaid.mermaidAPI.initialize({
    startOnLoad: false
})

// works around padding bug: https://github.com/mermaid-js/mermaid/issues/1758
$(function() {
    const elements = document.querySelectorAll('.mermaid')
    for (const e of elements) {
        const id = `mermaid-${Math.floor(Math.random() * 10000000)}`
        
        const container = document.createElement('div')
        container.setAttribute('id', id)
        e.appendChild(container)
    
        const cb = (svgCode, bindFunctions) => {
            e.innerHTML = svgCode
            e.setAttribute('id', id)
            e.querySelector('svg').setAttribute('height', e.querySelector('g').getBoundingClientRect().height)
        }
        mermaid.mermaidAPI.render(id, e.firstChild.nodeValue.trim(), cb)
    }
});

The SVG element itself has a wrong bounding box, but you can get the client rect of the first group element and then set the SVG height attribute to it. This only works on initial page load (uses jQuery, bind to DOMContentLoaded otherwise). If you want to react to window resizes, you will have to add an additional event handler for that.

@phoerious solution works for flowcharts, however it doesn't for sequence diagrams, because the first <g> element has 0 height. However, what worked for us was removing the height attribute altogether.

I can make it work for sequence diagrams by set css for <svg> to height: 100%; in browser debug, but didn't know how to set it via mermaid.initialize ๐Ÿค”