Below is my code with a circle inside svg element which i want to render through jinja2 using st.html in streamlit the issue is the continer is visible but svg element is not visible. it is blank. see below code.
<style>
html,body {
height: 100%;
background-color: #404040;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
.container {
display: flex;
width: 500px;
/* Extended width for pipe */
height: 500px;
border: 3px solid #EEEEEE;
justify-content: center;
align-items: center;
border-radius: 20px;
}
.drawing {
position: relative;
width: 2000px;
/* Extended width for pipe */
height: 600px;
}
.circle-svg {
width: 100%;
height: 100%;
}
.c3 {
fill: none;
stroke: grey;
stroke-width: 10;
}
</style>
<body>
<div class="container">
<div class="drawing">
<svg viewBox="0 0 500 500" class="circle-svg">
<!-- Circle -->
<circle class="c3" cx="250" cy="250" r="198"></circle>
</svg>
</div>
</div>
</body>
python code:
def cutting_dimention(html_content):
# Directly use the HTML content without treating it as a file path
template = Template(html_content)
rendered_html = template.render() # Render the HTML with Jinja2
st.text(rendered_html) # Display rendered HTML text
st.html(rendered_html) # Display rendered HTML as an HTML block in Streamlit
cutting_dimention(my_circle)
I just had a play on
Streamlit's playground page and
noticed that st.html()
will accept <p>A paragraph</p>
but not your SVG tag.
As documented, they do internal sanitizing with DOMPurify, who strips it out of your output because
the <svg>
tag is not in the list of accepted tags.
I would suggest you two options:
You could create your own Streamlit component, following the official documentation.
I finally Googled and found that the st.markdown()
function
has the parameter unsafe_allow_html
which one can set to True
,
which will allow HTML in the Markdown code. And this output doesn't
seem to be filtered with DOMPurify.
Example:
st.markdown(
"""
<svg viewBox="0 0 500 500" class="circle-svg">
<circle class="c3" cx="250" cy="250" r="198"></circle>
</svg>""",
unsafe_allow_html=True
)
Outputs:
<div class="stElementContainer element-container st-emotion-cache-67qddt e1f1d6gn4" data-testid="stElementContainer" data-stale="false" width="252">
<div class="stMarkdown" data-testid="stMarkdown" style="width: 252px;">
<div data-testid="stMarkdownContainer" class="st-emotion-cache-phe2gf e1nzilvr5">
<svg viewBox="0 0 500 500" class="circle-svg">
<circle class="c3" cx="250" cy="250" r="198"></circle>
</svg>
</div>
</div>
</div>
The HTML output with your SVG tag is wrapped in some <div>
tags,
and will not be put inside an <iframe>
. So this might help
you, as you'll be able to apply some CSS rules or attach some event
handlers in JavaScript, without struggling to link the JS code
between the iframe and the parent page, neither need to set a size
to the iframe.
Notice that the width of the element-container
is updated live
by the Streamlit JavaScript code. So the attributes width="252"
and style="width: 252px;"
are changed when you resize the page.
This means that your SVG image will grow correctly by preserving its original ratio.
<svg>
tagI didn't see how to modify DOMPurify's config. It doesn't seem to be exposed by their API.
So I asked Google Gemini:
How do I configure streamlit to add the SVG tag as accepted tags in their internal DOMPurify configuration?
It told me that one cannot modify the config directly as it is not given
accessible via the API, but it also proposed to use the html component
via st.components.v1.html(your_svg_code, height=110)
.
I'm clearly not convinced, as it will put your SVG image inside an
<iframe>
, meaning that you won't be able to style it. Secondly, you'll
have to set a height to this iframe, which is stupid in your case.
I don't really know what is the best practise, but I would go for option A, to build a component that I can re-use or share with other Streamlit users.
I would choose option B if I quickly have to get things working and don't need to build a re-usable component.