2025, Sep 28 09:00
How to Make a Tkinter Horizontal Scrollbar Sit Flush with a Listbox (Grid sticky and Frame fixes)
Troubleshooting a Tkinter gap between a Listbox and horizontal Scrollbar? Learn why grid sizing causes it and how sticky or a Frame makes them sit flush.
Getting a Tkinter Scrollbar to sit flush with a Listbox
Sometimes a seemingly simple layout in Tkinter refuses to line up. A common example is a horizontal Scrollbar that won’t sit tightly against a Listbox, leaving an unexpected gap even when highlightthickness, padding, and sticky values appear correct. The situation gets trickier when other widgets like Canvas are part of the same grid, because they influence how rows are sized.
The minimal setup that exposes the issue
The following example places a Canvas on the left and a Listbox with a horizontal Scrollbar on the right. The gap tends to appear when the Listbox has a fixed height, and it becomes visible across platforms in that configuration.
import tkinter as tk
app = tk.Tk()
lb = tk.Listbox(app)
hbar = tk.Scrollbar(app)
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0, rowspan=2)
lb.config(height=4, xscrollcommand=hbar.set)
lb.grid(column=1, row=0, sticky="EW")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="EW")
app.mainloop()What actually causes the gap
The behavior shows up clearly after setting the Listbox height to a fixed value. The grid geometry manager aligns row heights across columns, and the combination of widget sizes can create a vertical offset when widgets aren’t anchored toward each other. In the example above, the Listbox isn’t pushed down to the bottom of its grid cell and the Scrollbar isn’t pulled up to the top of its cell, so you end up seeing a sliver of space between them.
The fix: anchor both sides with sticky
Force the Listbox to stick to the south edge and the Scrollbar to stick to the north edge, while keeping them stretched east–west. This brings both edges together and removes the gap.
import tkinter as tk
app = tk.Tk()
lb = tk.Listbox(app)
hbar = tk.Scrollbar(app)
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0, rowspan=2)
lb.config(height=4, xscrollcommand=hbar.set)
lb.grid(column=1, row=0, sticky="EWS")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="NEW")
app.mainloop()This adjustment keeps everything in place without removing other vertical gaps you may want to preserve elsewhere.
Alternative: isolate with a Frame
Another robust approach is to group the Listbox and Scrollbar in a Frame and manage their relationship inside that container. That way they aren’t affected by the grid used by the rest of the window. In this variant, the Canvas doesn’t need rowspan.
import tkinter as tk
app = tk.Tk()
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0)
holder = tk.Frame(app)
holder.grid(column=1, row=0)
lb = tk.Listbox(holder)
hbar = tk.Scrollbar(holder)
lb.config(xscrollcommand=hbar.set, height=4)
lb.grid(column=1, row=0, sticky="EW")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="EW")
app.mainloop()This layout keeps the pair together and produces the same visual result while keeping the rest of the UI independent.
Why this matters
Grid-managed rows share height across columns, similar to how spreadsheets behave. A taller widget in one column can influence row height and reveal gaps elsewhere if elements aren’t anchored appropriately. Being explicit with sticky and, when needed, isolating related widgets in a Frame prevents subtle layout shifts when the UI grows, shrinks, or adds components.
Conclusion
When a Scrollbar won’t sit flush against a Listbox, anchor both sides: add S to the Listbox sticky and N to the Scrollbar sticky while keeping them stretched east–west. If your window contains other widgets that affect grid sizing, group the Listbox and Scrollbar in a Frame and lay them out inside that container. These two patterns keep layouts predictable and spare you from chasing unexplained gaps later.
The article is based on a question from StackOverflow by Nabodita Gangully and an answer by furas.