overflow: visible (the default) does nothing — content simply spills past the box edge and can overlap neighboring elements. hidden clips the overflow and provides no way to reach it — users have no means to see the cut-off content. scroll always shows a scrollbar whether content overflows or not; auto only creates one when content actually overflows — auto is the right answer for most "scrollable area" needs.
clip (a comparatively recent value) crops like hidden, but also blocks scrolling programmatically — hidden can still be scrolled via JS methods like scrollTo(), while clip can't be scrolled at all. It also accepts overflow-clip-margin, letting content extend a few pixels past the edge before being clipped — handy for a shadow that shouldn't get cut off.
overflow-x and overflow-y set each axis independently. A common trap: overflow: hidden on a parent that contains a position: sticky child — sticky stops working the moment its nearest scrollable ancestor's overflow isn't visible.
When to use
auto is the default choice for a fixed-size viewport whose contents scroll internally — a long list in a modal, a chat window, a code block. If a design element intentionally spills slightly past its box, just leave overflow as visible.