Are you using HTML in Markdown? Tell us why!

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).

st.markdown(
        """
<style>
canvas {
max-width: 100%!important;
height: auto!important;
</style>
""",
        unsafe_allow_html=True
    )

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!

2 Likes

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
Dan

2 Likes

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 = """
                <style>
                .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;
                }}
                </style>
                <div style="text-align:left">
                <h3>Legend</h3>
                <span class="bdot"></span>  {} - {}<br>
                <span class="gdot"></span>  &#62;{} - {}
                </div>
                """.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.

st.markdown("""
<style>
body {
    color: #fff;
    background-color: #111;
    etc. 
}
</style>
    """, 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.

2 Likes

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.

3 Likes

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:

4 Likes

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 = HtmlFile.read() 
    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.open();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 - demo.py (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'],
    ['lat','lon'])

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 = HtmlFile.read()
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 https://github.com/streamlit/streamlit/issues/859 :bow_and_arrow: )

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

1 Like

Hello!

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 m.save('./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 app.py.

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:

/Users/nthmost/.local/share/virtualenvs/st_sandbox-D9fr_O3a/lib/python3.7/site-packages/streamlit/static/

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!

2 Likes

@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!

2 Likes

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:

1 Like

Hello, do you have any idea how could we use folium in streamlit? I donā€™t understand why it doesnā€™t work with st.markdown(m.repr_html(), unsafe_allow_html =True). And I donā€™t have any other solutions for now to display my folium result with streamlit. Tks for your reply

Hello, I have the same problem in using folium in streamlit, could you please tell me how you fix this problem?