Version: 0.2.1
Create resizable columns in Streamlit! This component provides st.columns
functionality with draggable resize handles that allow users to adjust column widths dynamically.
- 🎯 Drop-in Replacement: Works exactly like
st.columns
with the same API - 🖱️ Resizable Boundaries: Drag handles between columns to adjust widths
- 💾 Persistent State: Column widths persist across app reruns
- 🎨 Theme Integration: Automatically matches your Streamlit theme
- 📱 Responsive: Works on desktop and mobile devices
- ⚙️ Full Compatibility: Supports all
st.columns
parameters (gap, alignment, border) - 🔒 Minimum Width: 6% minimum width constraint prevents unusably narrow columns
- 📊 Width Tracking: Optional
return_widths
parameter for dynamic layouts - 👁️ Hide/Show Columns: Double-click column headers to hide/show columns dynamically
pip install streamlit-adjustable-columns
Note: Packages installed from PyPI already include the compiled frontend so no additional tools are required. If you install from a source checkout (e.g. GitHub), Node.js and npm are needed to build the frontend assets.
import streamlit as st
from streamlit_adjustable_columns import adjustable_columns
# Use exactly like st.columns - but with resize handles!
col1, col2, col3 = adjustable_columns(3, labels=["📊 Charts", "📋 Data", "⚙️ Settings"])
with col1:
st.metric("Sales", "$1,234", "12%")
col2.write("This column can be resized!")
col3.button("Settings")
You know it's working when you see:
- ✅ Column headers with drag handles between them
- ✅ Ability to drag column separators to resize
- ✅ Column widths persist when you interact with other elements
- ✅ Responsive behavior on different screen sizes
adjustable_columns(spec, *, gap="small", vertical_alignment="top", border=False, labels=None, return_widths=False, initial_hidden=None, key=None)
Creates resizable columns with draggable boundaries.
spec
(int or list): Number of columns or width ratios3
→ Three equal columns[2, 1]
→ Two columns with 2:1 ratio
gap
(str): Space between columns -"small"
,"medium"
, or"large"
vertical_alignment
(str): Content alignment -"top"
,"center"
, or"bottom"
border
(bool): Show borders around columnslabels
(list): Custom labels shown in resize handlesreturn_widths
(bool): Return width information along with columnsinitial_hidden
(list of bool, optional): List of booleans indicating which columns should start hidden. Must match the number of columns. Example:[False, True, False]
will start the second column hidden.key
(str): Unique component key (recommended for multiple instances)
- Default: List of column containers (same as
st.columns
) - With
return_widths=True
: Dict with{'columns': [...], 'widths': [...], 'hidden': [...]}
- Look for resize handles above each set of adjustable columns
- Hover over the boundaries between column areas - you'll see resize cursors
- Click and drag the handles to adjust column widths
- Double-click a column header to hide/show that column
- Release to apply changes - they persist across app reruns!
# Create a dashboard with resizable main content and sidebar
main, sidebar = adjustable_columns([4, 1], labels=["📊 Dashboard", "⚙️ Controls"])
with main:
st.subheader("Analytics Overview")
col1, col2 = st.columns(2)
col1.metric("Revenue", "$45,231", "12%")
col2.metric("Users", "1,429", "3%")
st.line_chart(data)
with sidebar:
st.selectbox("Time Period", ["1D", "1W", "1M"])
st.checkbox("Show Trends")
st.button("Refresh Data")
# Track column widths for dynamic layouts
result = adjustable_columns([2, 1], labels=["Content", "Sidebar"], return_widths=True)
content, sidebar = result['columns']
current_widths = result['widths']
st.info(f"Current ratios: {[f'{w:.1f}' for w in current_widths]}")
with content:
st.write("Main content area")
with sidebar:
st.write("Adjustable sidebar")
# Each set of columns needs a unique key
cols1 = adjustable_columns(3, labels=["A", "B", "C"], key="top")
cols2 = adjustable_columns([1, 2], labels=["Left", "Right"], key="bottom")
# First row
cols1[0].metric("Metric 1", "100")
cols1[1].metric("Metric 2", "200")
cols1[2].metric("Metric 3", "300")
# Second row
cols2[0].button("Action")
cols2[1].write("Content area")
columns = adjustable_columns(
spec=[3, 2, 1], # Custom width ratios
gap="large", # Large spacing
vertical_alignment="center", # Center-align content
border=True, # Show column borders
labels=["📊 Charts", "📋 Data", "⚙️ Tools"], # Custom labels
return_widths=True, # Get width info
key="advanced_example" # Unique identifier
)
cols = columns['columns']
widths = columns['widths']
Start with Some Columns Hidden
# Start with the second column hidden
cols = adjustable_columns(
[1, 1, 1],
labels=["Main", "Side", "Tools"],
initial_hidden=[False, True, False],
key="hidden_example"
)
with cols[0]:
st.write("Main column is visible!")
with cols[1]:
st.write("Side column starts hidden!")
with cols[2]:
st.write("Tools column is visible!")
Customize the labels shown in resize handles:
cols = adjustable_columns(
3,
labels=["📈 Analytics", "🛠️ Tools", "📱 Mobile"]
)
Use width information for responsive behavior:
result = adjustable_columns([2, 1], return_widths=True)
main_col, side_col = result['columns']
widths = result['widths']
# Adapt content based on current column width
if widths[0] > 3: # Main column is wide
main_col.plotly_chart(fig, use_container_width=True)
else: # Main column is narrow
main_col.write("Chart too narrow - expand column to view")
- Python 3.9+
- Node.js 18+
- npm or yarn
- Git
# Clone the repository
git clone https://github.com/danieljannai/streamlit-adjustable-columns
cd streamlit-adjustable-columns
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
make install-dev
# Or manually:
pip install -e ".[dev]"
cd streamlit_adjustable_columns/frontend
npm install
cd ../..
# Terminal 1: Start frontend development server
make frontend-dev # Or: cd streamlit_adjustable_columns/frontend && npm start
# Terminal 2: Run the demo (make sure venv is activated)
source venv/bin/activate
streamlit run example.py
-
Frontend Dev Server: http://localhost:3001
- This serves the interactive column resizer component
-
Streamlit App: http://localhost:8501
- Your main app with the adjustable columns
The project includes comprehensive tests using pytest and Playwright:
# Run all tests
make test
# Run only unit tests
make test-unit
# Run only E2E tests
make test-e2e
# Run with coverage
pytest --cov=streamlit_adjustable_columns
# Format code
make format
# Check linting
make lint
# Run full check (format + lint + test)
make format && make lint && make test
# Build the package
make build
# Upload to PyPI (requires credentials)
make upload
- Make sure the frontend dev server is running on port 3001
- Check that
_RELEASE = False
instreamlit_adjustable_columns/__init__.py
- Make sure your virtual environment is activated:
source venv/bin/activate
- Reinstall dependencies:
make install-dev
- Make sure Node.js and npm are installed
- Delete
node_modules
and runnpm install
again
- If port 3001 or 8501 are busy, kill other processes or change ports in the configuration
The project includes comprehensive test coverage:
- Unit Tests: Test core functionality, parameter handling, and state management
- Integration Tests: Test component behavior with Streamlit integration
- E2E Tests: Test user interactions, resize functionality, and visual elements
- Cross-browser Testing: Firefox and Chromium support via Playwright
Test files are organized in the tests/
directory:
tests/test_unit.py
- Unit tests for Python codetests/test_integration.py
- Integration teststests/test_*.py
- E2E tests for specific featurestests/streamlit_apps/
- Test Streamlit applications
Contributions are welcome! Please feel free to submit a Pull Request. This is a brief overview of how to contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Install development dependencies (
make install-dev
) - Make your changes and add tests
- Run the test suite (
make test
) - Format your code (
make format
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
For detailed contributing guidelines, development setup, testing procedures, and release processes, please see CONTRIBUTING.md.
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Streamlit
- Inspired by the need for flexible column layouts in Streamlit applications
- Developed with great assistance from Cursor AI coding assistant
Daniel Jannai Epstein
- GitHub: @danieljannai
- Created this component to enhance Streamlit's column functionality
Made with ❤️ for the Streamlit community