w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.49k stars 660 forks source link

[css-grid] Control size of individual gutters independently #1659

Open tabatkins opened 7 years ago

tabatkins commented 7 years ago

Thread starting here asks for the ability to manually control gutter sizes, so they can be different sizes in different spots.

Right now, the only way to do so is to create it as a track, and then either explicitly avoid placing according to that track, or use a dummy element to fill that track (so auto-placed items avoid it, tho this means they can't span across it either).

There's some suggestions in the thread to extend the grid-gap syntax to allow multiple lengths, interpreted as a repeat pattern.

I'd prefer building this into the grid-template syntax. We already have a place in the syntax for line names, which live in the gutter between the tracks; we can throw in a gap(<length>) function as well, which can only be put between tracks, and which overrides the grid-gap property. (That is, grid-gap sets the default gap size, but you can manually override it.)

Nokel81 commented 7 years ago

My only concern with having this be a part of grid-template is that that requires the explicit naming of the sub objects. The benefit to the pattern based approach is that the contents of the grid can be left "unclassified"

praveenpuglia commented 7 years ago

How does the grid-template syntax address the repetition of a pattern for gutters?

Example - I need 12 columns with a repeating grid-gap pattern of 1rem and 2rem and all my column names remain [col] with all tracks being 1fr.

It would be amazing if we could do something like this without breaking the existing syntax.

.container {
  display: grid;
  /*Because obviously you can't repeat the pattern 11 times or 6 times 
  and say discard the values that go into it. 
  So this repeat function just tries to repeat those length values as long as 
  it can and the first argument isn't a <number>*/
  grid-gap: repeat(1rem, 2rem)  3rem;
}

Here, the grid-column-gap has a pattern of 1rem and 2rem and we get 3rem gutter on rows.

Didn't put a lot of thoughts into parsing so not sure how many things this might break.

Nokel81 commented 7 years ago

If repeat accepted any number of values I would be completely for this solution as long as using it just for columns of rows was also allowed

praveenpuglia commented 7 years ago

@Nokel81 I updated my answer to include how this new repeat syntax would work

jhpratt commented 7 years ago

Another option is to do grid-gap: 1rem 2rem / 3rem. Not sure on the pros and cons of the two options implementation-wise, though.

Nokel81 commented 7 years ago

What do you mean by by the first argument isn't a */?

Nokel81 commented 7 years ago

@jhpratt I would prefer the have it act like a function so that it is easier to read that it is actually repeating

praveenpuglia commented 7 years ago

@jhpratt - that syntax would be really simple but doesn't convey anything about repetition. A repeat syntax makes it really clear that it has to be repeated.

@Nokel81 Right now, the repeat syntax takes a number as first arguments to figure out how many times it needs to repeat. I skipped the auto-fill keyword which might solve my issue too. So the updated syntax will be like,

grid-gap: 3rem / repeat(auto-fill, 1rem 2rem);

I have now included the slash to make sure we understand the separation for columns and rows. Also, in grid-gap row comes before column so i reversed the order.

Nokel81 commented 7 years ago

Yes, having auto-fill would be a must because of the auto columns/rows in grids. This is nice and explicit, it does what I believe it should be able to be done and it should work with each direction individually. Lastly, it wouldn't overlap with the current spec because it is a function

rachelandrew commented 7 years ago

I'd generally prefer having it as part of the grid-gap properties instead of or in addition to grid-template, if only because a complex grid-template setup is something I find people struggle with when I'm teaching this stuff.

We have other stuff that accepts a track listing (eg. grid-auto-rows) so it would be consistent to add that capability here too.

rachelandrew commented 7 years ago

@jhpratt I'm perfectly capable of teaching it ;) what I am observing is where people learning get confused. As I think that is useful data in terms of designing stuff people have to use.

SebastianZ commented 7 years ago

Adding this to grid-template limits its usage to explicit grids. Though I assume people may also like to apply different gaps to implicit grids.

Non-the-less, the solutions are non-exclusive, i.e. there might be some way to specify the gaps for the explicit grid, which will either be overwritten by grid-gap or grid-gap then defines the gaps for the implicit grid. (Or there might be some switch that controls to what grid-gap applies.

Sebastian

Nokel81 commented 7 years ago

One question that needs to be answered is what the auto gap would be if auto-fill is not used. Or would it be required?

Nokel81 commented 7 years ago

Since I am new to this, how does something like an issue move forward in the discussion of adding it to the standard? I presume it has to go to one of the meetings.

rachelandrew commented 7 years ago

Discussing it here is the first step, things posted here will be considered when Level 2 is discussed and when something is discussed it gets updated here so you can read the log of the conversation.

Nokel81 commented 7 years ago

Is there a known time frame for when specific levels for certain items will be discussed at the contributor level?

rachelandrew commented 7 years ago

If you are interested in how the CSS WG works then there is information available on that here http://fantasai.inkedblade.net/weblog/2011/inside-csswg/

There aren't specific time frames for specifications, but discussions here are valuable and also demonstrate author interest in a feature.

tabatkins commented 7 years ago

My only concern with having this be a part of grid-template is that that requires the explicit naming of the sub objects. The benefit to the pattern based approach is that the contents of the grid can be left "unclassified"

No, it doesn't; what makes you assume that? Grid-template is the shorthand for the rows/columns/areas properties; are you thinking that it's just for grid-template-areas?

How does the grid-template syntax address the repetition of a pattern for gutters?

It doesn't, but I wasn't aware of a use-case presented that wants a repeated pattern of different gutters between implicit tracks. Tho hm, even if you grouped each "set" of things into a subgrid, you'd still need to establish the gutters on the outer grid, which requires a repeating pattern.

Example - I need 12 columns with a repeating grid-gap pattern of 1rem and 2rem and all my column names remain [col] with all tracks being 1fr.

Ah, this is explicit grid. Then it'd be:

grid-template-columns: repeat(6, [col] 1fr [col gap(1rem)]  1fr [col gap(2rem)] )

As opposed to using an explicit pattern in grid-column-gap:

grid-template-columns: repeat(12, [col] 1fr [col])
grid-column-gap: 1rem 2rem;
Nokel81 commented 7 years ago

Yes I was think of only grid-template-areas though I always seem to use grid-template-columns and grid-template-rows. I still think that the repeat() function in grid-gap is the cleanest solution and should cover all use cases (including individually changing gaps)

Nokel81 commented 6 years ago

Any new information on when this might be discussed?

I think that the best syntax would be

grid-column-gap: repeat(1 rem, 0 rem, 2 rem, 0 rem);

Where the pattern is repeated.

One problem I do have is that you might want to have a fixed number of fixed widths and then have it repeating.

Here there could be the following syntax:

grid-column-gap: group(fixed(1 rem, 5), repeat(1 rem, 0 rem), fixed(2 rem, 3))

This syntax means the first 5 gaps have a width of 1rem, the last 3 gaps have a width of 2rem and the intervening gaps are switching between a width of 1rem and 0.

With this syntax it can be group(fixed(), repeat()), or group(fixed(), repeat(), fixed()), or group(repeat(), fixed()), or repeat().

If there are less gaps then there are defined in the supplied fixed then the widths from the first are prioritized

fantasai commented 6 years ago

I'm proposing we defer this issue to Level 3. I want to see how far we can get with a combination of margins and subgrid, first.

Ericnr commented 5 years ago

I've been discouraged from using grids exactly because this is not yet possible. Would be great to see individual gutter sizes added.

Amerlander commented 4 years ago

I would use this too.

At the moment I help myself with using columns which are left empty and just giving the space, but this only works, if the wider gap has to be a multiple wide of the regular ones:

.parent {
display: grid;
grid-template-columns: repeat(4, 1fr) 0px repeat(12, 1fr)
  0px repeat(12, 1fr) 0px repeat(12, 1fr) 0px repeat(12, 1fr);
grid-template-rows: repeat(5, 2rem);
grid-column-gap: 4px;
grid-row-gap: 4px;
}

I would prefer to be able to do:

.parent {
display: grid;
grid-template-columns: repeat(4, 1fr) repeat(12, 1fr)
  repeat(12, 1fr) repeat(12, 1fr) repeat(12, 1fr);
grid-template-rows: repeat(5, 2rem);
grid-column-gap: group(fixed(4px 4px 4px), repeat(8px 4px 4px 4px 4px 4px 4px 4px 4px 4px 4px 4px))
grid-row-gap: 4px;
}

Since this will only result in the grid columns I really use. Subgrids doesn't seem to work for me, since they would limit the placement of child elements to each subgrid, but I need to be able to place like grid-column: 2 / 24;. This is possible in the code I actually use, but I also have to keep the 'blind' columns in mind when counting and I have to worry about 'losing' an element by placing it in a blind column like grid-column: 5 / 6.

https://codepen.io/amerlander/pen/abzXrLm grafik

OliverJAsh commented 4 years ago

This would also be very useful for flexbox, since now gap applies to that as well.

odil-io commented 2 years ago

I was looking for something similar, designers not always respect using actual grids and thats OK, but that means different row-gaps and different column-gaps.

I'm all for the gap: repeat(3, 1fr); method, it's almost self-explanatory.

stephenmcghee commented 1 year ago

Any updates on this request? It is definitely my most wanted CSS feature.

My use cases:

  1. Instead of using margin/padding to space out elements (for eg. on an H2, p, div), we could almost eliminate them by controlling individual gutters/gaps. ie. row-gap: 1.5rem 2rem 5rem; I find myself having to use both margin and gaps to space out elements the way I want, which seems a bit messy.

  2. There are certain grid lines I may not want gaps on, as it can affect the overall width/height of a layout. If we could define individual gaps like: column-gap: 0 repeat(2, 1rem) 0; that would be a game changer.

tabatkins commented 1 year ago

I'll note that variable-sized gaps directly impacts our ability to do gap images (#2748) in anything remotely similar to a border-image style. I think it's an either/or proposition.

To expand on this, border-image requires specifying 4 stretchable/tileable images, one for each side because the sides can be different sizes. These four sides intersect at four corners, so you need 4 corner images as well. (Conveniently, we can combine these 8 images into a single image that we slice up.)

Gap images will require 6 images for the "straight" sections - two endcaps and one stretchable/tileable part each, for the two axises. Then you need images for the intersections as well - I think you end up needing 17 to fully cover the intersection possibilities.

If gaps can vary in size, tho, the number of potentially needed images blows up multiplicatively, and the syntax space for assigning the images to particular gaps gets real funky.

SebastianZ commented 1 year ago

I'll note that variable-sized gaps directly impacts our ability to do gap images (#2748) in anything remotely similar to a border-image style. I think it's an either/or proposition.

I claim that variable-sized gaps and gap images can work quite well together. And we already need to solve this, anyway, because horizontal and vertical sizes can already differ.


To expand on this, border-image requires specifying 4 stretchable/tileable images, one for each side because the sides can be different sizes. These four sides intersect at four corners, so you need 4 corner images as well. (Conveniently, we can combine these 8 images into a single image that we slice up.)

Gap images will require 6 images for the "straight" sections - two endcaps and one stretchable/tileable part each, for the two axises. Then you need images for the intersections as well

@MatsPalmgren's proposed spec., we sticks with 6 images. Though it reuses the end caps for the intersections.

I think you end up needing 17 to fully cover the intersection possibilities.

I wonder how you get those 17. 6 images plus 2 intersection images are 8. Or if you want to, you could require another stretchable/tileable image between the intersection and the end cap, then you'd have 10 in total.


Anyway, the different proposals related to gap images already define a thickness for them. So the width of the gap and the width of the image can be set individually and they work independently from each other. Mats' spec. has an animated example illustrating that.

Also, here's an example how variable-sized gaps and gap images could look (please don't judge my painting skills, it's just for illustration):

Grid with variable-sized gaps and gap images

If we want the gap sizes and image sizes to work together, we could define a way to let the rule width be influenced by the gap width. In that case, the different images would need to be stretched or squeezed in the cross-axis to the rule depending on the gap's width. Having said that, I'm not sure whether there are any use cases for such a behavior.

Sebastian

tabatkins commented 1 year ago

And we already need to solve this, anyway, because horizontal and vertical sizes can already differ.

Yes, the fact that vertical and horizontal sizes can differ is why you need 6+13 images in total to duplicate the power of border-image for gap images.

@MatsPalmgren's proposed spec., we sticks with 6 images.

Mats' proposed spec is significantly weaker than border-image. It cannot represent custom intersections in the same way that border-image can represent interesting corners; all it can do is overlap things. Maybe that's a weakness we're okay with! (It's almost certainly one we'd have to live with to get variable-width gutters.) But it's not one we can take for granted.

I wonder how you get those 17. 6 images plus 2 intersection images are 8. Or if you want to, you could require another stretchable/tileable image between the intersection and the end cap, then you'd have 10 in total.

Sorry, I meant 13.

A rule can cross thru an intersection, or only enter from one side and not exit the other. There are thirteen combinations of these possibilities, when taking both axises into account: one 4-way intersection (both rules fully cross the intersection), four 3-way intersection (one rule goes fully thru the intersection, the other only comes in from one edge), four 2-way corner intersections (each rule only comes in from one edge), and four 1-way intersections (one rule comes in from one edge, without fully crossing). That's 13 in total.

For example, imagine a border-image that's an iron frame with vines wrapping around it. You can do this with the 8-slice technique, with only minor restrictions on your design. You absolutely cannot do an equivalent gap-image with "just overlap them", unless you specifically want that sort of design. You need custom images for each intersection, instead.