Scrolling widgets and borders

When making a scrolling widget (e.g., using a canvas or text widget, plus scrollbar of course) it is important to ensure that the widget doing the scrolling does not have a border. To demonstrate the problem, here's a small sample program:

# Basic scrollable container setup
package require Tk
canvas .c -width 100 -height 100 -yscrollcommand {.s set}
scrollbar .s -orient vertical -command {.c yview}
pack .c .s -fill y -expand 1 -side left -padx 2 -pady 2
set w .c.f
.c create window 0 0 -window [frame $w] -anchor nw -width 100 -height 150
bind $w <Configure> {.c configure -scrollregion [list 0 0 %w %h]}

# Basic content; scrollable windows *must* be children of scroller
label $w.l -text "Just so you\nknow it is\nscrolled" -background yellow
pack $w.l -expand 1 -fill both

# The (exaggerated) problem...
.c configure -relief sunken -borderwidth 5
# that now the label can overlap that border!

When you scroll the label up and down, you'll notice that it overlaps the border, which looks really ugly. (The yellow just makes it more obvious.) This is because Tk draws all borders within the bounds of the widget, yet it is those official bounds which are used to clip the children of the widget. (Indeed, if you don't make the scrolled widgets into children of the scrollable, you will always have the clipping problem.)

The fix is to have no border on the scrollable widget itself, but rather to wrap it in another widget whose sole purpose is to provide the border. It should also be noted that widgets have multiple types of border in normal circumstances. There is the “official” border, and there's also the focus ring (controlled via the -highlightthickness option). Some widgets (though not normally the scrollable ones) have additional “internal” padding, which is also part of the border area.