w3c / csswg-drafts

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

[css-contain] [css-sizing] [sizing-values] Allow sizing values like @container burgermenu (width < min-width) #9978

Open codermapuche opened 4 months ago

codermapuche commented 4 months ago

Want allow the use of sizing values like max-content or min-content as units for @container rules.

This open the door to another world of possibles uses cases. Imagine a nav menu, current in desktop has flexbox horizontally and a hamburger menu in mobile. Currently we need to know the width of the menu content for write the rules, if we can use max-content in the selector, we can activate the burger style when the menu can't be placed without scroll or wrap. This is the gateway to be full responsive with dinamic content without javascript.

What you think?

Loirooriol commented 4 months ago

It's hard to understand what exactly you are proposing. Do you want to be able to check the min/max-content size in the query? Do you want to refer to the min/max-content size of the container in the rules inside @container?

I also don't understand the usecase. Please provide some code.

codermapuche commented 4 months ago

@Loirooriol i created a codepen for ilustrate best the feature: https://codepen.io/codermapuche/pen/bGZPmWP

In this pen, from the line 50 is the relevant code placed with comments about what iam doing currently, and what i want todo for the same results.

Basically: NOW: @container (width < 760px)

Where 760px = 
     4[a_tag] * 
       (100px[a_tag.width]   + 
        20px[a_tag.padding]  + 
        20px[a_tag.margin])  +
     4[li_tag] * 
       (20px[li_tag.padding] + 
        20px[li_tag.margin]) + 
     1[ul_tag] * 
       (20px[ul_tag.padding] + 
        20px[ul_tag.margin])

PROPOSAL: @container (width < min-width)

Loirooriol commented 4 months ago

I see. But the problem is that it's inherently circular that min-width depends on the contents (bypassing containment):

<style>
#container { container-type: inline-size }
@container (width < min-width) {
  #content { width: 0 }
}
@container (width >= min-width) {
  #content { width: calc(100% + 100px) }
}
</style>
<div id="container">
  <div id="content"></div>
</div>
codermapuche commented 4 months ago

I gave the matter some thought, and in the mdn says "inline-size containment is applied to the element in both the inline and block directions, the size of the element can be computed in isolation, ignoring the child elements", so the isolation avoid circular references.

I dont figure how the min-size can be calculated ignoring the child elements, in isolation. Think in some like this to prevent circular references and use child elements:

var a_size                            = computed_with_child_elements_in_isolation( node, general_rules ),
    container_what_match              = get_container_what_match( node, a_size ),
    general_rules_and_container_rules = general_rules + container_what_match.rules,
    b_size                            = computed_with_child_elements_in_isolation( node, general_rules_and_container_rules ),
    containers                        = [ ];

while ( a_size != b_size && containers.indexOf(container_what_match.id) == -1 ) {
  containers.push(container_what_match.id);

  container_what_match              = get_container_what_match( node, b_size );
  general_rules_and_container_rules = general_rules + container_what_match.rules;
  a_size                            = b_size;
  b_size                            = computed_with_child_elements_in_isolation( node, general_rules_and_container_rules );  
}

// now
container_what_match === FINAL_CONTAINER_RULES_TO_APPLY
b_size               === FINAL_SIZE

some approach when every @container rule is only applied one time per element dont be a problem with recursion.

for example if this rule is the last in css, the element is computed with a width of 0

@container (width < min-width) {
  #content { width: 0 }
}

for example if this rule is the last in css, the element is computed with a width of calc(100% of_container_width + 100px) only one time, if width is 1000 and min-width is 950 and max-width is 1020 #content width is 950 the result is a container of 1020px and content width of 1050 with 30 of content overflow

@container (width >= min-width) {
  #content { width: calc(100% + 100px) }
}

if width is 1000 and min-width is 950 and max-width is 1500 content width is 950 the result is a container of 1050px and content width of 1050 with 0 of content overflow

@container (width >= min-width) {
  #content { width: calc(100% + 100px) }
}
@container (width >= min-width) {
  #content { width: calc(100% + 100px) }
}

if width is 1000 and min-width is 950 and max-width is 1500 content width is 950 the result is a container of 1150px and content width of 1150 with 0 of content overflow

uhmm i dont know what i want in the last case, what is better, the proposal or what the last rule override the first?

i dont know how this things are computed internally, where i can learn more about the tecnical current implementation for get a better understanding of this topic?