Skip to content

How to Use Tkinter Pack Fill and Expand in Python

Learn how to create responsive Tkinter layouts using fill and expand parameters to control widget sizing and space allocation when windows are resized.

Creating responsive GUI layouts that adapt gracefully when users resize windows is essential for professional applications. Tkinter's pack() geometry manager provides two key parameters, fill and expand, that control how widgets claim and occupy available space. Understanding the distinction between these parameters transforms static interfaces into dynamic, polished applications.

Understanding the Concepts

Think of each widget as having two components: its allocated space (parcel) and its visible presence within that space:

  • expand: Determines whether the widget's parcel grows to claim unused space in the parent container
  • fill: Determines whether the widget stretches to occupy its allocated parcel
Parameter Purpose Values
expand Claim available space True or False
fill Stretch to fill parcel 'x', 'y', 'both', 'none'

Visual Demonstration

Run this example and resize the window to observe how each configuration behaves:

import tkinter as tk

root = tk.Tk()
root.title("Pack Fill and Expand Demo")
root.geometry("400x300")

tk.Label(root, text="Default (no options)", bg="#e74c3c", 
         fg="white", pady=10).pack()

tk.Label(root, text="fill='x'", bg="#3498db", 
         fg="white", pady=10).pack(fill='x')

tk.Label(root, text="expand=True (no fill)", bg="#2ecc71", 
         pady=10).pack(expand=True)

tk.Label(root, text="expand=True, fill='both'", bg="#9b59b6", 
         fg="white", pady=10).pack(expand=True, fill='both')

root.mainloop()

Fill Options Explained

import tkinter as tk

root = tk.Tk()
root.geometry("300x200")

tk.Label(root, text="fill='x'", bg="coral").pack(fill='x', pady=5)

tk.Label(root, text="fill='y'", bg="lightblue").pack(fill='y', side='left', padx=5)

tk.Label(root, text="fill='both'", bg="lightgreen").pack(fill='both', expand=True)

root.mainloop()

Combining with Side Parameter

The side parameter determines stacking direction, affecting how fill and expand work:

import tkinter as tk

root = tk.Tk()
root.geometry("400x300")

header = tk.Frame(root, bg="#2c3e50", height=50)
header.pack(side='top', fill='x')
tk.Label(header, text="Header", bg="#2c3e50", fg="white").pack()

sidebar = tk.Frame(root, bg="#34495e", width=100)
sidebar.pack(side='left', fill='y')
tk.Label(sidebar, text="Sidebar", bg="#34495e", fg="white").pack(pady=20)

main = tk.Frame(root, bg="#ecf0f1")
main.pack(side='left', expand=True, fill='both')
tk.Label(main, text="Main Content Area", bg="#ecf0f1").pack(expand=True)

root.mainloop()

Common Layout Patterns

Layout Goal Pack Configuration
Full-width header/footer pack(side='top', fill='x')
Full-height sidebar pack(side='left', fill='y')
Expanding content area pack(expand=True, fill='both')
Centered widget pack(expand=True)
Fixed-size, top-aligned pack() (defaults)

Multiple Expanding Widgets

When multiple widgets have expand=True, they share available space equally:

import tkinter as tk

root = tk.Tk()
root.geometry("400x300")

colors = ["#e74c3c", "#3498db", "#2ecc71"]
labels = ["Panel 1", "Panel 2", "Panel 3"]

for color, text in zip(colors, labels):
    tk.Label(root, text=text, bg=color, fg="white").pack(
        expand=True, fill='both'
    )

root.mainloop()

Practical Application: Complete Layout

import tkinter as tk

def create_app():
    root = tk.Tk()
    root.title("Application Layout")
    root.geometry("600x400")
    
    toolbar = tk.Frame(root, bg="#333", height=40)
    toolbar.pack(side='top', fill='x')
    toolbar.pack_propagate(False)  # Maintain fixed height
    
    tk.Button(toolbar, text="File").pack(side='left', padx=5, pady=5)
    tk.Button(toolbar, text="Edit").pack(side='left', padx=5, pady=5)
    
    statusbar = tk.Frame(root, bg="#ddd", height=25)
    statusbar.pack(side='bottom', fill='x')
    statusbar.pack_propagate(False)
    
    tk.Label(statusbar, text="Ready", bg="#ddd").pack(side='left', padx=10)
    
    left_panel = tk.Frame(root, bg="#f0f0f0", width=150)
    left_panel.pack(side='left', fill='y')
    left_panel.pack_propagate(False)
    
    tk.Label(left_panel, text="Navigation", bg="#f0f0f0").pack(pady=10)
    
    main_area = tk.Frame(root, bg="white")
    main_area.pack(side='left', expand=True, fill='both')
    
    tk.Label(main_area, text="Main Content", bg="white", 
             font=("Arial", 16)).pack(expand=True)
    
    return root

app = create_app()
app.mainloop()

By mastering fill and expand, you can create Tkinter interfaces that respond naturally to window resizing, providing a professional user experience.

Navigation