"Back" button in header

I need to create a “back” button that it will switch to another streamlit page (st.switch_page).

But the challenge is the following:

  1. The button must be a custom image (svg or png).
  2. It should be part of h1 section in st.markdown.
  3. Ideally it should be moved to left by 3rem (just like default streamlit link icon for headers).

I want it to look like this

Any suggestions are welcome!

I don’t think <h1> elements can have embedded content.

1 Like

Yes, I am aware that it cannot be done without some tweaks.
I have seen similar solution with adding an icon to st.metric with stylable_container here: 😍 Adding an icon to a st.metric easily.
But I haven’t found a way to make it clickable.

1 Like

You can hack your way to displaying the image next to the header, but it won’t be part of the <h1> element.

You need to use the component API to capture mouse clicks. I think there is a clickable image component that may or may not suit your needs.

1 Like

Here’s one way to do it – take a button and add some styling so it looks like the image you drew:

import streamlit as st

content1 = """
# Page 1

This is page 1
"""

content2 = """
# Page 2

This is page 2
"""

if "page" not in st.session_state:
    st.session_state.page = "page1"


def back_button():
    st.session_state.page = "page1"


def next_button():
    st.session_state.page = "page2"


cols = st.columns([1, 10])
if st.session_state.page == "page1":
    with cols[0].container():
        st.html("<span class='button'></span>")
        st.button("→", on_click=next_button)
    cols[1].write(content1)
else:
    with cols[0].container():
        st.html("<span class='button'></span>")
        st.button("←", on_click=back_button)
    cols[1].write(content2)


st.html(
    """
<style>
[data-testid="stVerticalBlock"]:has(.button) button {
    border: 2px solid yellow;
    color: yellow;
    border-radius: 50%;
    padding: 0;
    width: 41px;
    height: 41px;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 26px;
}
[data-testid="stVerticalBlock"]:has(.button) button p{
    font-size: 2rem;
    margin-bottom: 3px
}
</style>
"""
)

Result:
image

It’s not pixel-perfect, but you should be able to fiddle with the CSS to get it to look how you want

3 Likes

Thank you!

I was pretty convinced that the way to go is to use the st.button with some styling, but how you used the arrow icon with combination of border-radius to avoid using svg/png is simply brilliant :slight_smile:

2 Likes

I successfully implemented this approach in my application.
I just added more precise conditions in CSS - to avoid styling of some other buttons :slight_smile:

div[data-testid="stVerticalBlock"]:has(> div > div > .back_button)

Thanks again!

2 Likes

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