Re: [csswg-drafts] [css-multicol] image support for column rules (#5080)

border-image uses a 9-slice to give you complete control over all the relevant changeable areas - the four corners, and the four stretchable/repeatable sides. Using these 8 areas, you can do fancy things like scrollwork; the syntax was explicitly designed to allow these sort of uses.

But rules in a grid have a different set of areas - they've got only two stretchable/repeatable bits (horizontal and vertical), but *seventeen* possible fixed images - the four endcaps (top, bottom, left, right), then the four 1-way intersection, the four 2-way intersections, the four 3-way intersections, and the single 4-way. Only using 6 regions (row-* and column-* each specifying 3) doesn't account for any of the intersection areas.

We do have the advantage that all the missing intersection regions are the same size, so specifying them is potentially relatively easy, with a separate image that gets implicitly sliced into 13 regions (4 1-way, 4 2-way, 4 3-way, 1 4-way). We can just say they must be stacked vertically, for instance. This would be provided by a separate property from the row-gap-image and column-gap-image; if it wasn't specified, you would just overlay the repeat bit of the row and column images in some way.

--------

I also don't think we need the full complexity of border-image. It's designed in a slightly funky way to deal with the fact that border-width is layout-affecting, but the border-image might want to be smaller or larger than that border region, and extend both further in or further out than the inner/outer border edges. Gaps have a much simpler sizing model to deal with.

On the other hand, we have a physical/logical mismatch with gaps that doesn't exist with borders. Borders are specified physically (you can now use logicals, but physical is always an option) and the border-image directions are physical as well. But gaps are *inherently* logical; we'd have to autorotate images to make that work, which is (a) somewhat weird, and (b) favors one orientation as the "default"; vertical writing modes would have to author a "sideways" image which is then rotated into the actually-used orientation.

Both of these suggest that we actually need do something relatively different from border-image to get gap images.

Here's an initial sketch:

```
gap-image-x-source: none | <image>
gap-image-x-slice: [ <number> | <percentage> ]{1, 2}
gap-image-x-width: <length-percentage> | auto
/* analogous gap-image-y-* properties */

gap-image-cross-source: none | <image>
gap-image-cross-size: [ <length-percentage> | auto ]{1,2}
```

The `gap-image-x/y-*` properties define the stretchy part of the gap line, and the end caps.

* `-source` is self-explanatory.
* `-slice` specifies how to slice the image into 3 pieces (an endcap, a mid area, and an endcap), along the given axis. If only one length is given, it measures equally from either side (that is, it's `(100% - len)`) (initial `0`)
* `-width` sets the size of the image, perpendicular to the given axis. `auto` uses the image's natural size. %s are relative to the gap size. (initial `auto`)

The `gap-image-intersection-*` properties set the images used for when gap rules cross. The image is automatically sliced into 13 equal vertically-stacked sub-images, used for the 4 1-way intersections, 4 2-way intersections, the 4 3-way intersections, and the 4-way intersection. The size sets the size: again, `auto` uses the natural size of the image, and %s are relative to the appropriate gap width.

These interact with the existing+proposed gap-rule properties:
* `*-rule-extent` determine whether you use crosses or endcaps, depending on whether there's a break, a skip, or neither.
* `*-rule-inset` determines the size of the gap image area along the axis.

I think, then, that the endcap images are used against breaks, with the mid image between them. When gaps intersect without a break, the mid image goes up to the edge of the intersection, and the appropriate `-cross-` image is used inside the intersection area, depending on what skip behavior is being used, and how the gaps are intersecting. (In a normal grid, `no-skip` always uses the 4-way intersection, while `span-skip` can use any of them, depending on which sides of the intersection are spanned. In a flexbox/masonry, I think they'd *only* use the 3-way intersections?)

(Ugh, I didn't consider that intersection areas can overlap in flexbox and masonry. Not sure what to do about that. Maybe they just plain overlap, and you shouldn't use images that would look bad in that situation when using masonry or flexbox gap images.)

(If you only use a gap image in one axis (x or y, not both), then I think we only use the cross images when you'd trigger a skip in that axis. Otherwise we just stretch across the intersection area. That is, consider a horizontal multiline flexbox. With an `-x-image`, filling the flex-line gaps, you'd never trigger a skip, so it's always either one continuous rule, with one endcap on each end, or a bunch of rules triggered by breaks, each still only made of endcaps and stretch. With a `-y-` image, on the other hand, it'll be a bunch of 1-way intersections as the item-gap images extend into the line-gap intersection area.)

Gap images are always centered in the appropriate way; horizontal/vertically for the `-x-` and `-y-` images, and centered in both axises for the `-cross-` images.

-- 
GitHub Notification of comment by tabatkins
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/5080#issuecomment-1526585163 using your GitHub account


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

Received on Thursday, 27 April 2023 22:04:13 UTC