st.expander
Insert a multi-element container that can be expanded/collapsed.
Inserts a container into your app that can be used to hold multiple elements and can be expanded or collapsed by the user. When collapsed, all that is visible is the provided label.
To add elements to the returned container, you can use the with notation (preferred) or just call methods directly on the returned object. See examples below.
By default, all content within the expander is computed and sent to the frontend, even if the expander is closed. To enable lazy execution where content only runs when the expander is open, use on_change="rerun", pass a callable to on_change, or set bind="query-params" (with key). The .open property indicates whether the expander is currently open when state tracking is enabled, letting you conditionally render expensive content.
Note
To follow best design practices and maintain a good appearance on all screen sizes, don't nest expanders.
Examples
Example 1: Use context management You can use the with notation to insert any element into an expander
import streamlit as st st.bar_chart({"data": [1, 5, 2, 6, 2, 1]}) with st.expander("See explanation"): st.write(''' The chart above shows some numbers I picked for you. I rolled actual dice for these, so they're *guaranteed* to be random. ''') st.image("https://static.streamlit.io/examples/dice.jpg")
Example 2: Call methods directly
You can call methods directly on the returned object:
import streamlit as st st.bar_chart({"data": [1, 5, 2, 6, 2, 1]}) expander = st.expander("See explanation") expander.write(''' The chart above shows some numbers I picked for you. I rolled actual dice for these, so they're *guaranteed* to be random. ''') expander.image("https://static.streamlit.io/examples/dice.jpg")
Example 3: Programmatically control the expander state
You can use a key to programmatically control the expander state or access the state in callbacks. Set on_change to "rerun" or a callable, or set bind="query-params", for the expander to track state.
import streamlit as st def toggle_expander(): st.session_state.summary = not st.session_state.summary def on_expander_change(): if st.session_state.summary: st.toast("You opened the expander.") else: st.toast("You closed the expander.") with st.expander("Open expander", on_change=on_expander_change, key="summary"): st.write("This is the expander") st.button("Toggle expander", on_click=toggle_expander)
Example 4: Display a timeline of steps
Use type="step" to turn consecutive expanders into a connected timeline. The last step is empty, so it terminates the timeline.
import streamlit as st with st.expander("Understanding the question", type="step"): st.write("Parsed: 'What is the weather in NYC?'") with st.expander("Searching for information", type="step"): st.json({"sources": ["weather.gov", "accuweather.com"]}) # A step with no content terminates the timeline. st.expander("Generating response", type="step")
ExpanderContainer
A container returned by st.expander.
ExpanderContainer is a Streamlit container with an .open property for lazy execution. Use with notation or call methods directly on the container to add elements to the expander.
Examples
Example 1: Lazy loading content
import streamlit as st import time summary = st.expander("Summary", on_change="rerun") if summary.open: with summary: with st.spinner("Loading summary..."): time.sleep(2) st.write("This is the summary")
Example 2: Conditionally render content outside of the expander
import streamlit as st summary = st.expander("Summary", on_change="rerun") with summary: st.write("This is the summary") st.write( f"The expander is {':green[open]' if summary.open else ':red[closed]'}." )
Tip
Want a new st.expander feature or found a bug? Browse open issues and react with a 👍 on the initial post of the ones that matter to you. Your votes help us prioritize what to work on next.
Still have questions?
Our forums are full of helpful information and Streamlit experts.
