Why Vertical Gradients Compress Worse in GIFs

Vertical gradients result in significantly larger GIF file sizes than horizontal gradients due to the interaction between raster scan order and the Lempel-Ziv-Welch (LZW) compression algorithm. Because GIF reads pixel data horizontally row by row, a horizontal gradient produces identical color sequences on every single line, allowing the LZW dictionary to compress subsequent rows into a few recurring tokens. Conversely, a vertical gradient shifts color values row by row, forcing the dictionary to constantly discard or rebuild sequences, which severely degrades compression efficiency.

Raster Scan Order in GIF Files

The GIF specification stores image data using a linear raster scan. The encoder reads pixels sequentially starting from the top-left corner, moving horizontally across the row to the right edge, and then dropping down to the start of the next line. This process converts a two-dimensional grid of pixels into a single, continuous stream of color indices.

Because data is read horizontally, the direction of visual patterns relative to the scan line directly dictates how repetitive the resulting data stream will be.

How LZW Compression Works

GIF relies on LZW compression, a lossless, dictionary-based algorithm. As the encoder processes the linear stream of pixel values, it identifies repeated sequences of bytes and assigns them short numerical codes.

The LZW dictionary starts with basic single-pixel values and dynamically builds multi-pixel sequences as it encounters them. The dictionary has a maximum capacity of 4,096 entries (using 12-bit codes). Once the dictionary fills up, the encoder either stops adding new strings or clears the dictionary entirely and starts over. High compression ratios depend on encountering the exact same multi-pixel sequences repeatedly throughout the stream.

Horizontal Gradients: High Pattern Repetition

In a clean horizontal gradient, color changes across the X-axis while remaining uniform down the Y-axis.

While encoding the first row, LZW registers patterns like [Color A + Color B] and [Color C + Color D]. When the encoder moves to the second row, it encounters the exact same sequence.

Very quickly, the dictionary builds entries that represent large segments of a row—or even an entire row—under a single code. By the third or fourth row, hundreds or thousands of pixels can be represented by just a handful of LZW codes, leading to exceptionally small file sizes.

Vertical Gradients: Constant Dictionary Invalidation

In a vertical gradient, color remains uniform across any single row, but changes as you move down the Y-axis.

While LZW can compress Row 1 efficiently by building run-length patterns of Color A ([A + A], [A + A + A]), none of those dictionary entries apply to Row 2. When the scan line drops to Row 2, the encoder must start building new strings for Color B from scratch.

This behavior causes two critical issues:

  1. Dictionary Exhaustion: The dictionary quickly fills with long runs of individual colors (AAAA, BBBB, CCCC) that are never used again after their specific row finishes.
  2. Frequent Resets: Once the 4,096-entry limit is hit with single-use data, the encoder must reset the dictionary, forcing the compression process back to short, inefficient bit codes.

The Amplifying Effect of Dithering

Because the GIF format is limited to a 256-color palette, gradients almost always require dithering to prevent harsh color banding.

Dithering introduces alternating pixel patterns to simulate intermediate shades. In a horizontal gradient, these dithered patterns still repeat consistently from line to line. In a vertical gradient, error-diffusion algorithms scatter noise across rows, eliminating both horizontal run-length redundancy and vertical pattern reuse. This introduces high-frequency variance into the pixel stream, maximizing file size.