How Safari Implements CSS Grid and Subgrid for Web Layouts

This article provides a technical breakdown of how the Safari web browser implements CSS Grid and CSS Subgrid to render complex two-dimensional webpage layouts. It examines the underlying mechanics of Safari's WebKit rendering engine, detailing how the browser parses grid properties, executes the track sizing algorithm, and manages layout calculations. Additionally, it explains how Safari resolves nested layout dependencies through CSS Subgrid and optimizes rendering performance for modern web applications.

The WebKit Rendering Engine and RenderGrid

Safari relies on the open-source WebKit layout engine to convert HTML and CSS into pixels on the screen. When Safari encounters an element with display: grid or display: inline-grid, WebKit instantiates a specific C++ class in its render tree called RenderGrid.

The RenderGrid object is responsible for managing the two-dimensional coordinate system. Unlike traditional block or inline layouts that process elements sequentially along a single axis, RenderGrid evaluates both rows and columns simultaneously. It achieves this by dividing the layout process into distinct phases: item placement, track sizing, and alignment.

Step 1: Grid Item Placement

Before Safari can calculate the size of the grid, it must know where every child element (grid item) belongs. WebKit constructs an internal representation of the grid called the Grid Matrix.

  1. Explicit Placement: Safari first places items that have defined coordinates (using properties like grid-column-start or grid-row).
  2. Implicit Placement: For items without explicit coordinates, Safari runs the "grid auto-placement algorithm." WebKit iterates through the unoccupied cells in the Grid Matrix, placing items according to the grid-auto-flow property (either row by row, column by column, or filling in gaps using the dense keyword). If there are not enough defined tracks to hold the items, WebKit dynamically generates implicit tracks to accommodate them.

Step 2: The Track Sizing Algorithm

Once all items are mapped to the Grid Matrix, Safari executes the CSS Grid Track Sizing Algorithm to determine the exact pixel dimensions of every row and column. WebKit processes tracks in the following order:

  • Fixed Tracks: Columns and rows defined with absolute units (like pixels) or percentages that can be immediately resolved against the grid container’s size are calculated first.
  • Intrinsic Tracks: Tracks using keywords like min-content, max-content, or auto require Safari to measure the actual content inside the grid items. WebKit queries the child elements for their minimum and maximum intrinsic sizes and expands the tracks accordingly.
  • Flexible Tracks (fr): Finally, Safari calculates tracks using the fractional unit (fr). WebKit takes the remaining available space in the grid container—after subtracting fixed tracks, intrinsic tracks, and grid gaps—and distributes it proportionally among the flexible tracks.

To handle two-dimensional dependencies (where the width of a column might affect the height of text in a row), WebKit executes a multi-pass layout cycle. It calculates column widths first, constrains the grid items to those widths to determine how content wraps, and then calculates the resulting row heights.

Implementing CSS Subgrid

Introduced in Safari 16, CSS Subgrid allows a nested grid item to adopt the tracks of its parent grid container. Without Subgrid, nested grids operate as entirely independent layout contexts, making it impossible for grandchild elements to align with the main parent grid based on content size.

When Safari encounters grid-template-columns: subgrid or grid-template-rows: subgrid on a child RenderGrid object, it alters the standard layout boundary rules:

  1. Shared Sizing Context: The subgrid does not run its own independent track sizing algorithm for the subgridded dimension. Instead, it binds its tracks directly to the parent RenderGrid’s tracks that it spans across.
  2. Hoisting Grandchild Metrics: During the intrinsic sizing phase, WebKit "hoists" the sizing requirements of the subgrid's children up into the parent grid's calculation. The parent grid treats the subgrid's items as if they were its own direct children for the purpose of calculating min-content, max-content, and auto track sizes.
  3. Accounting for Box Model Offsets: A subgrid can have its own margins, borders, and padding, as well as its own custom gap sizes. Safari’s engine calculates the difference between the parent's gap and the subgrid's gap, alongside the subgrid's box-model edges. It then subtracts these values from the intrinsic space contributed by the subgrid's edge items, ensuring the nested items align perfectly with the outer tracks without overflowing.

Layout Optimization and Caching

Calculating two-dimensional layouts—especially with deeply nested subgrids—is computationally expensive. To maintain 60-frames-per-second (or 120fps on ProMotion displays) scrolling and animation performance, Safari employs aggressive caching strategies within WebKit:

  • Intrinsic Size Caching: Measuring text and images is the slowest part of grid layout. Safari caches the min-content and max-content sizes of grid items. If the viewport resizes, Safari re-runs the track sizing math using the cached content metrics rather than re-measuring the DOM nodes, provided the content itself hasn't changed.
  • Dirty-Bit Tracking: WebKit uses a system of "dirty bits" in the render tree. If a single grid item changes its content, Safari marks only that specific node and its immediate track dependencies as "dirty," preventing a full recalculation of the entire webpage layout.

Developer Tooling Integration

To help developers visualize this implementation, Safari includes a dedicated Grid Overlay tool within the Web Inspector. This tool hooks directly into the RenderGrid C++ objects, extracting the final computed values of the Grid Matrix. It renders visual lines over the webpage showing explicit tracks, implicit tracks, grid gaps, and extended subgrid lines, reflecting the exact mathematical boundaries WebKit used to paint the layout.