Skip to main content

Style and layout for your Streamlit app using SASS

Project description

SAL - Style and Layout for Streamlit

What does it do?

This library lets you style Streamlit components with ease! Here is a quick example of what it can do for you:

// You define SASS style using a predefined placeholder
%sal-button {
  border: 1px dashed antiquewhite
}

// Or you define SASS style using a custom placeholder (*)
%btn-large {
  padding: 12px 18px
  p {
    font-weight:bold
  }
}

(*Read more about custom placeholders)

Run streamlit-sal compile

import streamlit as st
import streamlit_sal as sal
from streamlit_sal import sal_stylesheet

with sal_stylesheet(move_sidebar_right=True):
    # The Streamlit sidebar is now on the right side of the view!

    # This wraps the 'btn-large' and general 'sal-button' styles onto the st.button in the context
    with sal.button('btn-large'):
        large_button = st.button('Big button')

    # It won't affect other usages of st.button
    normal_button = st.button('Streamlit button')

Result:

Result example screenshot

Disclaimer

We cannot guarantee that this library will continue to work for every Streamlit release!

How to install it?

Install with pip install streamlit-sal

From the root of your Streamlit app run: streamlit-sal init

Fill in the config variables for the desired style source and destination path. It will then create a main.scss in the given source path and a .streamlit_sal in the project root path

You can test whether the init was successful by running streamlit-sal compile which should create a CSS file.

How to use it?

(*Make sure to initiate the library first)

Wrap your app code with the stylesheet:

from streamlit_sal import sal_stylesheet

with sal_stylesheet():
    # Your app code goes here!

This will render a streamlit markdown element with a style tag containing the compiled CSS before your code

Add placeholders, compile and render

Navigate to your main.scss and start adding the style placeholders that you need. The available predefined placeholders can be found here. A rule of thumb for placeholders is that every Streamlit component name exists with a sal- prefix and underscores are replaced by dashes (st.download_button -> sal-download-button)

Let's take an example for st.button. We add a new border style for the existing placeholder:

%sal-button {
  border: 1px dashed red
}

Now we run streamlit-sal compile to create the CSS stylesheet sal-stylesheet.css (default name)

The CSS will now apply to all st.button elements that are wrapped with sal.button():

import streamlit as st
import streamlit_sal as sal
from streamlit_sal import sal_stylesheet

with sal_stylesheet():
    # This wraps the default 'sal-button' styles onto the st.button within the context
    with sal.button():
        st.button('Red Border Button')

Add custom classes to SAL components

SAL can easily be extended with additional custom placeholders/classes. Though it is important to register the new placeholders with the correct components.

// Define a custom placeholder (avoid sal- prefix to minimize risk of duplicates)
%btn-large {
  padding: 12px 18px
  p {
    font-weight:bold
  }
}

The above placeholder will not be compiled into the final CSS stylesheet yet. It first needs to be registered to the sal-button. You can find the $custom-classes variable at the bottom of your main.scss:

$custom-classes: (
  sal-button: (btn-large),
)

Multiple placeholders can be added to the same components and even reused between multiple components:

$custom-classes: (
  sal-button: (btn-large, btn-primary),
  sal-download-button: (btn-primary),
)

Normal elements vs container elements

Most elements behave the same, but there are some container-type elements that need special treatment. For these elements you will need to pass down the container to SAL to make it work:

  • with sal.column(..., container=col1): # From col0, col1 = st.columns(2)
  • with sal.popover_content(..., container=container): # From container = st.container()

SAL should warn you when a container element was not used correctly.

Advanced Example: Columns with flex and justify

Result

We define custom placeholders for the column:

%justify-start {
  justify-content: flex-start
}

%justify-center {
  justify-content: center
}

%justify-end {
  justify-content: flex-end
}

%flex-row {
  flex-direction: row

  div {
    // Most streamlit components add width values as inline style. Make it fit the content so justify works.
    width: fit-content !important
  }
}

Now we register the new placeholders with sal-column:

$custom-classes: (
  sal-column: (justify-start, justify-center, justify-end, flex-row),
)

After streamlit-sal compile the styles are prepared, we can move on with the app code. Note that we here use the col elements and pass them as containers for the sal.column call. To apply the same column style for any child elements you will need to extend on the col containers (col0, col1, col2)

import streamlit as st
import streamlit_sal as sal
from streamlit_sal import sal_stylesheet

with sal_stylesheet():
    col0, col1, col2 = st.columns(3)
    with sal.column('justify-start', 'flex-row', container=col0):
        col0.button("Left")
    with sal.column('justify-center', 'flex-row', container=col1):
        col1.button("Center")
    with sal.column('justify-end', 'flex-row', container=col2):
        col2.button("Right")

How does it work?

Streamlit does not give users the possibility to add CSS ids or classes. However by adding a span markdown element we can get the same effect:

import streamlit as st

st.markdown(f"<span class='sal-button'></span>", unsafe_allow_html=True)
st.button("Hello world!")

Using :has(.. span.sal-button) and a sibling selector (+) we can now target that exact st.button:

div:has(> div.stMarkdown > div[data-testid="stMarkdownContainer"] span.sal-button) + div button {
    /*Add custom styles*/
}

Building the selectors so you don't have to

SAL uses SASS to dynamically build all the required selectors using a component structure map and an @each loop. The output CSS will be selectors just like the one seen above. All the defined SASS % placeholders are optional and will not be part of the compiled when not set.

Any new custom classes that are registered properly will also be looped over during streamlit-sal compile.

Troubleshooting

No styling seems to apply

  • Make sure you have wrapped your app code using with sal_stylesheet():
  • Check that all placeholders in main.scss are defined correctly (% not $) and brackets are closed.
  • Make sure you have run streamlit-sal compile

The element I try to style has moved outside its container

  • It might be a container element, pass it into sal using the container= arg Read more

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

streamlit_sal-0.2.0.tar.gz (28.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

streamlit_sal-0.2.0-py3-none-any.whl (28.4 kB view details)

Uploaded Python 3

File details

Details for the file streamlit_sal-0.2.0.tar.gz.

File metadata

  • Download URL: streamlit_sal-0.2.0.tar.gz
  • Upload date:
  • Size: 28.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.9.5 Linux/5.15.0-79-generic

File hashes

Hashes for streamlit_sal-0.2.0.tar.gz
Algorithm Hash digest
SHA256 eaecfd848841f90d9c2ea67141233a08e01056759c36f69ec552d04a966aeb2f
MD5 1b9c292852e0bd622057cc0bc4de4c3f
BLAKE2b-256 2fc26651a959a33ec35ed25548ef4d02a7d155dcffb2e6d4afdcf21a8d6569aa

See more details on using hashes here.

File details

Details for the file streamlit_sal-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: streamlit_sal-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 28.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.9.5 Linux/5.15.0-79-generic

File hashes

Hashes for streamlit_sal-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f3d68253b57263fe0f72d69dd574477f102696a715558f9d6dc98af4c40e38a
MD5 7cdf451e8ff07aa25187bbb7e0e54aef
BLAKE2b-256 4b1e75d0bcdb49cfecb26d064d682836a34356c6f7d8434a989e99943c2c2b02

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page