Can I wrap or other elements inside custom HTML?


While waiting for elements/ components/ layout/ style etc. is there any chance that I can wrap the elements inside custom HTML?

For example could I inside a “card” div like the below?


I’ve used the below code for the experiment

import streamlit as st

def html(body):
    st.markdown(body, unsafe_allow_html=True)

def card_begin_str(header):
    return (
        "<style>div.card{background-color:lightblue;border-radius: 5px;box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);transition: 0.3s;}</style>"
        '<div class="card">'
        '<div class="container">'

def card_end_str():
    return "</div></div>"

def card(header, body):
    lines = [card_begin_str(header), f"<p>{body}</p>", card_end_str()]

def br(n):
    html(n * "<br>")

card("This works", "I can insert text inside a card")


html(card_begin_str("This does not work"))"I cannot insert an element inside a card")

And I can see that the problem is that the un-closed html is closed and wrapped in it’s own “element-container” div when using st.markdown.


Hi @Marc,

Thanks for your question. As you are discovering, what you’re attempting points at limitations in what you can do based on how Streamlit renders content.

Since Streamlit treats each text “utterance” as its own separate element, you’re going to end up with standard Markdown divs and CSS wrapped around each chunk. This has the positive effect of protecting elements from unwanted side effects to each other (e.g. accidentally unclosed div tags, which is how your card function’s output would be treated), but the undesired effect of making it difficult to create novel structure and styling on your dashboard.

We’d certainly like to make Streamlit more customizable in the near future. People are going to want more control over how their dashboards are put together and styled.

How we give people more flexibility over time is a matter of ongoing discussion, some of which you’ve already been part of. :slight_smile:

1 Like