Most apps are mainly displaying results, and choosing the right element makes them readable at a glance.
`st.write` is the Swiss Army knife: it accepts strings (rendered as Markdown), numbers, DataFrames, dicts, figures and more, and picks a suitable display. It also takes several arguments: st.write("Total:", total).
Magic: a bare expression on its own line, such as a variable name or a string, is written to the app automatically, as if wrapped in st.write. Handy for quick scripts; explicit calls are clearer in larger apps.
Dedicated elements give more control:
- Text:
st.title,st.header,st.subheader,st.markdown(with emoji shortcodes and colored text like:blue[text]),st.caption,st.code(src, language="python"),st.latex. - Data:
st.dataframe(df)is an interactive grid with sorting, search and column resizing;column_configformats columns (currency, progress bars, links, images).st.tablerenders a static table.st.jsonshows a collapsible tree. - KPIs:
st.metric("Revenue", "$12.3k", "+4.5%")shows a value with a colored delta. - Status:
st.success,st.info,st.warning,st.error,st.exception, andst.toastfor brief notifications.
st.dataframe handles large frames efficiently, but sending millions of rows to the browser is still slow; filter or aggregate first.
Anything displayed is part of the page only until the next rerun, when the script redraws everything from scratch.
Example
import pandas as pd
import streamlit as st
df = pd.DataFrame({"product": ["Tea", "Coffee", "Cocoa"],
"revenue": [1200.5, 3400.0, 560.25],
"share": [0.23, 0.66, 0.11]})
st.title("Sales overview")
st.markdown("Revenue for **March**, :blue[all regions].")
col1, col2 = st.columns(2)
col1.metric("Revenue", f"${df.revenue.sum():,.0f}", "+4.5%")
col2.metric("Products", len(df), "-1")
st.dataframe(df, hide_index=True, column_config={
"revenue": st.column_config.NumberColumn("Revenue", format="$%.2f"),
"share": st.column_config.ProgressColumn("Share", min_value=0, max_value=1),
})
st.write("Top product:", df.loc[df.revenue.idxmax(), "product"])
"Magic: this bare string is displayed too"
st.success("Data loaded")Remember
st.writedisplays almost anything; bare expressions are shown via magicst.dataframewithcolumn_configgives interactive, formatted tablesst.metricshows KPIs with deltas; status elements show messages
Watch out for
- Sending a multi-million-row DataFrame to
st.dataframeinstead of filtering or aggregating first.