skip to content
Li Kang

Create, to Defy Entropy

CSS bug in Google Search’s pagination

A subtle layout bug in Google Search: When CJK text-wrapping meets float

/ 5 min read

Recently, I investigated an interesting layout bug in Google Search’s pagination component. I first noticed it a few months ago but thought it was caused by some Chrome extensions I had installed. Later, I set up a fresh browser profile and reproduced the issue, realizing it was a broader problem.

The bug specifically affects the Chinese version, where the “Next” link (下一页) wraps onto multiple lines unexpectedly. It looked like a simple CSS issue at first, but a deeper dive revealed some fascinating quirks involving CSS layouts and CJK (Chinese, Japanese, Korean) text rendering.

A Closer Look at the Bug

Let’s break it down. The “Next” link in the pagination component is made up of two parts:

  1. A logo image
  2. The localized text for “Next”

Here’s a simplified version of the HTML:

<td>
<a href="#next" style="display: block;">
<img src="next.png" style="float: left; display: block; width: 71px" />
<span style="display: block; margin-left: 53px;">下一页</span>
</a>
</td>

The issue comes from the float: left applied to the image, combined with the lack of a clear property on the text span. To fix it:

  • Remove float: left, or
  • Add clear: left to the span.

Real Question

Why does this bug only show up in the Chinese version? To figure that out, let’s look at how text wrapping behaves in different languages when the span text’s margin-left changed.

From this visualization, we can see:

  1. CJK and Latin text wrap differently.
  2. The span text first appears below the image, but as the margin-left increases, it shifts to the right.

CJK Text-Wrapping

CSS uses the overflow-wrap and word-break properties to control text wrapping behavior. Under the default values of these two properties, most languages break lines at spaces between words. However, CJK languages don’t rely on spaces as word separators, which allows line breaks to occur between any characters.

Why Not Japanese or Korean Versions?

This is where it gets even more interesting. Let’s take a closer look at the block-level span text in the HTML. Its previous sibling (the image) is floated, which means the image is removed from the normal content flow according to CSS rules. As a result:

  1. The span starts at the same position as the floated image.
  2. Its content aligns to avoid overlapping the float, meaning:
    • If there’s enough space beside the floated image, the content flows into the remaining space next to it.
    • If there isn’t enough space, the content moves to the next available line below the float.

But when is there enough space beside the floated image? This depends on the width of the parent container. In this case, the parent <a> tag is a block element inside a <td>, which means its width is content-based. Its width is determined entirely by the wider of its two children—the floated image or the span text.

With this understanding, the conditions for wrapping are clear: if the width of the span (including its margin-left) is larger than the floated image, and the gap is just enough to fit a character, the span may wrap around the image. In the Chinese version, the text 下一页 contains three characters, while the Japanese and Korean versions only have two. This subtle difference causes the issue to occur exclusively in the Chinese version.

Now, why does it matter that the span is a block-level element? Because as a block element, it respects the float and makes its content sit beside it or moves below it. If it were an inline-level element, it would try its best to flow inline next to the image, making the issue visible across all languages.

Why Did This Bug Last So Long?

Several factors make this bug tricky:

  1. Language-Specific Behavior: Localization introduces edge cases that might go unnoticed during English-centric testing.
  2. CJK-Specific Wrapping: The default wrapping rules for CJK languages differ significantly.
  3. Subtle Width Interactions: The bug occurs due to a perfect storm of:
    • More than two CJK characters,
    • Precise margin-left values, and
    • Floated image behavior.

What We Can Learn

This quirky bug teaches us some important lessons:

  1. Test with CJK Languages: Don’t assume layouts will work universally. Always test localized versions.
  2. Floats Are Tricky: Floats are kind of outdated. Use Flexbox or Grid for layouts when possible.
  3. Cultural Awareness Matters: Writing systems like CJK interact differently with CSS—don’t assume your layouts work universally.

One more thing

An Image Shown Misaligned Text

While examining the layout of the pagination component for this post, I noticed another issue: the page numbers and the “Next” text are slightly misaligned in CJK languages. It’s not a major problem, but for a platform like Google, even small details matter. The fix is simple—apply a unified line-height to the text.

This happens because CJK text often falls back to a different font family than Latin text. Since different fonts have unique vertical metrics, such as baseline and line box properties, the text can appear misaligned when displayed together without proper adjustments. The fix? Use a consistent font-family or explicitly set line-height.