StreamlitのスタイリングTips

## はじめに
Streamlitは手軽にWebアプリケーションを作れる代わりにスタイリングの幅は非常に狭くなっています。
標準の機能で設定する方法と、直接CSSを適用する方法についてまとめてみようと思います。


## 標準のスタイリング
## config.toml
ライトモードとダークモード、背景色(メイン画面とサイドバー)やページ全体のテーマカラー(ボタン等に反映される)、文字色、フォントを設定できます。
まず、.streamlitフォルダを作成してconfig.tomlを配置します。
https://docs.streamlit.io/library/advanced-features/configuration

```  toml:config.toml
[theme]

# The preset Streamlit theme that your custom theme inherits from.
# One of "light" or "dark".
# base =

# Primary accent color for interactive elements.
# primaryColor =

# Background color for the main content area.
# backgroundColor =

# Background color used for the sidebar and most interactive widgets.
# secondaryBackgroundColor =

# Color used for almost all text.
# textColor =

# Font family for all text in the app, except code blocks. One of "sans serif",
# "serif", or "monospace".
# font =

```

※私は以下の設定にすることが多いです。
``` toml:config.toml
[theme]
base="light"
primaryColor="#004a55"
backgroundColor="#fafafa"
textColor="#222"
font="sans serif"

```

## st.set_page_config
ブラウザのタブに表示されるページのタイトルやページアイコン(ファビコン)、画面の表示領域の幅、ページ読み込み時点でのサイドバーの開閉を設定できます。

``` python
import streamlit as st

st.set_page_config(
    page_title="Ex-stream-ly Cool App",
    page_icon="🧊",
    layout="wide",
    initial_sidebar_state="expanded",
    menu_items={
        'Get Help': 'https://www.extremelycoolapp.com/help',
        'Report a bug': "https://www.extremelycoolapp.com/bug",
        'About': "# This is a header. This is an *extremely* cool app!"
    }
)
```


https://docs.streamlit.io/library/api-reference/utilities/st.set_page_config

ページアイコンは画像を利用することもできます。

``` python
from PIL import Image
import streamlit as st

im = Image.open("favicon.ico")
st.set_page_config(
    page_title="Hello",
    page_icon=im,
    layout="wide",
)
```


https://discuss.streamlit.io/t/fav-icon-title-customization/10662/10


## 標準でないスタイリング
### 画面いっぱいスペースを利用する
標準状態だと、画面右上にローディングのアニメーションや、ハンバーガーメニューが表示されるため画面上部にスペースが生じます。
以下の設定を行うことで、Streamlit独自の表示を消すことができます。(Streamlit Community Cloudで公開した時に表示される右下のアイコンメニューは消せないようです)

※赤枠部分が消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/8b79facb-fd7b-6ca4-f261-d5eb3167ae13.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/1128f82b-346e-4ba9-8ed3-34472c711860.png)



``` python
HIDE_ST_STYLE = """
                <style>
                div[data-testid="stToolbar"] {
                visibility: hidden;
                height: 0%;
                position: fixed;
                }
                div[data-testid="stDecoration"] {
                visibility: hidden;
                height: 0%;
                position: fixed;
                }
                #MainMenu {
                visibility: hidden;
                height: 0%;
                }
                header {
                visibility: hidden;
                height: 0%;
                }
                footer {
                visibility: hidden;
                height: 0%;
                }
				        .appview-container .main .block-container{
                            padding-top: 1rem;
                            padding-right: 3rem;
                            padding-left: 3rem;
                            padding-bottom: 1rem;
                        }  
                        .reportview-container {
                            padding-top: 0rem;
                            padding-right: 3rem;
                            padding-left: 3rem;
                            padding-bottom: 0rem;
                        }
                        header[data-testid="stHeader"] {
                            z-index: -1;
                        }
                        div[data-testid="stToolbar"] {
                        z-index: 100;
                        }
                        div[data-testid="stDecoration"] {
                        z-index: 100;
                        }
                </style>
"""

st.markdown(const.HIDE_ST_STYLE, unsafe_allow_html=True)
```
> hydralitというライブラリでの設定を参考にしています。
https://github.com/TangleSpace/hydralit

## 個人的なテンプレート
↓の感じの状態からスタートできます。（DB操作の部分は例で、あくまでスタイルの部分の参考用です。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649608/ad343b42-96b4-418a-32cc-c8e9780a6604.png)


``` toml:config.toml
[theme]
base="light"
primaryColor="#004a55"
backgroundColor="#fafafa"
textColor="#222"
font="sans serif"

```

``` python:const.py
SET_PAGE_CONFIG = {
    "page_title": "Streamlit Base",
    "page_icon": "😀",
    "layout": "wide",
    "initial_sidebar_state": "collapsed",
}


OPTION_MENU_CONFIG = {
    "menu_title": "Streamlit Base",
    "options": ["About", "DataBase", "Other"],
    "icons": ["bi-chat-dots", "bi-cloud-arrow-up", "bi-book"],
    "menu_icon": "bi-search",
    "default_index": 0,
    "orientation": "horizontal",
    "styles": {
        "container": {
            "margin": "0!important",
            "padding": "0!important",
            "background-color": "#fafafa",
        },
        "icon": {"color": "fafafa", "font-size": "25px"},
        "nav-link": {
            "font-size": "20px",
            "margin": "0px",
            "--hover-color": "#eee",
        },
        "nav-link-selected": {"background-color": "004a55"},
    },
}

HIDE_ST_STYLE = """
                <style>
                div[data-testid="stToolbar"] {
                visibility: hidden;
                height: 0%;
                position: fixed;
                }
                div[data-testid="stDecoration"] {
                visibility: hidden;
                height: 0%;
                position: fixed;
                }
                #MainMenu {
                visibility: hidden;
                height: 0%;
                }
                header {
                visibility: hidden;
                height: 0%;
                }
                footer {
                visibility: hidden;
                height: 0%;
                }
				        .appview-container .main .block-container{
                            padding-top: 1rem;
                            padding-right: 3rem;
                            padding-left: 3rem;
                            padding-bottom: 1rem;
                        }  
                        .reportview-container {
                            padding-top: 0rem;
                            padding-right: 3rem;
                            padding-left: 3rem;
                            padding-bottom: 0rem;
                        }
                        header[data-testid="stHeader"] {
                            z-index: -1;
                        }
                        div[data-testid="stToolbar"] {
                        z-index: 100;
                        }
                        div[data-testid="stDecoration"] {
                        z-index: 100;
                        }
                </style>
"""

```

``` python:app.py
import const
import streamlit as st
from streamlit_option_menu import option_menu

st.set_page_config(**const.SET_PAGE_CONFIG)
st.markdown(const.HIDE_ST_STYLE, unsafe_allow_html=True)
selected = option_menu(**const.OPTION_MENU_CONFIG)
    
```


## おわりに
以前ご紹介したロードマップでもスタイリングの自由度を上げるような内容がありますので、ページ全体や各コンポーネント事にCSSを指定できるようになるといいなと思っています。

https://qiita.com/papasim824/items/d6aea8d5e1c0e47e3286
    

※Figma to Streamlit なるものもあるようですね。

https://www.figma.com/community/plugin/1167469184805790690/figma-to-streamlit