CSS hacks for the dumb?

Hello,

I need a tutorial about CSS hacking for Streamlit.

Could you help?

Thanks,
Michel


I would like to customize the appearance of a ST app.
It is mainly about reducing space between rows of widgets.
No idea where to start.
I know almost nothing about CSS, styles and how to use them with ST.
For me this is almost as clear as Chinese:

styl = f"""
<style>
	.reportview-container .main .block-container{{
		{max_width_str}
		padding-top: {padding_top}rem;
		padding-right: {padding_right}rem;
		padding-left: {padding_left}rem;
		padding-bottom: {padding_bottom}rem;
	}}
	}}
</style>
"""
1 Like

You may you my code over here, it has CSS hacking on different items, not only colors.

TLDR;
You can just inject an external CSS file (you can find it in my example).

1 Like

CSS hacking tut

  • Your most important tool in this will be the Web Inspector. It’s usually F12 on Windows (I don’t know on Mac) otherwise you should find it inside the settings of your web browser (for Firefox it will be More tools > Web Developer tools). You should then see the HTML page of your Streamlit app.

Let’s suppose you want to edit the slider color with the CSS hack. Then you’ll need to find a way to select this slider using CSS Selection. You can try and use the inspector to hover the slider and find it’s corresponding HTML block.

See this HTML block selected corresponds to the container containing the slider? It has CSS classes associated, here it’s stSlider. So in your CSS file related to the CSS hack with Markdown, when you write

.stSlider {
    background-color: blue;
}

it will change the background color for any HTML block which has a stSlider CSS class (that’s the meaning of .stSlider).

You can also test your CSS selection live by editing the CSS attributes in the element part of the CSS rules in the bottom pane. Let’s add background-color:blue for example (this will be temporary, if you reload the page the edit is lost, which is why we use the Streamlit Markdown CSS hack to preserve those edits):

See that the background-color is applied to the whole container, not only the slider. If you want to change the color of the slider only, we need to take the div inside the HTML block, should be something like .stSlider > div > div for example.

There, with CSS Selection + web inspector you are all equipped to select the exact HTML elements you need. Try to look for example in the HTML where the .reportview-container .main .block-container HTML element is located, and try to edit the padding attributes in the element block like we did before to understand what is happening.

  • A tutorial about CSS Selection I like is https://flukeout.github.io/ . Master this first before considering trying to select subset of widgets inside rows.

About your problem

I did not test but the .stHorizontalBlock selector should help :wink: . I’ll let you try for yourself, good luck, CSS hacking is not an easy task, especially because you’re at risk of the Streamlit dev team changing every CSS class name between 2 versions.

Cheers,
Fanilo

1 Like

Thanks a lot andfanilo !

Concerning these “CSS class names” is there some list or doc available?
Maybe in some of the source files ?

Thanks

Michel

sorry frontend engineers / web scrapers, I’ll be doing some shortcuts in this explanation :slight_smile:

Unfortunately there’s no list of “CSS class name to corresponding Streamlit widget”, since CSS classes are generally there to apply a set of design rules instead of being responsible for mapping to a unique widget like an ID. For example if I want to turn a button to red I’d only add the .red class to my HTML element and then have .red {color: red;} in my CSS file, rather than adding color:red in a direct .button {color: red;} class.

Going further into this, most direct CSS class names to widgets are autogenerated by a special CSS library called emotion when Streamlit is built for release, you’ll notice them pretty quickly they resemble st-cp or css-glyadz etr89 …so you can’t really maintain a map of randomly generated CSS names to widgets that would change for every Streamlit version.

So for CSS hacking, the most robust way to do widget selection is to look for the widget container, which generally has a very stable name like stSlider or stBlock, and then dig into the div hierarchy for the element you want. Basically you get things like div[data-baseweb="select"] > div or from @BugzTheBunny 's css file .stTextInput>div>div>div

If you are courageous then yes you’ll find the names inside the source files, but honestly you’ll be much faster by using the web inspector to “guess” the correct CSS class name.

1 Like

Thanks again andfanilo !

Below is a screen capture where I expanded up to one of the stTextInput on my grid.
Which class should I target to reduce the overall height of all these widgets?
And how should I proceed?
I guess it should be close to the code I found to change the width of the ST page.
I reproduce it below, maybe it is very similar !

Thanks

Michel

def _set_block_container_style(
    max_width: int = 1200,
    max_width_100_percent: bool = False,
    padding_top: int = 1,
    padding_right: int = 1,
    padding_left: int = 1,
    padding_bottom: int = 1,
    ):
    if max_width_100_percent:
        max_width_str = f"max-width: 100%;"
    else:
        max_width_str = f"max-width: {max_width}px;"
        
    styl = f"""
    <style>
        .reportview-container .main .block-container{{
            {max_width_str}
            padding-top: {padding_top}rem;
            padding-right: {padding_right}rem;
            padding-left: {padding_left}rem;
            padding-bottom: {padding_bottom}rem;
        }}
        }}
    </style>
    """
    st.markdown(styl, unsafe_allow_html=True)

Randomly not tested, and it may also totally depend on the layout of your app, div[data-testid="stBlock"] stTextInput > div[data-baseweb="input"] will select all stTextInput in stBlock, then select any input children in those elements.

    styl = f"""
    <style>
        div[data-testid="stBlock"] stTextInput > div[data-baseweb="input"] {height: 80px;}
    </style>
"""

Yeah you’ll definitely need to learn CSS Selection with the CSS Diner tutorial now, because those selections can be pretty specific to your app. Also note that changing the height of an element will NOT redimension the height of elements inside, so you run the risk of cropping some elements if you don’t keep it at automatic height.

1 Like