Module 3 — Mise en page : colonnes, onglets, barre latérale
Une application se contente d'un ordre vertical au premier module. Au second, elle demande déjà deux colonnes pour caser le formulaire. Dès qu'on ajoute un tableau, un graphique et une aide en ligne, la page devient illisible sans structure explicite. Ce module rassemble les outils de mise en page de Streamlit et propose une charpente stable pour tout le reste du cours : un formulaire à gauche, un tableau au centre, des filtres dans la barre latérale, et des onglets pour séparer les vues.
Les cinq conteneurs de Streamlit
Streamlit organise l'espace avec cinq primitives, toutes utilisables en tant que gestionnaires de contexte avec with, ce qui rend l'imbrication lisible.
Les colonnes. st.columns(n) renvoie une liste de conteneurs disposés côte à côte. Un argument entier crée n colonnes égales ; une liste de poids donne des proportions. st.columns([2, 1]) produit deux colonnes dont la première fait le double de la seconde. Chaque colonne se remplit ensuite comme une page ordinaire.
Les onglets. st.tabs([...]) prend une liste d'étiquettes et renvoie autant de conteneurs. C'est la manière idiomatique de séparer des vues indépendantes qui partagent la même page — une vue « Individuel », une vue « Lot », une vue « Suivi », par exemple.
Les expandeurs. st.expander("Titre") produit un panneau replié par défaut. On y range les paramètres avancés, l'aide, un journal détaillé, tout ce qui pollue la page principale sans être utile en permanence.
Les conteneurs. st.container() crée simplement une zone qu'on peut remplir plus tard dans le script, ce qui contourne la contrainte d'ordre linéaire imposée par le modèle d'exécution. On appellera zone.write(...) depuis n'importe quel endroit ultérieur, et le contenu apparaîtra à la place réservée.
La barre latérale. st.sidebar est un conteneur particulier, présent en permanence à gauche (à droite dans une interface arabe), destiné aux filtres et aux paramètres globaux. On y accède via l'attribut, st.sidebar.selectbox(...), ou en gestionnaire de contexte, with st.sidebar:.
La charpente du tableau de bord
Voici la mise en page qui accompagne le reste du cours. La barre latérale porte les filtres, une rangée d'indicateurs occupe le haut, et trois onglets séparent le scoring individuel, le scoring en lot et le suivi hebdomadaire.
import streamlit as st
import pandas as pd
st.set_page_config(page_title="Résiliation", layout="wide")
# --- Filtres dans la barre latérale, communs à toute l'application. ---
with st.sidebar:
st.header("Filtres")
contrat = st.multiselect(
"Type de contrat",
options=["Mensuel", "Annuel", "Deux ans"],
default=["Mensuel", "Annuel", "Deux ans"],
)
anciennete_max = st.slider("Ancienneté maximale (mois)", 0, 120, 60)
seuil_risque = st.slider("Seuil de risque", 0.0, 1.0, 0.4, step=0.05)
# --- Rangée d'indicateurs en haut. ---
clients = pd.read_csv("donnees/clients.csv")
filtres = clients[
clients["type_contrat"].isin(contrat)
& (clients["anciennete_mois"] <= anciennete_max)
]
c1, c2, c3, c4 = st.columns(4)
c1.metric("Clients suivis", len(filtres))
c2.metric("Ancienneté moyenne", f"{filtres['anciennete_mois'].mean():.1f} mois")
c3.metric("Mensualité moyenne", f"{filtres['mensualite'].mean():.2f} EUR")
c4.metric("Part de contrats mensuels", f"{(filtres['type_contrat'] == 'Mensuel').mean():.0%}")
st.divider()
# --- Trois onglets pour les trois grandes vues de l'application. ---
onglet_indiv, onglet_lot, onglet_suivi = st.tabs(
["Scoring individuel", "Scoring en lot", "Suivi hebdomadaire"]
)
with onglet_indiv:
st.subheader("Scorer un client")
st.info("La saisie détaillée arrive au module 2 ; ici l'onglet est réservé.")
with onglet_lot:
st.subheader("Scorer un fichier de clients")
st.info("Le téléversement arrive au module 7.")
with onglet_suivi:
st.subheader("Évolution du nombre de clients à risque")
st.info("Les graphiques arrivent au module 4.")
with st.expander("Détails techniques et paramètres avancés"):
st.write(f"Fichier chargé : {len(clients)} lignes, {clients.shape[1]} colonnes.")
st.write("Seuil de risque appliqué :", seuil_risque)
Pourquoi la barre latérale change tout
Les filtres se placent dans la barre latérale pour deux raisons qui vont ensemble. Ergonomique d'abord : le corps de la page reste dédié aux résultats, ce qui améliore la densité d'information utile. Fonctionnelle ensuite : la barre latérale est visible depuis toutes les vues, donc un filtre appliqué là influence chaque onglet sans avoir à être dupliqué. C'est le contraire d'un filtre placé au sein d'un onglet, qui n'affecterait que celui-là.
Une conséquence pratique du modèle d'exécution s'invite ici. Quand l'utilisateur modifie un curseur dans la barre latérale, le script est intégralement relancé, y compris les onglets qui ne sont pas visibles. Streamlit rend intelligemment les onglets — seul l'onglet visible est affiché — mais le code Python de chaque onglet est bien exécuté. Les onglets ne sont donc pas des économies de calcul : ils sont une manière d'organiser la vue, pas une manière de ne pas calculer. Cette nuance importe pour tout onglet qui appelle un modèle ou une base ; le module 5 sur le cache y remédie.
Le sens de lecture, pour préparer la version arabe
Le fil rouge du cours existe aussi dans une version arabe. Streamlit gère le sens de lecture au niveau du navigateur, à travers un attribut de langue de la page. La consigne pratique est simple : ne jamais coder « à gauche » ou « à droite » en dur dans les libellés. On dit « la première colonne » et « la seconde colonne », jamais « la colonne de gauche » et « la colonne de droite », parce que dans une interface de droite à gauche, la première est à droite. La commande st.columns([2, 1]) donne toujours la première colonne à la position principale du sens de lecture, quelle que soit la langue.
Petit inventaire des habitudes utiles
| Besoin | Conteneur idiomatique |
|---|---|
| Deux blocs de même importance côte à côte | st.columns(2) |
| Un bloc principal et une aide compacte | st.columns([3, 1]) |
| Vues indépendantes qui partagent la page | st.tabs([...]) |
| Aide, paramètres, journaux détaillés | st.expander("...") |
| Filtres globaux et navigation | st.sidebar |
| Zone à remplir dans le désordre | st.container() |
Décidez de la charpente avant de coder les composants qu'elle contient. Une charpente stable — mêmes onglets, même barre latérale — devient un repère pour l'utilisateur, qui trouve rapidement où poser son geste. À l'inverse, une charpente qui évolue à chaque itération demande un réapprentissage à chaque déploiement. Traitez la mise en page comme un contrat visuel : rare à changer, et jamais sans raison.
En résumé
- Cinq conteneurs suffisent : colonnes, onglets, expandeurs, conteneurs libres et barre latérale ; tous utilisables avec
withpour une imbrication lisible. - La barre latérale accueille les filtres globaux ; sa persistance entre onglets évite la duplication des contrôles.
- Les onglets ordonnent la vue mais ne réduisent pas le calcul : le code de chaque onglet est exécuté même lorsque l'onglet est caché.
- Les libellés parlent en « première » et « seconde » colonne plutôt qu'en « gauche » et « droite », pour rester justes dans les langues qui se lisent de droite à gauche.
Module suivant : les graphiques et les tableaux, pour que les indicateurs deviennent des courbes et des matrices lisibles.