How Google Photos Delivers Smooth 60fps Scrolling with Advanced Layout Tricks

This article explains the technical challenges Google Photos faced—such as handling millions of images, preserving aspect ratios, enabling instant navigation, and maintaining 60fps scrolling—and details the algorithms, data chunking, justified layout, and performance optimizations that make the web UI fast and fluid.

AutoHome Frontend
AutoHome Frontend
AutoHome Frontend
How Google Photos Delivers Smooth 60fps Scrolling with Advanced Layout Tricks

Why It Was Hard

Google Photos needed to support massive photo libraries (hundreds of thousands of images per user) while keeping every thumbnail’s aspect ratio, allowing rapid scrubbing to any position, loading tens of thousands of photos at 60 fps, and providing an instantaneous feel.

1. Scrubbable Photos

Instead of traditional pagination, the team uses infinite scrolling with pre‑allocated space for each content block. Only minimal metadata (photo count per block) is sent initially, reducing payload size. The layout predicts the height of each block using simple calculations:

const columns = Math.floor(viewportWidth / (thumbnailSize + thumbnailMargin));
const rows = Math.ceil(photoCount / columns);
const height = rows * (thumbnailSize + thumbnailMargin);

Photos are grouped by month (e.g., "2014_06": 514) so the client can reserve space before actual images arrive. When a block loads, any height discrepancy is corrected by shifting subsequent blocks, a process that completes in a fraction of a frame.

It may not be perfectly accurate, but the approximation is sufficient for smooth scrolling.

2. Justified Layout

The layout allows rows to have different heights while keeping each photo’s aspect ratio. The algorithm scales photos to a common row height, accumulates widths, and when the total exceeds the viewport width, it rescales the row to fit exactly. Sample code:

let row = [];
let currentWidth = 0;
photos.forEach(photo => {
  row.push(photo);
  currentWidth += Math.round(maxHeight / photo.height) * photo.width;
  if (currentWidth >= viewportWidth) {
    rows.push(row);
    row = [];
    currentWidth = 0;
  }
});
if (row.length) rows.push(row);

To find the optimal break points, the team adapts the Knuth‑Plass line‑breaking algorithm, treating each photo as a "box" and the gaps as "glue" with penalties for undesirable breaks. The algorithm builds a directed acyclic graph of possible breaks, assigns a badness score based on stretch/shrink ratios, and computes the shortest path in linear time to select the best grid.

Considering millions of possible layouts, the algorithm still runs in a few milliseconds for typical photo counts.

3. 60 fps Scrolling

Maintaining 60 fps means each frame has only ~16 ms; after browser overhead, the app has ~10 ms for its work. The team minimizes DOM size by rendering only visible photos and recycling off‑screen elements. Content is divided into sections, segments, and tiles, each absolutely positioned, so moving a block only requires updating its top value.

CSS contain: layout is used to isolate layout calculations, and requestAnimationFrame batches updates to avoid layout thrashing. Long‑running code is split across workers or async fetches, and batch network requests fetch ~10 thumbnails at a time.

4. Instantaneous Feel

To mask loading latency, low‑resolution placeholders (≈ 1 KB) are shown first, then swapped with high‑resolution images using opacity fades. The placeholders are sized to match the final layout, so scrolling never encounters empty gaps. When a user clicks a thumbnail, the high‑resolution image loads in the background while a blurred version animates into place.

Additional tricks include pre‑loading in the scroll direction, adjusting placeholder resolution based on scroll speed, and using CSS gradients to render empty tiles without extra network requests.

Results

The combined techniques keep the UI responsive: most interactions stay at 60 fps, occasional frame drops only occur during heavy layout events (e.g., inserting a new section). Monitoring tools track frame rates, load times, and other metrics, guiding continuous performance improvements.

Conclusion

Google Photos’ smooth experience stems from careful data chunking, sophisticated layout algorithms, aggressive DOM minimization, and visual tricks that hide latency. These engineering solutions illustrate how large‑scale web photo galleries can achieve both visual fidelity and high performance.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Frontendalgorithmlayoutscrollingphotos
AutoHome Frontend
Written by

AutoHome Frontend

AutoHome Frontend Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.