Customizing text in st.expander

Summary

I am curious if there is a way to customize streamlit expander?

Adding styling options like newline, font size and mixing f-string inside the label.

Thanks.

@newbie123 You can always use the st.markdown() for styling. You just need to specify the Streamlit class of the generated elements and you’re good to go.

st.markdown("""
  <style>
  </style>
    """, unsafe_allow_html=True)
2 Likes

Most of the formatting that you can do with Markdown can be passed to the header of the st.expander: colors, bold, italics, etc.

Code:
import streamlit as st

value = st.number_input("Value")

text = rf""" 
:pencil: **Multiline** expander title _with some_ :violet[color].

:green[Another line here and an equation:]

$$

    \sqrt{{x^2+y^2}}=1

$$

Here is an f-string: `{value = :.2f}`.

"""

# text

with st.expander(text, expanded=False):
    "Hello from the expander"

Other modifications, like changing the font size, will need to inject some CSS as @IndigoWizard pointed out.

Excellent! Works like a charm. However it seems to ignore # for header size. Is there a way to change the font size?

Sorry, I am not sure what that means. could you enlighten me with a few lines of code example using st.expander and st.markdown?

@newbie123 You can inject custom CSS with st.markdown() the esthetics as follows:

st.markdown("""
  <style>
     /* Streamlit class name of the div that holds the expander's title*/
    .css-q8sbsg p {
      font-size: 32px;
      color: red;
      }
    
     /* Streamlit class name of the div that holds the expander's text*/
    .css-nahz7x p {
      font-family: bariol;
      font-size: 20px;
      }
  </style>
""", unsafe_allow_html=True)

Before custom CSS

After custom CSS

NOTE:
  1. You can get the class names of the dives by simply using your browser’s inpsect element.
  2. Make sure to inject it in the right place, sometimes it’s better to add it after the elment is created (your expander in this case), like at the end of the code and sometimes it’s fine to have it before.
1 Like

I am using Streamlit for my project. When I set expanded=True, the expander does not go to a new line; instead, it stays at the top of the chat. I have tried several ways, but it’s not working.

if questions_list:
    with st.expander(" Questions", expanded=True):
        for item in questions_list:
            st.button(label=item, on_click=update_chat_input, args=(item,))

Hello,

Thanks for sharing, the result looks very good. Unfortunately I didn’t manage to reproduce it by copy pasting your code. Here is what I got :

It appears that the headers of st.expanding don’t treat the input as markdown but simple text.

I’ve tried it with 1.22.0, 1.25.0 and the latest version of streamlit, but the result is the same.

Would you have some explanations for that?

Many thanks.

Check the indentation of the text.

Indented text Not indented text
Indented text:
import streamlit as st

value = st.number_input("Value")

text = rf""" 
    :pencil: **Multiline** expander title _with some_ :violet[color].

    :green[Another line here and an equation:]

    $$

        \sqrt{{x^2+y^2}}=1

    $$

    Here is an f-string: `{value = :.2f}`.
"""

with st.expander(text, expanded=False):
    "Hello from the expander"
Not indented text:
import streamlit as st

value = st.number_input("Value")

text = rf""" 
:pencil: **Multiline** expander title _with some_ :violet[color].

:green[Another line here and an equation:]

$$

    \sqrt{{x^2+y^2}}=1

$$

Here is an f-string: `{value = :.2f}`.
"""

with st.expander(text, expanded=False):
    "Hello from the expander"

To programmatically remove indentation, check textwrap — Text wrapping and filling — Python 3.13.0 documentation

1 Like