I figured out a way to do this without using a Frame which wasn't feasible in my implementation. You have to use a combination of sticky=tk.EW on the grid and justify/anchor on the label.
Here is a piece of my code that lists account names, balances, and account type in a grid. When you hover over one of the rows, the entire row will highlight without any gaps. The only frame being used is to hold all of the contents (which I needed to keep the columns neat and organized) -- it doesn't use a frame for each row.
import tkinter as tk
from tkinter import ttk
def show_accounts(self) -> None:
account_frame = ttk.Frame(self.content_frame)
account_frame.grid(column=0, row=0)
ttk.Label(account_frame, text="Account").grid(column=0, row=0, sticky=tk.W, padx=(0,20))
ttk.Label(account_frame, text="Balance").grid(column=1, row=0, sticky=tk.W, padx=(0,20))
ttk.Label(account_frame, text="Type").grid(column=2, row=0, sticky=tk.W)
ttk.Separator(account_frame).grid(column=0, row=1, sticky=tk.EW, columnspan=3)
accounts = self.controller.get_accounts()
for i, account in enumerate(accounts):
account_name = ttk.Label(account_frame, text=str(account.name), justify=tk.LEFT, anchor=tk.W)
account_name.grid(column=0, row=i+2, sticky=tk.EW, ipadx=20)
account_balance = ttk.Label(account_frame, text=f"{account.balance:,.2f}", justify=tk.LEFT, anchor=tk.W)
account_balance.grid(column=1, row=i+2, sticky=tk.EW, ipadx=20)
account_type = ttk.Label(account_frame, text=AccountType(account.type).name.title(), justify=tk.LEFT, anchor=tk.W)
account_type.grid(column=2, row=i+2, sticky=tk.EW)
# Bindings
account_name.bind("<Enter>", lambda e, account=account: self.highlight_account_row(e, account))
account_name.bind("<Leave>", lambda e, account=account: self.unhighlight_account_row(e, account))
# Save to dictionary
self.widgets[f"{account.name}_name"] = account_name
self.widgets[f"{account.name}_balance"] = account_balance
self.widgets[f"{account.name}_type"] = account_type
def highlight_account_row(self, event, account):
self.widgets[f"{account.name}_name"].configure(background="grey")
self.widgets[f"{account.name}_balance"].configure(background="grey")
self.widgets[f"{account.name}_type"].configure(background="grey")
def unhighlight_account_row(self, event, account):
self.widgets[f"{account.name}_name"].configure(background="white")
self.widgets[f"{account.name}_balance"].configure(background="white")
self.widgets[f"{account.name}_type"].configure(background="white")