Open fantasai opened 6 years ago
Just adding a couple common questions and our twitter discussion:
my use case - if i were to make this table and didnt want to use border-bottom or add (a few) extra 1px elements:
grid-row-gap-color: gray
might do it? i am definitely not the guy to ask about coming up with css specs haha
I understand the conflict between columns and rows, but i would only use one or the other myself.
another way to do it would be to style between named or numbered line markers.
i love that you are still willing to consider this, please keep it up!
@tsiq-swyx If you were to make that table, please, please use <table>
markup? :) Data tables should be marked up with data table markup.
Hi. Rachel Andrew kindly let me know about this open issue. I've put a Pen together which I hope is a relevant use case: Horizontal lines between CSS grid rows.
I believe allowing images of some form within the line gaps together with some way to inset them would cover all use cases.
Also, the name should be general enough to also cover horizontal rules. So it may be aligned to the gap
property.
So, one approach extending column-rule
s syntax could be
gap-rule: [ <'gap-rule-width'> <'gap-rule-length'>? ] || [ [ <'gap-rule-style'> ||
<'gap-rule-color'> ] | [ <'gap-rule-image'> ] ]
with gap-rule-width
being an extended version of <line-width>
gap-rule-width = <length-percentage> | thin | medium | thick
where the percentage refers to the width of the gutter.
gap-rule-length
would be used for insetting (or outsetting) the rule in the orthogonal direction to gap-rule-width
with an initial value of 100%
gap-rule-length = <length-percentage>
where the percentage refers to the length of the gutter.
gap-rule-style = <line-style>
gap-rule-color = <color>
being the equivalents for column-rule-style
and column-rule-color
.
And the gap-rule-image
would be defined as
gap-rule-image = <image> [ stretch | repeat | round | space ]{1,2}
where the repetition values work like for border-image-repeat
.
The rule is always centered horizontally and vertically within the gutter.
Examples:
gap-rule: 1px solid silver; /* equal to the existing column-rule: 1px solid silver; */
gap-rule: 2px 80% dotted blue; /* draws a 2px wide blue dotted line spanning 80% of the length of the gutter */
gap-rule: 10px calc(100% - 20px) url(rule.svg) /* draws a 10px wide and 10px inset stretched image */
Regarding spanning elements and gutter intersections, there may be another property specifying whether the rules cross the elements or each other or are interrupted. E.g. something like
gap-rule-interrupt: [ continuous | interrupt ]{1, 2}
allowing to control the horizontal and vertical interruption individually.
Examples:
gap-rule-interrupt: continuous; /* draws the rule(s) without interruption by spanning elements or crossing rules */
gap-rule-interrupt: interrupt continuous; /* draws the rule(s) with interruption in vertical direction but not in horizontal direction */
I'll try to come up with some visual representations of the examples above.
Sebastian
Here are the examples including their output:
gap-rule: 1px solid silver;
gap-rule: 2px 80% dotted blue;
gap-rule: 10px calc(100% - 20px) url(rule.svg)
gap-rule-interrupt: continuous;
gap-rule-interrupt: interrupt continuous;
Sebastian
Good stuff Sebastian.
My only observation is that because grid-gap
specifies the row gap first and the column gap optionally second, it is a bit odd for a property such as gap-rule-interrupt
to do the inverse: specify the column interrupt first and the row interrupt second.
There should be a consistent pattern.
@watershed Right, gap-rule-interrupt
should follow the gap
syntax, so first the row then the column.
Also, gap-rule-interrupt
may be included in the gap-rule
shorthand, so the syntax for it would then be like this:
gap-rule: [ <'gap-rule-width'> <'gap-rule-length'>? ] || [ [ <'gap-rule-style'> ||
<'gap-rule-color'> ] | [ <'gap-rule-image'> ] ] || <'gap-rule-interrupt'>{1,2}
So the full value to get the last example would be:
gap-rule: 1px solid silver continuous interrupt;
To allow to set the vertical and horizontal rules individually, the gap-rule
property could also be split up into row-gap-rule
and column-gap-rule
.
Sebastian
@fantasai Are there more use cases needed or anything else to push this forward?
Sebastian
It wasn't explicitly mentioned yet, but styling gaps should also apply to Flexbox layouts.
Sebastian
Hello,
This is my first post here.
What if it was instead possible to add more options to the current grid-gap
property while including @SebastianZ's idea?
Like grid-gap: 10px
, grid-gap: 10px 20px
, grid-gap: 10px solid black
, grid-gap: 10px 20px solid black
, grid-gap: 10px 20px url(image.png)
, grid-gap: 10px 20px solid red solid black continuous interrupt
.
What do you think ?
Note that grid-gap
got renamed to just gap
(and also grid-row-gap
and grid-column-gap
to row-gap
and column-gap
) in order to be also used in flexbox and multi-column layout.
The rule styles might be applied directly in the gap
property but this also brings some disadvantages. First, it would make the lengths ambiguous, because it mixes the sizes of the gaps with the width and length of the rule. Second, it requires you to always define both when you only want to overwrite one of them.
Sebastian
How is it possible to rename a css property? I mean, this will make incompatible many websites.
Having a look at the syntax of my last comment from December 2018, I realized that it missed the optional second interruption value. Therefore I've now added a {1,2}
behind it.
Sebastian
How is it possible to rename a css property? I mean, this will make incompatible many websites.
The properties with the grid-
prefix are still supported but marked as legacy names, see https://drafts.csswg.org/css-align/#gap-legacy.
Sebastian
Another Stack Overflow question popped up about this feature https://stackoverflow.com/questions/59899641/is-it-possible-to-draw-all-css-grid-lines-as-dotted-borders-or-outlines-if-js-i
Could gap-rule-interrupt
apply to individual cells? Or another property overriding the default set on the grid container. (Probably both would be needed, as well as doing something sane with nested grids and subgrids.)
@ByteEater-pl What are the use cases for having different values of gap-rule-interrupt
for specific grid cells or areas? Anyway, that would then need support for styling grid areas as discussed in #499.
Sebastian
OTOH roughly the same as for whole grids. Just worth killing another bird with the same stone if it turns out not to be much more work.
Anyway, that would then need support for styling grid areas as discussed in #499.
Not necessarily. There's usually at most one box slotted in a grid area. An if there are many, then document order or z-index
could be consulted. (And yes, it'll be another thing to consider when flow inside areas is allowed.)
Anyway, that would then need support for styling grid areas as discussed in #499.
Not necessarily. There's usually at most one box slotted in a grid area. An if there are many, then document order or
z-index
could be consulted. (And yes, it'll be another thing to consider when flow inside areas is allowed.)
Sure, it could work on the item level. Though basing the final display on document order or z-index
seems rather hacky to me and is potentially confusing to authors.
Sebastian
In the App of Alibaba Group, we have countless similar designs, and we hope to realize this feature in the specification as soon as possible.
In order to create this calendar with the lines demarcating each hour (and half hour in a lighter shade) we currently have to create 48 extra divs just for styling.
<div class="hour-border hour-0"></div>
<div class="half-hour-border half-hour-0"></div>
<div class="hour-border hour-1"></div>
<div class="half-hour-border half-hour-1"></div>
...
@jrjohnson That's a data table, not a grid-based layout; it should be using <table>
markup...
@fantasai I can understand why you'd say that, but when you start putting real events on a calendar and have to account for accessibility, performance, and responsiveness, we've found that it is impossible to make it work with a table. Using a grid allows us to build AT navigable markup while presenting a conventional calendar view at many different resolutions and as new events are added we don't have to re-calculate (and re-paint) inline markup for the entire table.
With some events:
I hope that additional context makes it easier to understand why I think this is a valid case for this feature. If there is more detail I can provide please let me know or if you're aware of a way to do this with a table I'd be thrilled to make that work, so please correct me if I'm missing that option.
For what it's worth, my proposal could also apply to tables, it just needs to be defined to also work together with border-spacing
(as long as it is not replaced by the row-gap
/column-gap
/gap
properties).
Sebastian
In general, this seems like a good feature to add since it addresses common existing use cases. If we can implement it as some kind of border or background rendering in the gutters (like column-rule
is today), then it should be fairly straight-forward to implement I think.
One could theoretically style the background on the parent if they wanted to apply the style @yisibl and @tsiq-swyx's usecases
@yisibl ahh yes thank you for the illustration!
I think it would be nice to have per-axis properties for this so that we can have independent styling for each axis. I think we can re-use the existing column-rule properties and just add corresponding row-*
properties. And then add a shorthand to specify both at the same time, e.g.
rule: <row-rule> [ '/' <column-rule> ]?
.
Regarding gap-rule-length
: it might be better to add a rule-inset
property instead of having to deal with percentages. Especially if we add an option to extend the rule to the length of the tracks or the length of the content box (which may be different as illustrated in this example), then it's probably easier to use an "indentation" rather than specifying a length.
Regarding gap-rule-interrupt
: this is nice, but might be a bit tricky to implement for images, especially if you want to stretch the image to the full rule length and slice pieces away, as opposed to rendering each segment as a separate image. I guess you could emulate it by using an opaque row-rule-image
that is as large as the row-gap
to simply hide the column-rule-image
by overlapping it (assuming the row rules renders on top). An alternative would be to add a property to control the extent explicitly, e.g. column-rule-extent: [ auto | content | segment ]
, for example:
I think that might be simpler to implement.
@fantasai I'm not sure I understand what you're referring too with "rules that can reasonably interact with spanning elements". Are you saying that rule segments that have a spanning item crossing it should be canceled? Including abs.pos. children? If so, does the rule start again at the gap start edge or at the next track start edge?
Regarding support for images: has there been any prior discussion on supporting that in the existing column-rule
properties? (I'm a bit surprised it isn't already supported and I'm wondering if there were any issues with it.)
Finally, I think all these properties should apply to all boxes that support gaps for consistency, so including flex containers too. (And between items in the masonry axis too, if this proposal is adopted.) (Updating the issue subject accordingly.)
I like the idea of rule
and rule-image
. There are many coupon styles in Chinese shopping websites, and there is usually a dotted line (or image) between them. It is not appropriate to use border to achieve it, its height is not 100%.So we still need an attribute to control the height of the rule?
However, I did not expect what to use for the top and bottom semicircles. The corner-shape property can only cut four corners, not the middle of the element.
So I can only implement it with the underlying CSS Houdini API: demo:
I think it would be nice to have per-axis properties for this so that we can have independent styling for each axis. I think we can re-use the existing column-rule properties and just add corresponding
row-*
properties. And then add a shorthand to specify both at the same time, e.g.rule: <row-rule> [ '/' <column-rule> ]?
.
Yes, having two properties for each axis is also what I mentioned in one of my later comments.
It would be ok to reuse column-rule
for that and add corresponding row-rule-*
properties. My earlier thought was to align the names with the gap-*
properties to make it obvious that they are related and also to allow to extend the column-gap
, row-gap
, and gap
properties to set the rule.
But of course that would also be possible without giving them a gap-*
prefix.
Regarding
gap-rule-length
: it might be better to add arule-inset
property instead of having to deal with percentages. Especially if we add an option to extend the rule to the length of the tracks or the length of the content box (which may be different as illustrated in this example), then it's probably easier to use an "indentation" rather than specifying a length.
One thought behind gap-rule-length
was to align it with existing properties, though I agree that defining an inset is easier to handle from an author's perspective. Percentages might still be acceptable, referring to the length of the tracks. (Letting them refer to the content box doesn't look desirable in my eyes.)
Regarding
gap-rule-interrupt
: this is nice, but might be a bit tricky to implement for images, especially if you want to stretch the image to the full rule length and slice pieces away, as opposed to rendering each segment as a separate image. I guess you could emulate it by using an opaquerow-rule-image
that is as large as therow-gap
to simply hide thecolumn-rule-image
by overlapping it (assuming the row rules renders on top). An alternative would be to add a property to control the extent explicitly, e.g.column-rule-extent: [ auto | content | segment ]
, for example:I think that might be simpler to implement.
Thank you for bringing that up! I didn't give gap-rule-interrupt
a deeper thought in regard of the extent of images before. I really like the idea of column-rule-extent
. And I think authors also rather expect the images to be separate like column-rule-extent: segment
does it instead of being sliced into pieces as gap-rule-interrupt
suggests.
There should also be an equivalent in the horizontal direction, i.e. row-rule-extent
.
It looks like @yisibl's use case would already be covered by column-rule-extent: segment
.
There's one more value that should be supported which is extending the image up to the center of the gaps.
That in combination with the suggested gap-rule-image
repetition values should make something like that possible:
Making the intersections fit like that probably requires more complex syntax and implementations around image slicing like for border-image-slice
and isn't needed for a first version of the feature, though it should be kept in mind when defining the syntax to make it future proof.
Finally, I think all these properties should apply to all boxes that support gaps for consistency, so including flex containers too. (And between items in the masonry axis too, if this proposal is adopted.) (Updating the issue subject accordingly.)
I totally agree that this should work for grid, flexbox and multi-column layout! And as I wrote before, it might even apply to table layouts (with some special handling).
Sebastian
It should look more like a background property, for example:
background-color = rule-color background-image = rule-image background-size = rule-size background-repeat = rule-repeat background-clip = rule-clip
On this basis can be further extended, eg: rule-style.
However, there should not be many similar properties to confuse developers.I think so: Whether column and row spacing or style rules can be described by the same attribute, such as rule, the corresponding row is row-rule, the column is column-rule, there should be no gap-rule, gap-row-rule,gap-column-rule, column-rule, etc., which will confuse the developer
Seems to me this feels more akin to border
than background
:
border-image-source
--> rule-image-source
border-image-slice
--> rule-image-slice
border-image-width
--> rule-image-width
border-image-outset
--> perhaps not a 1:1 here since this would always be center positioned in the gutterborder-image-repeat
--> rule-image-repeat
border-color
--> rule-color
I do like the ability to have gap-rule-interrupt
(or rule-interrupt
) as well. We'd back to specify direction with something like block
, inline
, or all
.
The CSS Working Group just discussed Styling gap
.
FYI, I've made a proposal to add image support for column rules in #5080.
Using Sebastian Zartner's diagrams of grid line intersection options in #5080, @mirisuzanne and I sketched out the following syntax proposal to handle segmenting:
column-rule-extent: span-skip | no-skip | span-break | corner-break
column-rule-extent
specifies how column rules are segmented. Each segment is drawn separately, and has its own inset and image application, if any.
no-skip
- extends across the grid, going behind grid itemsspan-skip
- extends across the grid, not drawn behind grid itemsspan-break
- spanning items split rule into individual segmentscorner-break
- split at every intersectionNote: In Flexbox, the cross-axis rules are always segmented between flex lines.
We thought it made more sense to split out handling of whether lines cross the gaps into a separate property, maybe the column-rule-inset
property @matspalmgren mentioned earlier:
column-rule-inset: nearest | center | farthest | <length>
column-rule-inset
specifies how far a column rule extends into (or recedes from) an intersecting gap (or the edge of the container).
nearest
- Segment not extend into the gap. Computes to zero.center
- Segment extends to the center of the gap.farthest
- Segment crosses the entire gap.<length>
- Segment intrudes by given length.(At the edge of a container, where there is no gap, a gap is assumed to exist for the purpose of calculating the rule's length. This ensures symmetry.)
The keywords might need some bikeshedding. And/or we might want rule-outset
instead of rule-inset
.
Putting it all together, we'd have the following syntaxes for gap styling (with row-/column-/unprefixed variants for each):
/* Existing Properties */
column-gap: normal | <length-percentage>
column-rule: <color> || <line-style> || <line-width>
column-rule-color: <color>
column-rule-style: <line-style>
column-rule-width: <line-width>
/* Proposed Properties */
column-rule-extent: span-skip | no-skip | span-break | corner-break
column-rule-inset: nearest | center | farthest | <length>
column-rule-image: <border image syntax but with only one axis>
rule-image-source: none | <image>
rule-image-slice: [ <number [0,∞]> | <percentage [0,∞]> ]{1,2}
rule-image-width: [ <length-percentage [0,∞]> | <number [0,∞]> | auto ]
rule-image-outset: [ <length [0,∞]> | <number [0,∞]> ]{1,2}
rule-image-repeat: [ stretch | repeat | round | space ]
(See also open questions in @SebastianZ's post, which are follow-up questions we'll need to answer.)
What do people think?
@fantasai @mirisuzanne I gave your suggested syntax some thought now and have some remarks and questions.
column-rule-extent: no-skip
? Implementation-wise it shouldn't be much different from span-skip
, I presume, though I wonder if it's actually needed as a separate value.column-rule-extent
and column-rule-inset
work together? Are they completely separate from each other or does column-rule-inset
require individual segments, i.e. column-rule-extent
to be span-break
or corner-break
?column-rule-inset: farthest
means that segments overlap each other, one ending at the gap end, one starting at the gap start. What's the use case for that?column-rule-inset
can be negative to recede from the gap, right?rule-image-outset
meant to work?Sebastian
Forgive me for coming into this discussion in the middle, I'll more thoroughly read all the replies a little later when I have more time.
Am I right in assuming this is intended to draw a line between gaps, but not apply to the gaps themselves?
I'm coming here from this discussion where I proposed a gap-fill
property, before I was made aware of this issue and gap decorations in general. If I'm understanding @Loirooriol correctly, the idea to apply a background color to gaps overlaps with the goals of this proposal.
My question is, would it be useful to apply a background to the gap and treat the *-rule
properties as the foreground?
-extent
and -inset
are good; I think it fills the functionality fully. I'd probably fiddle with the names a bit, but that's it.
The model, essentially, is that anything with gaps defines a collection of horizontal and/or vertical areas, plus intersection rects where they touch. The existing -rule properties define whether rules exist in the horiz/vert areas. At each intersection rect, a rule either stops (a break) or continues thru it to join with the rule on the other side; this is controlled by -extent
. Depending on the -rule and -extent properties, an intersection rect might contain none, one, or two (intersecting) rules.
-inset
only controls rule breaks; by default the break is right up against the edge of the intersection rect, but you can shift it in or out.
Hm, I do have a question about span-skip interactions, tho. Say you have a grid set up like:
A│ │C
─╯ │C
│C
─╮ │C
B│ │C
Assuming rules are drawn in both axises:
-extent: corner-break
A│ ┃ │C
─╯ ╹ │C
━╸ │C
─╮ ╻ │C
B│ ┃ │C
-extent: span-break
A│ ┃ │C
─╯ ┃ │C
━╸ ┃ │C
─╮ ┃ │C
B│ ┃ │C
-extent: span-skip
A│ ┃ │C
─╯ ┃ │C
━━━┫ │C
─╮ ┃ │C
B│ ┃ │C
-extent: no-skip
A│ ┃ │C
─╯ ┃ │C
━━━╋━│C
─╮ ┃ │C
B│ ┃ │C
Right?
The question is - what does span-skip
look like if only row-gaps are drawn? How far into the intersection area does it extend?
None?
A│ │C
─╯ │C
━╸ │C
─╮ │C
B│ │C
Half?
A│ │C
─╯ │C
━━━╸ │C
─╮ │C
B│ │C
All the way?
A│ │C
─╯ │C
━━━━━│C
─╮ │C
B│ │C
Or should we implicitly treat this like a break, and let -inset
take control?
(Note that this will have an effect on how we want to handle gap images; see my comment on 5080 about handling intersections better. Under the model I describe there, the choice I'm outlining here is between using mid+endcap for this intersection area, or using a 1-way intersection for it.)
My use case for this is a left-and-right view in landscape that becomes a top-and-bottom view in portrait – with a divider in the middle (think split screen on a phone). Currently I have to use border-right
in landscape, and switch to border-bottom
in portrait. I would prefer setting a gap rule so the line automatically adjusts depending on the flex-direction
.
<style>
#container {
position: absolute;
top: 0; bottom: 0; left: 0; right: 0;
display: flex;
}
.synced-panel {
overflow: scroll;
padding: 2em;
flex-basis: 100%;
}
.synced-panel:not(:last-of-type) { border-right: 2px solid #eee; }
@media screen and (orientation: portrait) {
#container { flex-direction: column; }
.synced-panel:not(:last-of-type) { border-right: 0; }
.synced-panel:not(:last-of-type) { border-bottom: 2px solid #eee; }
}
</style>
There's been a number of requests for styling grid gaps (gutters). We have a
column-rule
property from the multicol module we should probably try to re-use, but the styling requirements for grids are more complicated due to e.g. spanning elements, which we have to figure out what to do with.There's also styling requirements that apply to both multicol and grid that we aren't meeting. (E.g. having the rule start not flush with the top/bottom of the column boxes but somewhat inset, various fancier graphical effects than a simple “line”.)
Basic line rules that can reasonably interact with spanning elements is the top priority, but we should have some idea at what else we might need to accommodate in the future.
This is a placeholder issue to collect use cases and examples, so that we understand problems we need to handle before we try to design a solution. Please add suggestions/examples/ideas/drawings/background info/warnings/suggestions/anything else that seems like it might be helpful! While we're unlikely to handle 100% of all the graphic design capabilities the Internet can imagine, we should at least aim to handle the more common cases.