Are you using HTML in Markdown? Tell us why!

For markup of raw text in NLP. Highlighting certain features, original spacing, etc…
Streamlit formats the text which is nice but sometimes it is needed to see raw text and still use some custom formatting.


It’d be great to be able to adjust the background.
E.g. Creating a moving background using HTML and CSS.

We’re using unsafe_allow_html in a few places now to inject css. The most recent is to make our Altair-based graphs responsive (they previously looked pretty bad on mobile).

canvas {
max-width: 100%!important;
height: auto!important;

I have a lot of trust in the Streamlit team, because you’re doing awesome stuff. But I’m still nervous about whether we’ll be able to replicate these css hacks after the deprecation…

Hi Dan — thanks for the kind words!

Regarding your max-width hack, we’re probably going to have an official solution soon.

As for the Altair issue, can you create a bug report for it? This is the first time I’m hearing about it, but it sounds like something we should address too.

Regarding all the other things in this thread (and in assorted Github issues!), we have recently compiled a doc where we cluster everyone’s use-cases into categories and then brainstorm official solutions for each. So there is some progress, even though you can see it yet! Our goal really is to have clean solutions for the vast majority of things people are proposing here, and at his point I’m confident it’s doable.

More on this very soon!


Thanks. I may have mischaracterized things with the graphs looking bad. It was just that we previously set widths that made sense for desktop, and they were (as one would expect) too wide to look good on mobile.

So, the only issue was wanting the responsiveness we get from that css hack. Glad to hear there’s good solutions in the works =)

Thanks again for all the thought you’re putting into this


I just used html and css to generate a legend for pydeck charts. My map shows concentrations with a color gradient going from blue to green. I have not found a way in pydeck to generate this, so I included the code below, that renders a blue and a green dot with the corresponding value interval. Ideally of course, I could generate the legend with pydeck directly (maybe this is possible and I just did not find out how :smile:). Second best solution would be if I could generate Unicode symbols directly from streamlit:
st.write(st.symbol(#9679, blue) + ‘10-15’)
st.write(st.symbol(#9679, green) + ‘15-20’)
so something like this is shown:
:large_blue_circle: 10-15
:green_circle: >15-20

However, I find HTML/CSS very handy and fear it will be difficult to replace it by something similarly flexible.

legend = """
                .bdot {{
                height: 15px;
                width: 15px;
                background-color: Blue;
                border-radius: 50%;
                display: inline-block;
                .gdot {{
                height: 15px;
                width: 15px;
                background-color: #4DFF00;
                border-radius: 50%;
                display: inline-block;
                <div style="text-align:left">
                <span class="bdot"></span>  {} - {}<br>
                <span class="gdot"></span>  &#62;{} - {}
                """.format(round(min_val), round((max_val - min_val) / 2), round((max_val - min_val) / 2), round(max_val))
            st.markdown(legend, unsafe_allow_html=True)

I’m starting to experiment with converting an app to something that feels like dark mode.

body {
    color: #fff;
    background-color: #111;
    """, unsafe_allow_html=True)

There’s still some work needed to update all the colors like I’d want them, as well as adjusting the color pallete in plots so they don’t fry my corneas against the black background.

I may put it on hold until I there’s more info about how much CSS control we’ll have after the relevant changes. But it’d be nice to be able to do this.

1 Like

I want to use html not due to formatting reasons, but because more and more python libraries render the output of analysis in HTML format.

As such, these are not html injected by me, but are directly generated by those packages after me inputting some legit input. They could be interactive charts or rich-formatted tables.

Without html function one would go extreme length to reverse-engineer the original package, by stopping the function one step short of the html output, then plot one’s own chart, basically re-do a lot of things already in those packages. Many times that’s not feasible.


I wanted to insert script tag with JS code. The code adds keyboards shortcuts to buttons in my Streamlit app.

Update: We heard you, and have no plans to deprecate allow_unsafe_html ! :champagne:

Thank you for sharing your thoughts. It’s really useful!! :pray:t2:


i just try ur code, but the maps didnt show, how ?thanks

1 Like

That’s great to hear, I had some nightmares about html being disabled :wink:

1 Like

I converted an ipynb notebook to a local html file and displayed it in streamlit.

    HtmlFile = open("sales_impact_report.html", 'r', encoding='utf-8')
    source_code = 
    st.markdown(source_code, unsafe_allow_html=True)

However, my output gives me this, how can i hide/remove the blocks before my header?

1 Like

Hi @Chris_Brake,
Thanks for your contribution.

I’m having trouble trying to make this work here. If I just use st.write(m.repr_html()), then copy the code and inject it manually in the page source code, my map shows ok.

But if I try to use st.markdown(m.repr_html(), unsafe_allow_html=True) the object uses the space in the page but shows nothing.

Did you face a similar problem? I can’t figure out what is going wrong.

If I inspect the page source code, all js code is missing after using st.markdown. For instance, if I add onload=“;this.contentDocument.write(atob(this.getAttribute(‘data-html’)));this.contentDocument.close();” before allowfullscreen the map is correctly shown.

This is the file I’m trying to replicate - (version 0.53.0):

import streamlit as st
import pandas as pd
import folium

all_cities = pd.DataFrame(
    [(40.7127837, -74.0059413),(34.0522342, -118.2436849),(41.8781136, -87.6297982)],
    ['New York', 'Los Angeles', 'Chicago'],

selected_city = st.selectbox('Select city', all_cities.index)

route_map = folium.Map(location=(all_cities.loc[selected_city]), zoom_start=9, control_scale=True)

aux = route_map._repr_html_()
st.markdown(aux, unsafe_allow_html=True)
1 Like

Hi @dqniellew1,

You may be in a bit of a bind with trying to display this HTML in Streamlit, because it looks a lot like those scripts are needed to make the exported HTML code work.

You could attempt to strip this entire header out of the HTML you’re reading with something like this:

HtmlFile = open("sales_impact_report.html", 'r', encoding='utf-8')
source =
end_tag = "</head>"
source = source[source.find(end_tag)+len(end_tag):]
st.markdown(source, unsafe_allow_html=True)

Since I don’t know what the entire HTML looks like, I can only guess at what will happen if you strip the header out, but I know that your header is not being interpreted as HTML right now (because it’s being displayed). So it’s worth a try.

Conceptually speaking, if you want to get Streamlit to take an entire pre-constructed page of HTML via the markdown processor, you’re going to have to feed any Javascript or styling in on a block-by-block basis.

This is because the Markdown processor will respect the “unsafe_allow_html” flag for the first chunk of code it encounters, but not after the first newline. (This causes other problems as well, and we really want to fix this. See :bow_and_arrow: )

Thanks for your question. I promise this will get easier in the near future. :heavy_heart_exclamation:

1 Like


First of all, I have to thank you for streamlit, such a great and beautiful library and it works perfectly.

On the other hand, I am facing a problem such as @Lazaro_Pinheiro_Domi . I have tried his code and also the following:

import streamlit as st
import folium

m = folium.Map([38.8934, -76.9470], tiles=’stamentoner’,   zoom_start=12)
st.markdown(m._repr_html_(), unsafe_allow_html =True)

Firstly, I tried that way, but, as Lazaro mentioned, it just returns an empty white box. I have tried working with previous versions of Streamlit and Folium but no satisfactory result was obtained. I also tried to manually add the .html file that it is generated when you do'./map.html') with the following:

st.markdown('<iframe src="./STREAMLIT/img/map.html"> </iframe>', unsafe_allow_html=True)

However, it did not work (perhaps because my HTML knowledge is limited), it does not seem able to find the path, and I have tried many approaches. Note that img is a folder where I have put the map and that in the STREAMLIT folder is where it is the

One last approach I have thought about is maybe introducing a button that redirects to the HTML map (locally stored, because I am actually running this locally, I am not either planning to deploy this into a server yet), however, I cannot make it work.

Here is some more info:

Python: 3.6
Ubuntu: 18.04
Google Chrome 80.0, Mozilla 73.0

Thanks in advance and have a nice day!

1 Like

Hi @Adri_Lopez,

I really respect how much problem-solving you’re putting into this!

The issue with where you put the output HTML file is that Streamlit has no map to finding this. What you should be able to do (and this isn’t “recommended”, but if you’re intent on hacking a solution for this anyway) is place your HTML file under the “static” folder in the installed streamlit package for your virtual environment.

For example, my static folder for when I’m experimenting with Streamlit features is here:


Yours should look like mine after the st_sandbox-D9fr_O3a.

Put an HTML page in there and test it out by doing streamlit hello and then changing the url to your test page, e.g. http://localhost:8501/test.html

I can promise you this is not going to be a supported way to do things in the future, and we’re working on incorporating 3rd party HTML outputs in Streamlit in a more formal manner. But this should work for you in the short term.

Thanks for your interest!

1 Like

@Adri_Lopez @Lazaro_Pinheiro_Domi did you guys find a good workaround to render folium maps?

I have just tried it and it works perfectly. I really appreciate your effort in answering and understanding everyone’s problems. I still don’t understand why the _repr_html_.() function doesn’t work on my case, but anyway, if I can figure it out, I will tell you all. :slight_smile:

Thanks a lot!


Thanks so much @Adri_Lopez! It feels good to have effort appreciated and I really needed to hear that today. :heart:

Hope you and everyone you know are keeping safe! :mask: