Common visual bugs and how to catch them
The visual defects that reach production most often — overflow, z-index stacking, font fallback shift, broken empty states — what causes each one, and the cheapest way to detect it automatically.
Every one of these ships regularly, in real products, with a full test suite passing. They share a property: nothing throws, no assertion fails, and the page is functionally correct. Only looking at it reveals the problem.
Layout and overflow
1. Horizontal scroll on mobile
One element a few pixels too wide makes the entire page scroll sideways. Usually a fixed width, a wide table, a long unbreakable string, or an element with negative margins.
Catch it cheaply: assert document.documentElement.scrollWidth <= clientWidth at a mobile viewport. This is the highest value-per-line check in the whole list — see responsive visual testing.
2. Text overflowing its container
A layout designed around "Jane Doe" meets "Konstantinos Papadopoulos-Williamson". The name escapes its card, overlaps a button, or gets clipped mid-word. Long email addresses and untranslated German strings do the same.
Catch it: seed fixture data with deliberately long values. A test dataset where every name is short is testing the case that never breaks.
3. Grid and flex collapse
A three-column grid that becomes one column at an unexpected width, or flex items that refuse to shrink because grid and flex children default to min-width: auto and cannot go below their content's min-content size.
Catch it: capture between your breakpoints rather than at them. The fix, nine times out of ten, is min-width: 0 on the item.
4. Content escaping a fixed-height container
A card with height: 200px looks right until the description runs to four lines. Then text spills over the border or gets silently clipped.
Stacking and positioning
5. z-index stacking failures
A modal renders behind its own backdrop. A dropdown is clipped by a parent with overflow: hidden. A sticky header slides under the content it should sit above. New stacking contexts created by transform, filter, opacity or will-change are the usual hidden cause.
Catch it: capture interactive states, not just the page at rest — open the modal, open the dropdown, then screenshot.
6. Sticky elements that stop sticking
position: sticky silently does nothing if any ancestor has overflow: hidden, auto, or scroll. Adding a scroll container three levels up breaks a sticky header with no error anywhere.
7. Fixed elements covering content
A fixed footer or cookie banner that covers the submit button at short viewport heights. Functional tests click the button through the overlay and pass; a real user cannot reach it.
Typography and assets
8. Font fallback shift
A web font fails or loads late and the fallback has different metrics. Every line reflows, headings wrap differently, and a carefully balanced layout becomes ragged. Also the single largest source of visual test flake — see how to fix flaky visual tests.
Catch it: test with the font blocked as well as loaded. size-adjust and ascent-override on the fallback face reduce the damage.
9. Broken or slow images
A missing image leaves alt text in a space sized for a photograph. An image without explicit dimensions causes layout shift as it loads, pushing content down after the user has started reading.
10. Icon misalignment
Icons sitting a pixel or two off their text baseline. Individually trivial, collectively the difference between a product that looks considered and one that does not.
State and data
11. Empty states nobody designed
The most reliably broken screen in any product. A dashboard designed around six populated cards, viewed by a brand-new account with zero of everything: a heading floating above nothing, a table header with no rows, a chart axis with no data.
Catch it: make an empty-state capture part of your standard coverage for every data-driven route. It costs one extra screenshot and catches a disproportionate share of real bugs — visual testing authenticated pages covers seeding these deliberately.
12. Loading and error states
Skeletons that do not match the shape of the content that replaces them, causing a jolt. Error banners that push the layout down. Spinners that are never captured because the test waited for them to disappear — so nobody has ever looked at them.
Why the test suite misses all of these
A functional test asserts the submit button exists and is clickable. It is satisfied by a button that is invisible, positioned off-screen, covered by a banner, or rendered in white on white. The assertion and the user experience have diverged completely, and nothing reports it.
That gap is what visual testing exists to close — background in what is visual regression testing, and the commercial consequence in what visual bugs actually cost.
Frequently asked questions
What are the most common visual bugs?
Horizontal scroll on mobile, text overflowing its container with long real-world values, grid and flex collapse at unexpected widths, z-index stacking failures such as modals behind their backdrop, font fallback reflow, and empty states nobody designed for.
Why don't functional tests catch visual bugs?
Functional tests assert on behaviour and the DOM, not appearance. A test that checks the submit button exists and is clickable passes even if that button is invisible, off-screen, covered by a banner, or white on a white background.
What is the easiest visual bug to test for automatically?
Horizontal overflow. Compare document.documentElement.scrollWidth against clientWidth at a mobile viewport — if scrollWidth is larger, something sticks out. It is a few lines of code, it almost never produces false positives, and it catches a genuinely common and highly visible defect.