Error when customize button style to use image as a background

Hi guys,

im new to Streamlit, and I want to create three buttons, each one with differen image as backgroud, the code of doing that i found is first convert the image to base64, then apply it to the button style below:

button_style = f"""
                        <style>
                        div.stButton > button {{
                            background: url(data:image/png;base64,{encoded_image}) no-repeat;
                            background-size: cover;
                            background-position: center;
                            height: 16em;
                            width: 24em;
                            box-shadow: 10px 10px 5px grey;
                            margin: 15px;
                        }}
                        </style>
                        """
            st.markdown(button_style, unsafe_allow_html=True)

however, it seems only the last โ€˜encoded_imageโ€™ is working, that my three buttons showing the same background image, can anyone tell me how to properly set the correct image background? below is my full code for this one:

import streamlit as st
import pandas as pd
import re
import os
import base64

def display_image_csv_viewer(file_path):
    st.set_page_config(layout='wide')

    all_files = search_file(file_path)
    image_files = [file for file in all_files if file.find('twitter_image') != -1]
    paper_files = [file for file in all_files if file.endswith('.csv')]

    encoded_images = {}
    for i, image_file in enumerate(image_files):
        with open(image_file, "rb") as f:
            encoded_image = base64.b64encode(f.read()).decode()
            encoded_images[f"button{i + 1}"] = encoded_image

    # Create buttons dynamically
    cols = st.columns(len(encoded_images))

    selected_button_key = st.session_state.get('selected_button_key')

    for i, button_key in enumerate(encoded_images.keys()):
        with cols[i]:
            encoded_image = encoded_images[button_key]
            # Apply new button style
            button_style = f"""
                        <style>
                        div.stButton > button {{
                            background: url(data:image/png;base64,{encoded_image}) no-repeat;
                            background-size: cover;
                            background-position: center;
                            height: 16em;
                            width: 24em;
                            box-shadow: 10px 10px 5px grey;
                            margin: 15px;
                        }}
                        </style>
                        """
            st.markdown(button_style, unsafe_allow_html=True)

            if selected_button_key == button_key:
                st.button('', key=button_key, on_click=None)
            else:
                if st.button('', key=button_key):
                    selected_button_key = button_key
1 Like

Hi @kow! And welcome to our Community! :raised_hands:

You may need to target each button individually by adding a unique ID to each button and setting the CSS accordingly.

Try the following amendment for button_style:

button_style = f"""
                        <style>
                        #{button_key} div.stButton > button {{
                            background: url(data:image/png;base64,{encoded_image}) no-repeat;
                            background-size: cover;
                            background-position: center;
                            height: 16em;
                            width: 24em;
                            box-shadow: 10px 10px 5px grey;
                            margin: 15px;
                        }}
                        </style>
                        """

Then tweak the below if statement accordingly:

if selected_button_key == button_key:
    st.markdown(f'<div id="{button_key}">', unsafe_allow_html=True)
    st.button('', key=button_key, on_click=None)
    st.markdown('</div>', unsafe_allow_html=True)
else:
    st.markdown(f'<div id="{button_key}">', unsafe_allow_html=True)
    if st.button('', key=button_key):
        selected_button_key = button_key
    st.markdown('</div>', unsafe_allow_html=True)

I havenโ€™t had a chance to try this, but please let me know if that makes a difference.

Best wishes,
Charly

@Charly_Wargnier Thanks for your reply:)

I tried with your code, and the button now are three white blank, below is code for you to see if i done it wrong:

import streamlit as st
import pandas as pd
import re
import os
import base64

def display_image_csv_viewer(file_path):
    st.set_page_config(layout='wide')

    all_files = search_file(file_path)
    image_files = [file for file in all_files if file.find('twitter_image') != -1]
    paper_files = [file for file in all_files if file.endswith('.csv')]

    encoded_images = {}
    for i, image_file in enumerate(image_files):
        with open(image_file, "rb") as f:
            encoded_image = base64.b64encode(f.read()).decode()
            button_key = f"button{i + 1}"
            encoded_images[button_key] = encoded_image

    # Create buttons dynamically
    cols = st.columns(len(encoded_images))

    selected_button_key = st.session_state.get('selected_button_key')

    for i, button_key in enumerate(encoded_images.keys()):
        with cols[i]:
            encoded_image = encoded_images[button_key]
            button_style = f"""
            <style>
            #{button_key} div.stButton > button {{
                background: url(data:image/png;base64,{encoded_image}) no-repeat;
                background-size: cover;
                background-position: center;
                height: 16em;
                width: 24em;
                box-shadow: 10px 10px 5px grey;
                margin: 15px;
            }}
            </style>
            """
            if selected_button_key == button_key:
                st.markdown(f'<div id="{button_key}">', unsafe_allow_html=True)
                st.button('', key=button_key, on_click=None)
                st.markdown('</div>', unsafe_allow_html=True)
            else:
                st.markdown(f'<div id="{button_key}">', unsafe_allow_html=True)
                if st.button('', key=button_key):
                    selected_button_key = button_key
                st.markdown('</div>', unsafe_allow_html=True)

Thanks, @kow!

Is there any way you could deploy on st.lite or a similar platform so that we can debug/experiment from there?

Thanks,
Charly

@Charly_Wargnier Thanks:)

Iโ€™m new to the site you provided, and it seems if I upload files, it will prevent me from sharing the site (over 32000 charachters), so I have no choice but give you a google driver sharing link with my test data, but i put my code on the site you provided, below are the sharing link along with the site code link:

Google Drive

https://drive.google.com/file/d/1vG38yobLVWwRfobKxwQFTmSA1yDgSt4b/view?usp=sharing

Site code link:

https://share.stlite.net/#!ChBzdHJlYW1saXRfYXBwLnB5EoYfChBzdHJlYW1saXRfYXBwLnB5EvEeCu4eaW1wb3J0IHN0cmVhbWxpdCBhcyBzdAppbXBvcnQgcGFuZGFzIGFzIHBkCmltcG9ydCByZQppbXBvcnQgb3MKaW1wb3J0IGJhc2U2NAoKCmRlZiBzZWFyY2hfZmlsZShmaWxlX3BhdGgpOgogICAgZmlsZV9uYW1lID0gW10KICAgIGZvciBwYXJlbnQsIGRpcm5hbWVzLCBmaWxlbmFtZXMgaW4gb3Mud2FsayhmaWxlX3BhdGgpOgogICAgICAgIGZvciBmbiBpbiBmaWxlbmFtZXM6CiAgICAgICAgICAgIGZpbGVfbmFtZS5hcHBlbmQob3MucGF0aC5qb2luKHBhcmVudCwgZm4pKQoKICAgIHJldHVybiBmaWxlX25hbWUKCgpkZWYgZGlzcGxheV9jb250ZW50KGNvbnRlbnQpOgogICAgc3QubWFya2Rvd24oZiIiIgogICAgICAgIDxkaXYgc3R5bGU9IgogICAgICAgICAgICBmb250LXNpemU6MTZweDsKICAgICAgICAgICAgYm9yZGVyOjJweCBzb2xpZCAjZjYzMzY2OwogICAgICAgICAgICBib3JkZXItcmFkaXVzOiA1cHg7CiAgICAgICAgICAgIHBhZGRpbmc6IDEwcHg7CiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGYwZjA7CiAgICAgICAgICAgIGNvbG9yOiAjNGY0ZjRmOwogICAgICAgICAgICBib3gtc2hhZG93OiA1cHggNXB4IDVweCBncmV5OyI-CiAgICAgICAgICAgIHtjb250ZW50fQogICAgICAgIDwvZGl2PgogICAgIiIiLCB1bnNhZmVfYWxsb3dfaHRtbD1UcnVlKQoKCmRlZiBjaGVja19saXN0X2Zvcm1hdCh2YWx1ZSk6CiAgICAjIENoZWNrIGlmIHRoZSB2YWx1ZSBtYXRjaGVzIHRoZSBwYXR0ZXJuOiAiMS4gIiBvciAiMi4gIgogICAgcmV0dXJuIHJlLnNlYXJjaChyIjFcLiB8MlwuICIsIHZhbHVlKSBpcyBub3QgTm9uZQoKCmRlZiBkaXNwbGF5X2ltYWdlX2Nzdl92aWV3ZXIoZmlsZV9wYXRoKToKICAgIHN0LnNldF9wYWdlX2NvbmZpZyhsYXlvdXQ9J3dpZGUnKQoKICAgIGFsbF9maWxlcyA9IHNlYXJjaF9maWxlKGZpbGVfcGF0aCkKICAgIGltYWdlX2ZpbGVzID0gW2ZpbGUgZm9yIGZpbGUgaW4gYWxsX2ZpbGVzIGlmIGZpbGUuZmluZCgndHdpdHRlcl9pbWFnZScpICE9IC0xXQogICAgcGFwZXJfZmlsZXMgPSBbZmlsZSBmb3IgZmlsZSBpbiBhbGxfZmlsZXMgaWYgZmlsZS5lbmRzd2l0aCgnLmNzdicpXQoKICAgIGVuY29kZWRfaW1hZ2VzID0ge30KICAgIGZvciBpLCBpbWFnZV9maWxlIGluIGVudW1lcmF0ZShpbWFnZV9maWxlcyk6CiAgICAgICAgd2l0aCBvcGVuKGltYWdlX2ZpbGUsICJyYiIpIGFzIGY6CiAgICAgICAgICAgIGVuY29kZWRfaW1hZ2UgPSBiYXNlNjQuYjY0ZW5jb2RlKGYucmVhZCgpKS5kZWNvZGUoKQogICAgICAgICAgICBidXR0b25fa2V5ID0gZiJidXR0b257aSArIDF9IgogICAgICAgICAgICBlbmNvZGVkX2ltYWdlc1tidXR0b25fa2V5XSA9IGVuY29kZWRfaW1hZ2UKCiAgICAjIENyZWF0ZSBidXR0b25zIGR5bmFtaWNhbGx5CiAgICBjb2xzID0gc3QuY29sdW1ucyhsZW4oZW5jb2RlZF9pbWFnZXMpKQoKICAgIHNlbGVjdGVkX2J1dHRvbl9rZXkgPSBzdC5zZXNzaW9uX3N0YXRlLmdldCgnc2VsZWN0ZWRfYnV0dG9uX2tleScpCgogICAgZm9yIGksIGJ1dHRvbl9rZXkgaW4gZW51bWVyYXRlKGVuY29kZWRfaW1hZ2VzLmtleXMoKSk6CiAgICAgICAgd2l0aCBjb2xzW2ldOgogICAgICAgICAgICBlbmNvZGVkX2ltYWdlID0gZW5jb2RlZF9pbWFnZXNbYnV0dG9uX2tleV0KICAgICAgICAgICAgYnV0dG9uX3N0eWxlID0gZiIiIgogICAgICAgICAgICA8c3R5bGU+CiAgICAgICAgICAgICN7YnV0dG9uX2tleX0gZGl2LnN0QnV0dG9uID4gYnV0dG9uIHt7CiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiB1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LHtlbmNvZGVkX2ltYWdlfSkgbm8tcmVwZWF0OwogICAgICAgICAgICAgICAgYmFja2dyb3VuZC1zaXplOiBjb3ZlcjsKICAgICAgICAgICAgICAgIGJhY2tncm91bmQtcG9zaXRpb246IGNlbnRlcjsKICAgICAgICAgICAgICAgIGhlaWdodDogMTZlbTsKICAgICAgICAgICAgICAgIHdpZHRoOiAyNGVtOwogICAgICAgICAgICAgICAgYm94LXNoYWRvdzogMTBweCAxMHB4IDVweCBncmV5OwogICAgICAgICAgICAgICAgbWFyZ2luOiAxNXB4OwogICAgICAgICAgICB9fQogICAgICAgICAgICA8L3N0eWxlPgogICAgICAgICAgICAiIiIKICAgICAgICAgICAgc3QubWFya2Rvd24oYnV0dG9uX3N0eWxlLCB1bnNhZmVfYWxsb3dfaHRtbD1UcnVlKQoKICAgICAgICAgICAgaWYgc2VsZWN0ZWRfYnV0dG9uX2tleSA9PSBidXR0b25fa2V5OgogICAgICAgICAgICAgICAgc3QubWFya2Rvd24oZic8ZGl2IGlkPSJ7YnV0dG9uX2tleX0iPicsIHVuc2FmZV9hbGxvd19odG1sPVRydWUpCiAgICAgICAgICAgICAgICBzdC5idXR0b24oJycsIGtleT1idXR0b25fa2V5LCBvbl9jbGljaz1Ob25lKQogICAgICAgICAgICAgICAgc3QubWFya2Rvd24oJzwvZGl2PicsIHVuc2FmZV9hbGxvd19odG1sPVRydWUpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzdC5tYXJrZG93bihmJzxkaXYgaWQ9IntidXR0b25fa2V5fSI+JywgdW5zYWZlX2FsbG93X2h0bWw9VHJ1ZSkKICAgICAgICAgICAgICAgIGlmIHN0LmJ1dHRvbignJywga2V5PWJ1dHRvbl9rZXkpOgogICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkX2J1dHRvbl9rZXkgPSBidXR0b25fa2V5CiAgICAgICAgICAgICAgICBzdC5tYXJrZG93bignPC9kaXY+JywgdW5zYWZlX2FsbG93X2h0bWw9VHJ1ZSkKCiAgICAjIElmIGFueSBidXR0b24gaXMgY2xpY2tlZCwgc2hvdyB0aGUgaW5mb3JtYXRpb24KICAgIGlmIHNlbGVjdGVkX2J1dHRvbl9rZXkgaXMgbm90IE5vbmU6CiAgICAgICAgaW5kZXggPSBpbnQoc2VsZWN0ZWRfYnV0dG9uX2tleS5sc3RyaXAoJ2J1dHRvbicpKSAtIDEKICAgICAgICBjc3ZfZmlsZSA9IHBhcGVyX2ZpbGVzW2luZGV4XQogICAgICAgIGRmID0gcGQucmVhZF9jc3YoY3N2X2ZpbGUsIGVuY29kaW5nPSdnYmsnKQogICAgICAgIGRpY3Rpb25hcnkgPSBkaWN0KHppcChkZlsnVGl0bGUnXSwgZGZbJ0Fuc3dlciddKSkKICAgICAgICBzdC5tYXJrZG93bihmIjxkaXYgc3R5bGU9J2ZvbnQtc2l6ZTozMHB4Oyc+PGI+e2RpY3Rpb25hcnkuZ2V0KCdvZzp0aXRsZScsICcnKX08L2I+PC9kaXY+IiwKICAgICAgICAgICAgICAgICAgICB1bnNhZmVfYWxsb3dfaHRtbD1UcnVlKQogICAgICAgIHN0LnRleHQoIiIpICAjIEFkZCBhbiBlbXB0eSBsaW5lIGFmdGVyIHRoZSB0aXRsZQogICAgICAgIGtleXMgPSBbJ1Jlc2VhcmNoIE9iamVjdGl2ZXMnLCAnTWV0aG9kb2xvZ2ljYWwgQXBwcm9hY2gnLCAnS2V5IEZpbmRpbmdzJ10KCiAgICAgICAgZm9yIHRhZyBpbiBrZXlzOgogICAgICAgICAgICBpZiB0YWcgaW4gZGljdGlvbmFyeToKICAgICAgICAgICAgICAgIGNvbnRlbnQgPSBkaWN0aW9uYXJ5W3RhZ10KICAgICAgICAgICAgICAgIHN0Lm1hcmtkb3duKGYiPGRpdiBzdHlsZT0nZm9udC1zaXplOjI1cHg7Jz48Yj57dGFnfTo8L2I+PC9kaXY+IiwgdW5zYWZlX2FsbG93X2h0bWw9VHJ1ZSkKICAgICAgICAgICAgICAgIHN0LnRleHQoIiIpICAjIEFkZCBhbiBlbXB0eSBsaW5lIGFmdGVyIHRoZSB0aXRsZQogICAgICAgICAgICAgICAgaWYgY2hlY2tfbGlzdF9mb3JtYXQoY29udGVudCk6CiAgICAgICAgICAgICAgICAgICAgZGlzcGxheV9jb250ZW50KGNvbnRlbnQpCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIGRpc3BsYXlfY29udGVudChjb250ZW50KQogICAgICAgICAgICAgICAgc3QudGV4dCgiIikgICMgQWRkIGFuIGVtcHR5IGxpbmUgYWZ0ZXIgdGhlIHRpdGxlCgogICAgIyBTdG9yZSB0aGUgc2VsZWN0ZWQgYnV0dG9uIGtleSBpbiBzZXNzaW9uIHN0YXRlCiAgICBzdC5zZXNzaW9uX3N0YXRlWydzZWxlY3RlZF9idXR0b25fa2V5J10gPSBzZWxlY3RlZF9idXR0b25fa2V5CgoKZmlsZV9wYXRoID0gJy4vJwpkaXNwbGF5X2ltYWdlX2Nzdl92aWV3ZXIoZmlsZV9wYXRoKQo,
1 Like

Thanks @kow

Let me have a look at it :slight_smile:

1 Like

Hi guys, after days of trying, I still canโ€™t successful to use image as button and they are two different errors im getting:

first kind of error:

def button_style(image_data):
    import streamlit as st

    button_config = f"""
                    <style>
                    div.stButton > button {{
                        background: url({image_data}) no-repeat;
                        background-size: cover;
                        background-position: center;
                        border-radius: 50px;
                        height: 120px;
                        width: 200px;
                        padding: 0px 10px; /* Adjust the padding */
                        box-shadow: 3px 3px 5px #222222;
                        text-align: center;
                        font-size: 16px;
                        margin: 4px 2px;
                        white-space: nowrap; 
                        overflow: hidden; 
                        text-overflow: ellipsis; 
                    }}
                    div.stButton > button:hover {{
                        background-color: #666666;
                        color: white;
                        transform: scale(1.05);
                    }}
                    </style>
                """
    st.markdown(button_config, unsafe_allow_html=True)

and i be able to apply the image into the button by:

wc.button_style(image_data)

if st.button('', key=website):
    selected_button_key = website

# Content display code
if website == selected_button_key:
    st.write('kow')

like the button is showing image, and when i click on it, it will show โ€˜kowโ€™, however, all the button showing same image, and it looks like the last one.

second kind of error:

i searched online and ask chatgpt or something and it give me below code:

def button_style(image_data, button_text="Button"):
    import streamlit as st

    button_html = f"""
                <button class="customButton" style="
                    background: url({image_data}) no-repeat;
                    background-size: cover;
                    background-position: center;
                    border-radius: 50px;
                    height: 120px;
                    width: 200px;
                    padding: 0px 10px;
                    box-shadow: 3px 3px 5px #222222;
                    text-align: center;
                    font-size: 16px;
                    margin: 4px 2px;
                    white-space: nowrap; 
                    overflow: hidden; 
                    text-overflow: ellipsis;
                ">{button_text}</button>
                """
    st.markdown(button_html, unsafe_allow_html=True)

this time, all the image button is not the same, but it will not write โ€˜kowโ€™ after i click on it, besides, below each image button, there is a default button could write โ€˜kowโ€™ when i click on it, so im guesssing, the button style didnt applied into st.button

I tried with @Charly_Wargnierโ€™s answer, but its not working, and its similar to my second error.

can anyone guild me how to correct this?

let me know if you need the whole code and data:)

Thanks in advance

Hello, has the problem of multiple buttons displaying the same image been solved?

@peng Nah, I still stuck at this:(

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