Sticky banner conflict with st.segmented_control and st.form

I used answers from a few of these threads to create a sticky banner at the bottom of the viewport for my app:

This solution works for pretty simple pages. However, I have a page where I use st.segmented_control to decide which st.form is rendered. When I do so using this method, there seems to be some conflict caused by the use of the sticky banner markdown that causes the form to display on top of any widgets that exist before it. I have provided an example below. If you run it and select Option 1 in the segmented control bar you’ll see the issue.

def create_sticky_bar():
    button_bar = st.container()
    button_bar.write("""<div class='fixed-footer-w-buttons'><div/>""", unsafe_allow_html=True)
    st.markdown(
        """
        <style>
        div[data-testid="stVerticalBlock"] div:has(div.fixed-footer-w-buttons) {
            position: sticky;
            bottom: 0;                    
            background-color: white;
            padding-bottom: 0.3rem;
            }

        div[data-testid="stElementContainer"] div:has(div.fixed-footer-w-buttons) div {
            border-top: 1px solid #223398;
            }
        </style>
        """, unsafe_allow_html=True)
    with button_bar:
        button_cols = st.columns([1, 1, 10])


    return button_bar, button_cols

st.write("Some  text before the segmented control")


seg_selection = st.segmented_control(
    "Segmented Control Example",
    options=["Option 1", "Option 2", "Option 3"],
    format_func=lambda option: option,
    key="segmented_control_example",
    help="This is a segmented control example")

st.write("Some text before the form")

if seg_selection == "Option 1":
    with st.form("test_form", border=False, clear_on_submit=False):
    
        # Example input fields
        name = st.text_input("Name")
        age = st.number_input("Age", min_value=0, max_value=120, value=25)
        date_of_birth = st.date_input("Date of Birth", value=datetime.date.today())

        st.write(":material/phone_iphone:")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")

        # Form submit buttons
        # with st.sidebar:
        button_bar, button_cols = create_sticky_bar()
        with button_bar:
            st.form_submit_button("Submit", use_container_width=True)

BEFORE click Option 1

AFTER click Option 1

Anyone able to help me understand what is causing this issue?
Thanks

I have adjusted your script, hoping it will be helpful to you. For component CSS design, you can use the ‘streamlit-extras. stylabele_container’ package.

import streamlit as st
import datetime  
from streamlit_extras.stylable_container import stylable_container

def create_sticky_bar():
    with stylable_container(
        key='sty',
        css_styles='''
            {
                position: fixed;
                padding-bottom: 0.1rem;
                background: white;
                z-index: 1000;
                padding: 0 0;
                box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
                bottom: 0rem;  
            }
            div[data-testid="stElementContainer"] div:has(div.fixed-footer-w-buttons) div {
            border-top: 1px solid #223398;
            }
        '''
        ):
        with st.container(height=100, border=False):
            button_bar = st.container()
            button_bar.write("""<div class='fixed-footer-w-buttons'><div/>""", unsafe_allow_html=True)
            with button_bar:
                button_cols = st.columns([1, 1, 10])


    return button_bar, button_cols

st.write("Some  text before the segmented control")


seg_selection = st.segmented_control(
    "Segmented Control Example",
    options=["Option 1", "Option 2", "Option 3"],
    format_func=lambda option: option,
    key="segmented_control_example",
    help="This is a segmented control example")

st.write("Some text before the form")

if seg_selection == "Option 1":
    with st.form("test_form", border=False, clear_on_submit=False):
    
        # Example input fields
        name = st.text_input("Name")
        age = st.number_input("Age", min_value=0, max_value=120, value=25)
        date_of_birth = st.date_input("Date of Birth", value=datetime.date.today())

        st.write(":material/phone_iphone:")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")
        st.write("Filler")

        # Form submit buttons
        # with st.sidebar:
        button_bar, button_cols = create_sticky_bar()
        with button_bar:
            st.form_submit_button("Submit", use_container_width=True)
1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.