[csswg-drafts] [css-gaps-1] Gap Intersection Points -> Segment Endpoints (#13366)

kbabbitt has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-gaps-1] Gap Intersection Points -> Segment Endpoints ==
This issue is an explanation and discussion touchpoint for changes being drafted in [PR 13299](https://github.com/w3c/csswg-drafts/pull/13299/changes).

-----

One thing we wanted to enable in Gaps 1 is allowing decorations to respond to conditions such as spanning items in Grid. Rather than having decorations run all the way across the grid and "beneath" spanning items, an author might want decorations to terminate in places where spanners form visible T intersections. Contrast the following two examples:

<img src="https://drafts.csswg.org/css-gaps-1/images/example-break-none-grid.png">

<img src="https://drafts.csswg.org/css-gaps-1/images/example-break-spanning-item-grid.png">

Currently, to handle this, the spec has a concept called [Gap Intersection Points](https://drafts.csswg.org/css-gaps-1/#gap-intersection-point):
>A gap intersection point is defined to exist in each of the following locations:
>
> * The center of the start or end edge of a [gutter](https://drafts.csswg.org/css-align-3/#gutter).
> * The center of an intersection between gaps in different directions.

In the examples above, the Gap Intersection Points are placed as follows:

<img src="https://drafts.csswg.org/css-gaps-1/images/example-gap-intersection-grid.png">

This definition seems natural for Grid at first, but it ends up being awkward in other layouts. https://github.com/w3c/csswg-drafts/issues/12784 has the best examples of this. Whereas Grid is structured as a single 2D container, wrapped Flex and Multicol layouts are structured in two layers: a flex line or multicol line contains a set of boxes which can be separated by gutters, and these line containers are themselves optionally separated by their own gutters. Flex structurally is this:

<img src="https://private-user-images.githubusercontent.com/20029735/493063077-34fc15fe-d0a8-4a15-9432-99d928e541d0.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Njg2NzY5NzUsIm5iZiI6MTc2ODY3NjY3NSwicGF0aCI6Ii8yMDAyOTczNS80OTMwNjMwNzctMzRmYzE1ZmUtZDBhOC00YTE1LTk0MzItOTlkOTI4ZTU0MWQwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAxMTclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMTE3VDE5MDQzNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTkwNjg0ZWIwZWZiMjIxOTllNTFhMGU3MzMyMThjM2Y0Njc4ZWQwODczMmY4NWE3NGU5MTE5Yzg3N2EwYmY4MWQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.fyhkBA4NP1BHaydGdbwW84HMzbCYnxWPZ6_DRgZoX5c">

But Gap Intersection Points would call for this:

<img src="https://private-user-images.githubusercontent.com/20029735/493062462-b7a8c31e-dfeb-419d-b652-9f3a538e0f9b.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Njg2NzY5NzUsIm5iZiI6MTc2ODY3NjY3NSwicGF0aCI6Ii8yMDAyOTczNS80OTMwNjI0NjItYjdhOGMzMWUtZGZlYi00MTlkLWI2NTItOWYzYTUzOGUwZjliLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNjAxMTclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjYwMTE3VDE5MDQzNVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWVkNzYwNWFiZjA5YmNhOGYzZTFhNDYwMTExYTdmMTViOWEyODFkMjVjOTZkMjVjMmRjMDRlY2VjNTc0ZTQwOGMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.fpOUxAvwED9hYR8g1h5t4-zVyUzP-_Rt32084wtheuw">

Which creates some tension in the mental model. This is exacerbated by the fact that we've seen cases where authors create layouts that resemble grids but actually use Flex, for example https://github.com/w3c/csswg-drafts/issues/12602#issuecomment-3451771895:

<img src="https://private-user-images.githubusercontent.com/2784308/506071191-5fd28f67-aa16-4590-87a7-4ff110defba0.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Njg2NzcwNzksIm5iZiI6MTc2ODY3Njc3OSwicGF0aCI6Ii8yNzg0MzA4LzUwNjA3MTE5MS01ZmQyOGY2Ny1hYTE2LTQ1OTAtODdhNy00ZmYxMTBkZWZiYTAucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDExNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAxMTdUMTkwNjE5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZDVjMjAzOWU2ZDhjZmJhODAyZjM1ODY4OGNmMDdhYWI0YzgxZWQwM2Q1NDMyODA5ZTI1ZTJmODY5ODZkYThmOCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.A4blc0gZlSdADM7X6G-5etj4QqcxMAurp89JO8o5PHE">

-----

Several of us discussed these issues at TPAC last year (see https://github.com/w3c/csswg-drafts/issues/12784#issuecomment-3514411109) and came up with a different mental model for handling these cases. Instead of Gap Intersection Points, we define **Segment Endpoints** approximately as follows (details under discussion in the PR linked above):

> * Bounds of a Gap: For each gap, endpoints are created at its two bounds:
>   * At the start of the gap, a <a>start segment endpoint</a> is created.
>   * At the end of the gap, an <a>end segment endpoint</a> is created.
> * Within a Gap: When a cross/perpendicular gap touches a given gap (either overlapping it, or abutting it without overlapping),
>    two endpoints are created which align with the boundaries of the cross/perpendicular gap:
>    * The earlier boundary creates an <a>end segment endpoint</a>.
>    * The later boundary creates a <a>start segment endpoint</a>.

The Grid example at the top of this comment would result in segment endpoints as follows; start endpoints in cyan and end endpoints in magenta:

<img src="https://raw.githubusercontent.com/jav099/javier-gaps-1/578bf9607c5858804187c20dabc22fed9330a469/css-gaps-1/images/example-grid-segment-endpoints.png">

In Flex we get the following:

<img src="https://raw.githubusercontent.com/jav099/javier-gaps-1/578bf9607c5858804187c20dabc22fed9330a469/css-gaps-1/images/flex-and-segment-endpoints.png">

Multicol with and without spanners:

<img src="https://raw.githubusercontent.com/jav099/javier-gaps-1/578bf9607c5858804187c20dabc22fed9330a469/css-gaps-1/images/multicol-gap-decoration-segments.png">

<img src="https://raw.githubusercontent.com/jav099/javier-gaps-1/578bf9607c5858804187c20dabc22fed9330a469/css-gaps-1/images/multicol-gap-decoration-segments-2.png">

Note that this change is largely just a shift in the mental model and does not necessarily affect implementation. However, this shift unlocks a couple of powerful simplifications:

1. Grid, Flex, and Multicol layouts that look identical visually produce the same set of reference points for drawing decorations. This makes for more consistent expectations and behaviors when the same set of parameters (decoration break settings, inset values) are applied to different layouts.
2. Intersection points had this quirk where the location of the intersection point corresponded to an inset value of 0 for edge intersection points but -50% (i.e. half the width of the crossing gap) for interior intersection points. With segment endpoints, the location of the segment endpoint consistently maps to an inset value of 0.


Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/13366 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Saturday, 17 January 2026 19:44:59 UTC