Hello Streamlit community,
I’m experiencing a persistent content bleeding issue in my multi-page Streamlit app that
only occurs in the deployed environment (Kubernetes/Docker) but works perfectly in local
development.
The Problem
When navigating between pages with different amounts of content, old content from the
previous page remains visible underneath the current page:
- Navigate from a large page (e.g., Executive Dashboard with multiple tabs and tables) to
a smaller page (e.g., About page with just text) - Scroll down on the smaller page
- Old content from the previous page is still visible below
This also affects sidebar content - filters and widgets from previous pages remain
visible.
Environment Details
Where it FAILS:
- Kubernetes deployment (containerized)
- Docker deployment
- Streamlit Cloud deployment (if applicable)
Where it WORKS:
- Local development with streamlit run
- Works perfectly every time locally
What I’ve Tried
- Using st.empty() placeholders (recommended approach)
At the top of each page
sidebar_placeholder = st.sidebar.empty()
main_placeholder = st.empty()
Wrap all sidebar content
with sidebar_placeholder.container():
st.markdown(“## Filters”)
… all sidebar widgets
Wrap all main content
with main_placeholder.container():
st.title(“My Page”)
… all page content
Result: Works perfectly in local development, but content still bleeds in deployed
environment.
- Adding CSS to force layout consistency
st.markdown(“”"
.main .block-container { width: 100% !important; max-width: 100% !important; }“”", unsafe_allow_html=True)
Result: Helps with layout compression but doesn’t fix content bleeding in deployment.
- Using st.rerun() and session state
Tried clearing session state and forcing reruns - still doesn’t clear old content in
deployed environment.
Code Structure
Page 1 (Large page with lots of content)
import streamlit as st
st.set_page_config(layout=“wide”)
sidebar_placeholder = st.sidebar.empty()
main_placeholder = st.empty()
with sidebar_placeholder.container():
Many filters and options
st.selectbox(“Filter 1”, options)
st.multiselect(“Filter 2”, options)
… more widgets
with main_placeholder.container():
Lots of content
tab1, tab2, tab3 = st.tabs([“Tab 1”, “Tab 2”, “Tab 3”])
Multiple dataframes, charts, metrics
Page 2 (Small page)
import streamlit as st
st.set_page_config(layout=“wide”)
sidebar_placeholder = st.sidebar.empty()
main_placeholder = st.empty()
with sidebar_placeholder.container():
st.markdown(“—”)
st.info(“Simple page”)
with main_placeholder.container():
st.title(“About”)
st.markdown(“Just some text here”)
Minimal content
Questions
- Why does this only happen in deployed environments? Local development works flawlessly
with the exact same code. - Is there a different approach for production deployments? Are there
environment-specific Streamlit configurations needed? - Could this be related to how Streamlit handles page state in containerized
environments? Perhaps session management differs between local and deployed? - Are there any Streamlit config.toml settings that might help with this issue in
production?
Additional Context
- The issue is consistent and reproducible in deployment
- Refreshing the page (F5) clears the content temporarily
- The problem gets worse with more page navigation
- All pages use the same st.empty() placeholder pattern
Has anyone else experienced this? Any suggestions for making st.empty() placeholders work
consistently in deployed environments?
Thanks in advance!