How to change the backgorund color of button widget

Hi @Marisa_Smith

Is it possible to set the color options in the app.py file?

You mentioned:
primary_clr = st.get_option(“theme.primaryColor”)

Is this a way to retrieve the settings from the config.toml file or is it possible to do it without the config.toml file?

I entered the code in my app however, your example doesn’t explain how to change the color using st.get_option without changing the config.toml file.

One other question; is there a way to change the color of st.success? It doesn’t work with my colors.

Thanks!

Hey @chefnewman,

No, it’s not possible to set the colours from the app.py file, just access them with the st.get_option function. To change the colour you can directly try out colour options in the config.toml file or you can use the more convenient (in my opinion) UI from the hamburger menu to dynamically try different colour options until you find one you like!

You can use the UI by going to the hamburger menu in the top right corner → settings and then clicking the edit active theme button!

Happy Streamlit-ing
Marisa

Thanks for confirming, that’s what I thought.

1 Like

you can change the button background color and text color like this:

import streamlit as st
m = st.markdown("""
<style>
div.stButton > button:first-child {
    background-color: #0099ff;
    color:#ffffff;
}
div.stButton > button:hover {
    background-color: #00ff00;
    color:#ff0000;
    }
</style>""", unsafe_allow_html=True)

b = st.button("点我开始运行程序")

before click:
image
hover effect:
image

5 Likes

BeyondMyself’s answer helps me much, but I elaborated it to make INDIVIDUAL buttons coloured differently.

    st.markdown("""<style>
    
    div:nth-child(7) > [class^="css-"] > div:nth-child(1) > div > div > div > button {
        background-color: #DD3300;
        color:#eeffee;
        border-radius: 0.75rem;
        }

    div[id^="bui-"] > button:nth-child(1) {
    background-color: #33DD00;
    color: #EEFFFF;
    }
    </style>""", unsafe_allow_html=True)

image

the most challenging part is to identify the individual CSS selectors of buttons.
You may get them by “Inspect” and then copy “CSS selector” with a browser’s developer mode. You will get something like:
.css-1qipfyj > div:nth-child(1) > button:nth-child(1)
this part 1qipfyj is random session to session, so you will need to use regex to replace this part with a match formula.
Also worth using the parent of the class as an additional separation tool.
Then, it will work reliably.

Worked without hussles, thanks :+1:t5:

Just an observation and not a criticism of the solution because I use it here in my tests too!

One of the things I mentioned in another post is that this is not very cool to do, because if Streamlit decides to refactor your classes by renaming them, what will happen is a general crash in the users’ apps.

That’s why I think that Streamlit should always allow this to be done by a proprietary function, because that’s the only way it will guarantee a good operation.

Here’s the tip!

Yes, you absolutely right. Even when new elements appear on the screen, the injected selector will stop working (as the path changes or the classes’ sequence is shifted).
So the better way would be adding a streamlit widget key as “a class” to element classes — in such case, using individual style becomes possible.
———
I would suggest adding a style property to the element arguments:

st.button(label="My button", style="background-color: #DD3300; color:#eeffee; border-radius: 0.75rem;")

And the streamlit would append it to something like custom.css

2 Likes

I agree, it’s an alternative that I think is valid.

Maybe Streamlit could use a NAME or ID field for all elements, giving a little more flexibility, being able to use a type method:

st.css( name, my_custom_css )

so that you can set the css at any time through some conditional

2 Likes

Hello!! Needing help in generating the regex!!

do you have an example of the full path to your button?

Hello! I would like to set height to my button.

st.markdown(“””<style> div.stButton> button:first-child {height : 1em} </style>”””, unsafe_allow_html = True)
st.button(“play”)

However, using the code above applies to all my button in the web page.

If I do a inspect on the web page this is what I see

<div class = “row-widget stButton” style = “width:112px”>
<button kind = “primary” class = “css-bzyszk e1tzin5v2”> Play </button>
</div>

Sorry for the delayed reply.

Your parent element (div) has no distinct attributes to catch it, then follow the child (button).
So, try the following to find the button class in your DOM:

button[class^="css-bzy"]  {
    background-color: #33DD00;
    color: #EEFFFF;
    }

I am unsure if “e1tzin5v2” is always assigned to that button, so I suggest using the first class in the list.
Tell me if it has worked in your case.

how to change different buttons with different colors I tried with the same solution but its not working for me, when I inspect all the buttons are having same class name and when I am using that class name all buttons are changing into same color.

button kind=“secondary” class=“css-1x8cf1d edgvbvh10”>
data-testid=“stMarkdownContainer”
class=“css-1offfwp e16nr0p34”>
This is how my class looks like

can someone help me
Thank you

Hi @Aravind_Kumar, you can do something like this:

import streamlit as st
import streamlit.components.v1 as components

def ChangeButtonColour(wgt_txt, wch_hex_colour = '12px'):
    htmlstr = """<script>var elements = window.parent.document.querySelectorAll('*'), i;
                for (i = 0; i < elements.length; ++i) 
                    { if (elements[i].innerText == |wgt_txt|) 
                        { elements[i].style.color ='""" + wch_hex_colour + """'; } }</script>  """

    htmlstr = htmlstr.replace('|wgt_txt|', "'" + wgt_txt + "'")
    components.html(f"{htmlstr}", height=0, width=0)

cols = st.columns(4)
cols[0].button('no colour', key='b1')
cols[1].button('green', key='b2')
cols[2].button('red', key='b3')
cols[3].button('no colour', key='b4')

ChangeButtonColour('green', '#4E9F3D') # button txt to find, colour to assign
ChangeButtonColour('red', '#FF0000') # button txt to find, colour to assign

Find the parameter you want the change and do it in the html.

Cheers

Hi Shawn,

Thanks for your code. Do you know how could I change this piece of code so I can change the button’s color based on the key value?

Thanks.

Hi @Jenny , you can do something like this:

btnfontcolor = '#000000'    # default colour black 
if btntxt= "Submit":
   btnfontcolor = '#4E9F3D'   # green
elif if btntxt= "Add":
   btnfontcolor = '#FF0000'   # red
# add as many conditions as you need

ChangeButtonColour(btntxt, btnfontcolor)  # call the function as per the code mentioned earlier

Cheers

Hi @Shawn_Pereira , thanks for the reply, however I don’t think this will work. For example,

cols = st.columns(4)
cols[0].button('has color', key='b1')
cols[1].button('has color', key='b2')
cols[2].button('has color', key='b3')
cols[3].button('has color', key='b4')

How could I change the button color based on the key=‘b4’ value? All my buttons have the inner text but different keys.

Thanks.

Hi @Jenny.

Sorry, I misread your query, hence the code…

I don’t know of any way that you can change colours based on the key, because

  1. streamlit can target widgets via keys but it has lacking / straight-forward cosmetic options for widgets
  2. the key is not exposed to JS (when you inspect) the page, so you cant lock on that specific widget for further processing.
  3. Further, the class attached to the button may not be static across streamlit versions.

Do you want to change the button colour after the button is clicked? OR
Do you want it to change automatically basis the key when the application is run?

Will check on a solution later today…

Cheers

Hi Shawn,

No worries at all. If it could be, I would like it be changed automatically when the code is running. I heard that by using the div>div path maybe I could locate that specific button, but I don’t actually know how to look at the div path…