Mises en page Shiny : fluidPage, sidebarLayout et la grille à 12 colonnes
Agencez vos entrées et vos sorties sur la page — l’enveloppe de page, la division en panneau latéral, la grille, les onglets et la navigation multi-pages.
Tous les conteneurs de mise en page Shiny au même endroit : fluidPage et titlePanel, sidebarLayout avec sidebarPanel et mainPanel, la grille fluidRow/column à 12 colonnes, tabsetPanel et navlistPanel, navbarPage pour les applications multi-pages, et wellPanel. Pour chacun, le code, ce qu’il agence, et quand y recourir — plus comment les largeurs de colonnes totalisent 12 et comment imbriquer les mises en page.
- Chaque application commence par une fonction de page : enveloppez tout le
uidansfluidPage()(responsive, le défaut) et donnez-lui untitlePanel(). sidebarLayout()est la division classique : les contrôles danssidebarPanel()à gauche, les résultats dansmainPanel()à droite — la mise en page qu’utilisent la plupart des applications de données.- La grille, c’est
fluidRow()+column(), et les largeurs totalisent 12. Une ligne fait 12 unités de large ;column(4, …)+column(8, …)la remplit. Utilisezoffset =pour pousser une colonne vers la droite. tabsetPanel()+tabPanel()créent des onglets ;navbarPage()crée une application multi-pages avec une barre de navigation en haut — recourez aux onglets pour grouper des vues, à une barre de navigation pour séparer des sections entières.wellPanel()est un encadré gris qui groupe visuellement des contrôles. Les conteneurs de mise en page s’imbriquent librement — des colonnes dans des lignes, des onglets dans unmainPanel, unwellPaneldans une colonne.
Introduction
Les entrées collectent des choix et les sorties affichent des résultats — les mises en page décident où ils se placent sur la page. Un conteneur de mise en page est une fonction dans laquelle vous enveloppez vos widgets et vos affichages ; il les agence en lignes, colonnes, panneaux latéraux ou onglets. Réussissez la mise en page et une application se lit d’elle-même ; ratez-la et une application puissante paraît à l’étroit ou chaotique.
C’est la référence à laquelle vous revenez. Chaque conteneur de mise en page que vous utiliserez est ici, groupé par la tâche qu’il accomplit, et pour chacun vous obtenez trois choses : le code, ce qu’il agence, et quand l’utiliser. Vous savez déjà déclarer les entrées et les sorties ; ici vous apprenez à les placer — de l’enveloppe de page jusqu’à une grille à 12 colonnes.
Le code de cette page n’est pas exécuté ici — une application Shiny a besoin d’une session R active, elle ne peut donc pas tourner dans une page web statique. Copiez n’importe quel bloc dans un fichier app.R et exécutez-le en local avec shiny::runApp() (ou cliquez sur Run App dans RStudio). Chaque exemple montre une mise en page isolée ; remplissez-la avec vos propres entrées et sorties.
Le conteneur de page
Le ui de chaque application est enveloppé dans une unique fonction de page — le conteneur le plus externe. fluidPage() est celle que vous utiliserez presque toujours : elle construit une page responsive qui s’adapte à la largeur du navigateur et se réorganise sur les petits écrans. Tout le reste se place à l’intérieur.
titlePanel() place un titre en haut de la page (et définit le titre de l’onglet du navigateur). C’est la première chose conventionnelle à mettre à l’intérieur de fluidPage().
library(shiny)
ui <- fluidPage(
titlePanel("My App"),
# ...all your layout, inputs, and outputs go here...
)Tout dans cette leçon vit à l’intérieur d’une fonction de page. Une règle : une fonction de page enveloppe tout le ui une seule fois — vous n’imbriquez pas un fluidPage() dans un autre fluidPage() (voir Problèmes fréquents).
La mise en page à panneau latéral
sidebarLayout() est l’agencement le plus courant pour une application de données : un sidebarPanel() étroit de contrôles à gauche, un large mainPanel() de résultats à droite. Il renvoie une mise en page complète en deux parties, vous la déposez donc directement dans fluidPage(). Utilisez-la chaque fois que l’utilisateur règle des options qui pilotent un unique affichage principal — la forme par défaut de presque toute application d’analyse.
ui <- fluidPage(
titlePanel("Histogram explorer"),
sidebarLayout(
sidebarPanel(
sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)
),
mainPanel(
plotOutput("hist")
)
)
)Par défaut le panneau latéral prend 4 des 12 unités de la grille et le panneau principal en prend 8. Changez la répartition avec l’argument width sur chaque panneau — sidebarPanel(width = 3, …) et mainPanel(width = 9, …) pour un panneau latéral plus étroit. Placez le panneau latéral à droite avec sidebarLayout(…, position = "right").
La grille à 12 colonnes
Quand vous avez besoin de plus qu’une division panneau-latéral-et-principal, construisez votre propre agencement avec la grille. Une page fait 12 unités de large. fluidRow() crée une ligne horizontale ; column(width, …) en découpe une partie — et les largeurs d’une ligne devraient totaliser 12. C’est le fondement sur lequel toute autre mise en page est bâtie.
column(6, …) + column(6, …) crée deux moitiés égales ; column(4, …) + column(8, …) crée une division un tiers / deux tiers. Utilisez la grille quand vous voulez un agencement sur mesure — plusieurs panneaux côte à côte, un bandeau d’en-tête au-dessus d’un corps à deux colonnes, une galerie de cellules égales.
ui <- fluidPage(
fluidRow(
column(6, h3("Left half"), plotOutput("a")),
column(6, h3("Right half"), plotOutput("b"))
)
)offset = pousse une colonne vers la droite du nombre d’unités indiqué — pratique pour centrer. column(6, offset = 3, …) place une colonne demi-largeur au milieu (3 unités vides de chaque côté).
ui <- fluidPage(
fluidRow(
column(6, offset = 3, h3("Centred content"))
)
)Sur un écran étroit les colonnes s’empilent verticalement d’elles-mêmes — la grille est responsive, vous n’écrivez donc rien de plus pour le mobile.
Les mises en page s’imbriquent : une column() peut contenir sa propre fluidRow(), et une ligne peut contenir des colonnes qui contiennent chacune d’autres lignes. Gardez l’imbrication peu profonde, cependant — une grille profondément imbriquée est difficile à lire et à maintenir.
ui <- fluidPage(
fluidRow(
column(12, h2("Header")) # full-width band
),
fluidRow(
column(3, h4("Controls")), # narrow sidebar...
column(9, plotOutput("plot")) # ...wide content (3 + 9 = 12)
)
)Onglets
tabsetPanel() regroupe plusieurs vues en onglets, chaque vue dans un tabPanel(). Un seul onglet s’affiche à la fois, c’est donc la façon de faire tenir un graphique, un résumé et un tableau de données dans le même espace sans faire défiler par-delà les trois. Donnez un id à tabsetPanel() si le server a besoin de savoir quel onglet est ouvert.
tabsetPanel(
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)Les onglets sont couramment placés à l’intérieur d’un mainPanel() — les contrôles restent en place dans le panneau latéral pendant que l’utilisateur passe d’une vue de résultats à l’autre.
navlistPanel() reprend la même idée avec les étiquettes d’onglets empilées verticalement sur le côté au lieu d’une ligne horizontale. Préférez-le quand vous avez beaucoup de sections ou de longues étiquettes qui ne tiendraient pas en haut.
navlistPanel(
tabPanel("Overview", "..."),
tabPanel("Details", "..."),
tabPanel("Settings", "...")
)Grouper avec wellPanel
wellPanel() enveloppe son contenu dans un encadré gris en creux — un léger cadre visuel qui dit « ces éléments vont ensemble. » Il ne change pas la grille ; c’est purement un repère de groupement. Utilisez-le pour distinguer un bloc de contrôles liés du reste de la page.
wellPanel(
h4("Filters"),
selectInput("var", "Variable:", choices = names(mtcars)),
sliderInput("n", "Rows:", min = 1, max = 32, value = 10)
)sidebarPanel() dessine déjà cet encadré gris, vous avez donc rarement besoin de wellPanel() dans un panneau latéral — recourez-y pour grouper des contrôles qui vivent dans une simple column().
Pages à largeur fixe et pleine fenêtre
Deux alternatives à fluidPage() pour des besoins spécifiques :
fixedPage()plafonne le contenu à une largeur maximale fixe et le centre sur les écrans larges, au lieu de l’étirer d’un bord à l’autre. Utilisez-le quand une application paraît trop clairsemée étalée sur un moniteur ultra-large et que vous voulez une colonne contenue, façon document.fillPage()fait remplir à son contenu toute la hauteur de la fenêtre du navigateur — utile pour un unique graphique ou une carte plein écran qui devrait occuper tout l’espace disponible plutôt que de s’inscrire dans le flux normal de la page.
Les deux sont des remplacements directs de fluidPage() en tête du ui ; fluidPage() reste le bon défaut pour la grande majorité des applications.
Quelle mise en page pour quelle tâche
Une recherche rapide. Le conteneur que vous choisissez découle de la façon dont vous voulez organiser la page.
| Vous voulez… | Utiliser | Ce qu’il agence |
|---|---|---|
| L’enveloppe de page (responsive) | fluidPage() |
tout le ui, s’adapte à la largeur |
| Un titre / en-tête de page | titlePanel() |
un titre en haut |
| Contrôles à gauche, résultats à droite | sidebarLayout() + sidebarPanel() / mainPanel() |
la division classique en deux parties |
| Un agencement côte à côte sur mesure | fluidRow() + column() |
une ligne de grille de 12 unités |
| Pousser une colonne vers la droite | column(width, offset = n, …) |
laisse n unités vides à gauche |
| Plusieurs vues dans un même espace | tabsetPanel() + tabPanel() |
des onglets horizontaux |
| Beaucoup de sections / de longues étiquettes | navlistPanel() |
des onglets verticaux sur le côté |
| Une application multi-pages | navbarPage() + tabPanel() |
une barre de navigation en haut, une page par onglet |
| Grouper des pages de navbar dans un menu | navbarMenu() |
un menu déroulant dans la barre de navigation |
| Grouper visuellement des contrôles | wellPanel() |
un encadré de groupement gris |
| Une page centrée à largeur fixe | fixedPage() |
plafonne la largeur du contenu |
| Une page pleine hauteur de fenêtre | fillPage() |
remplit toute la fenêtre |
Le motif est constant : une fonction de page enveloppe tout, sidebarLayout ou fluidRow/column agence le corps, et des onglets ou une barre de navigation ajoutent une seconde dimension quand un seul écran ne suffit pas.
Problèmes fréquents
Vos colonnes ne s’alignent pas — les largeurs ne totalisent pas 12. Une fluidRow() fait 12 unités de large. Si vous écrivez column(4, …) + column(4, …) (total 8), la ligne laisse 4 unités vides à droite ; column(6, …) + column(8, …) (total 14) déborde et la deuxième colonne passe à la ligne suivante. Faites en sorte que les largeurs de chaque ligne totalisent exactement 12 et la mise en page se met en place.
column() ne fait rien / génère une erreur hors d’une ligne. column() ne fonctionne qu’à l’intérieur d’une fluidRow() (ou d’un sidebarPanel/mainPanel, qui fournissent la ligne eux-mêmes). Un simple column(6, …) déposé directement dans fluidPage() n’a pas de grille pour se dimensionner. Enveloppez toujours les colonnes dans une fluidRow().
Imbriquer une fonction de page dans une autre fonction de page. Une fluidPage() (ou navbarPage, fixedPage) est le conteneur de premier niveau — elle enveloppe tout le ui une seule fois. Mettre une fluidPage() dans une column() ou une autre fluidPage() double le rembourrage de la page et casse la grille. À l’intérieur de la page, utilisez fluidRow(), sidebarLayout(), wellPanel() et div() pour agencer le contenu — jamais une seconde fonction de page.
Questions fréquentes
Chaque fluidRow() fait 12 unités de large, et chaque column(width, …) à l’intérieur réclame width de ces unités. Les largeurs d’une ligne devraient totaliser 12 — column(4, …) + column(8, …) remplit la ligne en une division un tiers / deux tiers. Les colonnes s’empilent verticalement sur les écrans étroits automatiquement, la grille est donc responsive sans code supplémentaire.
fluidPage() est l’enveloppe de page — le conteneur le plus externe qui contient tout le ui. sidebarLayout() est une mise en page à l’intérieur de cette page : elle divise le corps en un sidebarPanel() (contrôles) et un mainPanel() (résultats). Vous les utilisez ensemble — sidebarLayout() va à l’intérieur de fluidPage().
Utilisez tabsetPanel() avec un tabPanel() par vue : tabsetPanel(tabPanel("Plot", plotOutput("p")), tabPanel("Table", tableOutput("t"))). Un seul onglet s’affiche à la fois. Placez-le là où vous voulez que les onglets apparaissent — couramment à l’intérieur d’un mainPanel(). Pour des onglets verticaux sur le côté, utilisez navlistPanel() à la place.
Utilisez navbarPage() comme conteneur de premier niveau au lieu de fluidPage(). Chaque tabPanel() devient une page entière accessible depuis une barre de navigation en haut : navbarPage("My App", tabPanel("Home", …), tabPanel("About", …)). Regroupez des pages liées sous un menu déroulant avec navbarMenu(). Recourez à une barre de navigation quand l’application a des sections distinctes plutôt qu’un seul écran de résultats.
Passez l’argument width (en unités de grille, sur 12) à chaque panneau : sidebarPanel(width = 3, …) et mainPanel(width = 9, …) pour un panneau latéral plus étroit que le défaut 4/8. Déplacez le panneau latéral vers la droite avec sidebarLayout(…, position = "right").
Testez vos connaissances
Construisez un ui pour une application d’histogramme. Enveloppez-le dans fluidPage() avec un titlePanel(). Utilisez un sidebarLayout() où le panneau latéral contient un sliderInput("bins", …) et le panneau principal contient un tabsetPanel() avec deux onglets : un onglet Plot affichant plotOutput("hist") et un onglet Summary affichant verbatimTextOutput("stats").
Le squelette est fluidPage(titlePanel(…), sidebarLayout(sidebarPanel(…), mainPanel(…))). Le curseur va à l’intérieur de sidebarPanel(). À l’intérieur de mainPanel(), placez un tabsetPanel() avec deux appels tabPanel() — chacun prend une chaîne d’étiquette et la sortie à afficher.
ui <- fluidPage(
titlePanel("Histogram explorer"),
sidebarLayout(
sidebarPanel(
sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)
),
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("hist")),
tabPanel("Summary", verbatimTextOutput("stats"))
)
)
)
)sidebarLayout() crée la division contrôles-à-gauche / résultats-à-droite ; le tabsetPanel() à l’intérieur de mainPanel() permet à l’utilisateur de passer du graphique au résumé pendant que le curseur reste en place dans le panneau latéral.
Vous écrivez une ligne ainsi : fluidRow(column(5, …), column(5, …)). Que se passe-t-il ?
A. Les deux colonnes remplissent la ligne uniformément, chacune prenant la moitié. B. Les colonnes prennent 5 + 5 = 10 unités, laissant 2 unités vides à droite. C. Cela génère une erreur, car les largeurs de colonnes doivent toujours totaliser 12. D. La deuxième colonne passe à la ligne suivante.
B. Une fluidRow() fait 12 unités de large ; column(5, …) + column(5, …) en réclame 10, la ligne a donc 2 unités vides à droite et les colonnes ne sont pas centrées. Cela ne génère pas d’erreur (C) — le sous-remplissage est autorisé, ça paraît juste décalé. Le passage à la ligne (D) ne se produit que lorsque les largeurs dépassent 12. Pour deux moitiés égales, utilisez column(6, …) deux fois.
Conclusion
Vous disposez désormais de la boîte à outils de mise en page complète : l’enveloppe de page (fluidPage, avec fixedPage / fillPage pour des besoins de largeur fixe ou de pleine fenêtre), la classique sidebarLayout() avec sidebarPanel / mainPanel, la grille à 12 colonnes (fluidRow + column, les largeurs totalisant 12, offset pour décaler), les onglets (tabsetPanel / tabPanel, ou navlistPanel pour la verticale), la navigation multi-pages (navbarPage / navbarMenu), et wellPanel pour le groupement visuel. Ils s’imbriquent librement, et la grille est responsive par défaut — les colonnes s’empilent sur les petits écrans sans travail supplémentaire.
Avec les entrées, les sorties, et maintenant les mises en page en main, la dernière pièce du ui est de lui donner l’apparence que vous voulez — couleurs, polices et thèmes.
Leçons connexes
- Construisez à partir d’ici : affichages de sortie — les graphiques, tableaux et textes que vous agencez avec ces mises en page (la leçon précédente) ; contrôles d’entrée — les widgets qui remplissent un
sidebarPanel. Ensuite styles et thèmes change l’apparence de toute la mise en page — couleurs, polices, thèmes Bootstrap. Pour savoir où leuise situe dans l’application, voir structure d’une application. - Allez plus loin : UI Shiny — la série complète. · Science computationnelle et IA — le pilier.
Réutilisation
Citation
@online{2026,
author = {},
title = {Mises en page Shiny : fluidPage, sidebarLayout et la grille à
12 colonnes},
date = {2026-06-28},
url = {https://www.datanovia.com/learn/programming/shiny/ui/layout-systems},
langid = {fr}
}