st.columns para disposición en columnas y diseño responsive

Básico
Streamlit
Streamlit
Actualizado: 26/04/2026

st.columns: diseño en columnas

st.columns divide el espacio horizontal disponible en N columnas que pueden contener cualquier elemento de Streamlit. Es el componente de layout más usado en dashboards porque permite organizar métricas, gráficos y controles de forma horizontal, aprovechando todo el ancho de pantalla disponible.

Al pasar un entero, se crean columnas de igual proporción. Cada columna se comporta como un contenedor independiente donde se pueden insertar widgets, texto, gráficos o cualquier otro componente de Streamlit:

import streamlit as st

# Tres columnas iguales
col1, col2, col3 = st.columns(3)

with col1:
    st.metric("Ingresos", "€ 45.230", "+8,2%")

with col2:
    st.metric("Gastos", "€ 28.100", "+3,1%")

with col3:
    st.metric("Beneficio", "€ 17.130", "+15,4%")

Las columnas de Streamlit se comportan de forma responsive en dispositivos móviles: cuando el ancho de pantalla es insuficiente para mostrar todas las columnas en horizontal, se apilan verticalmente de forma automática.

flowchart TD
    A[st.columns N o lista pesos] --> B{"Forma de uso?"}
    B -->|Iguales| C["col1 col2 col3 = st.columns 3"]
    B -->|Proporcional| D["col1 col2 = st.columns 3 a 1"]
    C --> E[Cada col contenedor independiente]
    D --> E
    E --> F["with col1: contenido propio"]
    E --> G["with col2: contenido propio"]
    F --> H[Renderiza horizontal]
    G --> H
    H --> I{"Pantalla movil?"}
    I -->|Si| J[Apila vertical responsive]
    I -->|No| K[Mantiene horizontal]
    A --> L[gap small medium large]
    L --> H

Columnas con proporciones personalizadas

En lugar de un entero, se puede pasar una lista de proporciones para crear columnas con anchos diferentes. Este enfoque es fundamental para diseños asimétricos donde, por ejemplo, se necesita un panel lateral de filtros más estrecho junto a un área de contenido principal más ancha:

import streamlit as st
import numpy as np
import pandas as pd

# Columna de filtros (1 unidad) + columna principal (3 unidades)
col_filtros, col_principal = st.columns([1, 3])

with col_filtros:
    st.subheader("Filtros")
    año = st.selectbox("Año", [2024, 2025, 2026])
    region = st.multiselect("Región", ["Norte", "Sur", "Este", "Oeste"], default=["Norte", "Sur"])

with col_principal:
    st.subheader(f"Resultados — {año}")
    df = pd.DataFrame(np.random.randn(8, 3), columns=["A", "B", "C"])
    st.line_chart(df)

Las proporciones son relativas entre sí: [1, 3] significa que la primera columna ocupa el 25% del ancho y la segunda el 75%. Los valores [2, 3, 5] distribuyen el espacio en 20%, 30% y 50% respectivamente.

Parámetro gap: espaciado entre columnas

El parámetro gap controla el espacio horizontal entre columnas. Dispone de tres valores que permiten ajustar la separación según la densidad de información que se necesite mostrar:

import streamlit as st

# Gap pequeño (predeterminado)
c1, c2 = st.columns(2, gap="small")
c1.write("Columna 1 con gap pequeño")
c2.write("Columna 2 con gap pequeño")

# Gap mediano
c1, c2 = st.columns(2, gap="medium")
c1.write("Gap mediano")
c2.write("Gap mediano")

# Gap grande
c1, c2 = st.columns(2, gap="large")
c1.write("Gap grande")
c2.write("Gap grande")

En paneles de métricas donde cada columna contiene un solo valor, "small" maximiza el aprovechamiento del espacio. Para layouts con gráficos o formularios, "medium" o "large" mejoran la legibilidad al dar más aire visual a cada sección.

Vertical_alignment: alinear contenido verticalmente

import streamlit as st

col1, col2, col3 = st.columns(3, vertical_alignment="center")

with col1:
    st.image("https://streamlit.io/images/brand/streamlit-logo-secondary-colormark-darktext.png", width=150)

with col2:
    st.metric("Usuarios", "12.450")
    st.metric("Sesiones", "48.230")

with col3:
    if st.button("Ver informe completo", use_container_width=True, type="primary"):
        st.success("Generando informe...")

Panel de métricas con 4 columnas

import streamlit as st
import pandas as pd
import numpy as np

st.title("Dashboard ejecutivo")

# Panel de KPIs
kpis = {
    "Ingresos": ("€ 124.500", "+15,3%", "normal"),
    "Costes": ("€ 78.200", "+8,1%", "inverse"),
    "Margen": ("37,3%", "+4,2pp", "normal"),
    "NPS": ("72", "+5", "normal")
}

cols = st.columns(4)
for col, (nombre, (valor, delta, direction)) in zip(cols, kpis.items()):
    col.metric(nombre, valor, delta, delta_color=direction)

st.divider()

# Dos columnas para gráficos
col_graf1, col_graf2 = st.columns(2)

with col_graf1:
    st.subheader("Ingresos mensuales")
    df = pd.DataFrame({"mes": range(1, 13), "ingresos": np.random.randint(8000, 15000, 12)})
    st.bar_chart(df, x="mes", y="ingresos", color="#FF4B4B")

with col_graf2:
    st.subheader("Evolución del margen")
    df2 = pd.DataFrame({"mes": range(1, 13), "margen": np.random.uniform(30, 45, 12)})
    st.line_chart(df2, x="mes", y="margen", color="#2CA02C")

Columnas anidadas

import streamlit as st

# Columna principal con sub-columnas internas
col_izq, col_der = st.columns([2, 1])

with col_izq:
    st.subheader("Panel principal")
    sub1, sub2 = st.columns(2)
    sub1.metric("Ventas enero", "€ 38.000", "+12%")
    sub2.metric("Ventas febrero", "€ 41.200", "+8,4%")

    st.line_chart([38000, 41200, 45300])

with col_der:
    st.subheader("Resumen")
    st.write("**Total Q1:** € 124.500")
    st.write("**Crecimiento:** +10,2%")
    st.write("**Objetivo:** ✓ Alcanzado")
    st.progress(0.85, text="85% del objetivo anual")

Notación alternativa con métodos directos

Además del bloque with, se puede usar la notación de punto para insertar elementos directamente en una columna. Ambos enfoques son equivalentes, pero la notación de punto resulta más concisa para elementos sueltos:

import streamlit as st

c1, c2, c3 = st.columns(3)
c1.metric("CPU", "45%")
c2.metric("RAM", "72%")
c3.metric("Disco", "38%")

El bloque with es preferible cuando se insertan varios elementos en una misma columna, ya que evita repetir el nombre de la columna en cada línea y agrupa visualmente todo el contenido que pertenece a esa sección del layout.

Contexto: columnas como bloque fundamental del layout

Streamlit no ofrece un sistema de grilla tipo Bootstrap: en su lugar, apuesta por una API minimalista basada en columnas y contenedores. Esta decisión de diseño obedece al público objetivo de la biblioteca (analistas de datos sin experiencia frontend) y a la filosofía de "producir dashboards sin CSS". Aunque parezca limitado al principio, st.columns combinado con contenedores y pestañas cubre el 95 % de los layouts habituales en dashboards analíticos.

Internamente, cada columna es un contenedor Flexbox con una proporción relativa al resto. El motor de layout de Streamlit decide el ancho exacto en tiempo de render, lo que permite que las columnas se adapten automáticamente al ancho de la ventana. En móviles, cuando el espacio horizontal es insuficiente, las columnas se apilan en vertical sin que el desarrollador tenga que escribir media queries.

Explicación línea por línea del dashboard ejecutivo

El ejemplo del panel de KPIs demuestra un patrón idiomático de Streamlit:

  1. kpis = {...} define una estructura de datos separada de la capa de presentación. Cada KPI tiene su valor, su delta y el color del delta.
  2. cols = st.columns(4) crea cuatro columnas iguales, una por KPI.
  3. zip(cols, kpis.items()) empareja cada columna con su KPI correspondiente.
  4. Dentro del bucle, col.metric(...) inserta la métrica directamente en la columna usando la notación de punto (más concisa que with col:).
  5. st.divider() dibuja una línea horizontal para separar visualmente los KPIs de los gráficos.
  6. Dos nuevas columnas col_graf1, col_graf2 organizan los gráficos en paralelo, cada uno ocupando la mitad del ancho.

Tabla de parámetros de st.columns

| Parámetro | Tipo | Descripción | |-----------|------|-------------| | spec | int o list[float] | Número de columnas o lista de proporciones | | gap | "small", "medium", "large" | Espacio horizontal entre columnas | | vertical_alignment | "top", "center", "bottom" | Alineación vertical del contenido | | border | bool | Dibuja un borde alrededor de cada columna |

Errores comunes

Número desigual de columnas en iteraciones. Si creas columnas dentro de un bucle y el número varía, se producirán layouts inconsistentes. Calcula el número de columnas antes del bucle y mantenlo constante.

Gráficos que no respetan el ancho. Por defecto, algunos gráficos (matplotlib, plotly) se renderizan con un ancho fijo. Usa use_container_width=True en st.pyplot y st.plotly_chart para que se ajusten al ancho de la columna.

Anidar columnas demasiado. Streamlit permite anidar st.columns dentro de columnas, pero más de dos niveles de anidamiento genera layouts confusos y rompe la responsividad en móviles. Prefiere st.tabs o st.container para jerarquías más profundas.

Olvidar que las columnas son responsivas. En móviles se apilan verticalmente, lo que puede romper la lectura de datos pensada como tabla. Prueba tu app en ancho reducido antes de dar por bueno el diseño.

Proporciones con números muy distintos. Una proporción [1, 100] es matemáticamente válida pero visualmente la primera columna será imperceptible. Mantén las proporciones en el rango 1-5 para resultados razonables.

Mejores prácticas

  • Usa st.columns(4) o st.columns(3) para paneles de KPIs principales; más de 5 KPIs apilados en horizontal empiezan a sentirse saturados.
  • Combina st.columns con vertical_alignment="center" cuando mezcles elementos de alturas diferentes (logos, textos, botones) para evitar desalineaciones visuales.
  • Usa border=True en columnas para crear tarjetas visuales sin necesidad de CSS custom.
  • Para layouts complejos, dibuja primero el wireframe en papel: ayuda mucho a planificar dónde van las columnas y los contenedores antes de escribir el código.
  • Recuerda que st.columns solo se puede llamar en el área principal o dentro del sidebar, pero no dentro de otro widget como st.tabs. Para tabs con columnas internas, define las columnas dentro del with tab_x:.
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Streamlit es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Streamlit

Explora más contenido relacionado con Streamlit y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Crear layouts de columnas iguales y proporcionales con st.columns. Distribuir métricas, gráficos y widgets en columnas para aprovechar el espacio. Usar st.columns con el parámetro gap para controlar el espaciado entre columnas. Anidar columnas dentro de contenedores para layouts complejos. Aplicar patrones comunes de dashboard con columnas en Streamlit.