Cannot force line breaks in dcc.Markdown

Hello,
I’m trying to format some text to go into a dcc.Markdown element of a Dash app. I’m succeeding in using markdown such as “some text in bold”, but I struggle to enforce line breaks. According to Dash HTML Components | Dash for Python Documentation | Plotly, Dash Markdown should support CommonMark Spec. The latter states that backslash can be used to force line breaks (see section 6.7 Hard Line Breaks), but it is not happening when my Markdown is rendering in my app. How do I enforce line breaks?

You could use dangerously_allow_html=True and add <br /> where you want new line breaks. Make sure that you control where the content comes from before setting dangerously_allow_html to true though.

1 Like

Thanks, that’s a nice workaround, but as the documentation states it can be done with markdown without setting that flag, I won’t label it as a solution.

If you don’t want to set dangerously_allow_html, you can force a new line by ending the line with two or more spaces, then type return.

that would equate to " \r" in Python, right? In my code I’m using
'<markdown to allow line breaks>'.join(<my_list_of_text_elements_to_be_shown_on_separate_lines)

Inserting ’ \r’ for <markdown to allow...> does not work, unfortunately. With @RenaudLN’s suggestion of using '<br/> as <markdown to allow...> combined with dangerously_allow_html, it works well, but from the docs it seems it should be possible to simply use a backslash, without the flag.

not sure what you mean, but you can’t include HTML without setting the flag.

Adding to above, if you don’t want to set dangerously_allow_html you can also use &nbsp;- that’s what I’m normally using :slight_smile: So for example:

"""
My markdown string - bla bla
Another string

&nbsp;

Another section further down.
"""
3 Likes

Ideally I wouldn’t have to use HTML, just Markdown. However, although Dash HTML Components | Dash for Python Documentation | Plotly says that Dash Markdown is in accordance with CommonMark Spec, it does not seem to be the case (as backslashes in my Markdown do not cause line breaks).

Hi @Ernie,

Indeed, using a backslash doesn’t work, probably because it has a special meaning in python’s strings…
But double spaces (+new line = ‘\n’) works :tada:
If you have a list of strings you want to join with new line in markdown try:
' \n'.join(my_string_list)

3 Likes

This was a very annoying problem for me! This is the way to do it w/o using dangerously_allow_html=True, with proof

Before

example_query = (
    '''
    SELECT
    TOP 1 *
    FROM TABLE_NAME
    WHERE some_id = 4
    '''
)
app.layout = html.Div([
    html.H1("Example app"),
    dcc.Markdown(example_query, style={'overflow': 'hidden'})
])

imperfect_markdown

After

example_query = (
    '''
    SELECT
    TOP 1 *
    FROM TABLE_NAME
    WHERE some_id = 4
    '''
)
app.layout = html.Div([
    html.H1("Example app"),
    dcc.Markdown(f"```\n{example_query}\n```", style={'overflow': 'hidden'})
])

perfect_markdown

Basically, take your multi-line string, format it with markdown ticks, and add line breaks to the beginning and end.

1 Like

@Skiks, that’s exactly the type of solution I was looking for. However, I cannot make it work.

My app creates Markdown for pandas DataFrames. An example (using ’ \n’ to separate lines):

df = DataFrame({'hey': [2,3,4,5], 'you': [132,12315,3,111]})
generate_dash_markup(df, df.columns, 'new_col')

Which causes df to look like this:

   hey    you                         new_col
0    2    132    **hey** = 2  \n**you** = 132
1    3  12315  **hey** = 3  \n**you** = 12315
2    4      3      **hey** = 4  \n**you** = 3
3    5    111    **hey** = 5  \n**you** = 111

The Markdown looks right, but when it renders in the browser, it looks like this:
hey = 2 \nyou = 132

It seems the two spaces collapse into one. Using &nbsp; (see How do I ensure that whitespace is preserved in Markdown? - Stack Overflow), just like @li.nguyen mentioned, I can prevent the spaces from collapsing. However, the outcome is just that the following is rendered in the browser:
hey = 2  \nyou = 132
(two spaces now instead of one)
Do you have an idea as to what I’m doing wrong?

Oops! For some reason I used raw string literals (r' \n'.join(my_list))! It should have been
' \n'.join(my_list). My bad, and thanks for the solution, @Skiks !

2 Likes