Re: [css-box] margin-collapse property

On 2014-07-30 15:25, Alan Gresley wrote:
> On 30/07/2014 11:46 PM, Jonathan Rimmer wrote:
>>
>> On 2014-07-30 13:14, Alan Gresley wrote:
>>> On 30/07/2014 8:15 PM, Jon Rimmer wrote:
>>>> The box-sizing property has proven very popular as a way for
>>>> developers to control unintuitive default behaviour in CSS, to the
>>>> extent that many (most?) CSS frameworks such as Bootstrap include a
>>>> global box-sizing: border-box override by default.
>>>>
>>>> I believe it would be useful to provide a similar switch to control
>>>> margin-collapse behaviour. The default behaviour is useful in some
>>>> contexts, but in others, particularly collapsing margins between
>>>> parents and children, it is often just a pain. To that end, I
>>>> propose a new property margin-collapse that controls whether an
>>>> element is eligible for margin-collapsing. Between eligible elements,
>>>> margin collapsing would proceed as per the rules defined in CSS 2.1.
>>>>
>>>> The margin-collapse property would accept the following values:
>>>>
>>>> inherit Inherit from parent. Mixing with any other value is invalid.
>>>>
>>>> all Default value. Eligible for collapse with adjacent, parent and
>>>> child elements that are eligible for collapsing. Mixing with any
>>>> other value is invalid.
>>>>
>>>> none Do not collapse with any other element. Mixing with any other
>>>> value is invalid.
>>>>
>>>> adjacent Eligible for collapse with adjacent elements that are
>>>> eligible for collapsing.
>>>>
>>>> parent Eligible for collapse with parent elements that are eligible
>>>> for collapsing.
>>>>
>>>> children Eligible for collapse with first and last child elements
>>>> that are eligible for collapsing.
>>>>
>>>> The final three values would be combinable, e.g.
>>>>
>>>> .nestable { margin: 1em 0; margin-collapse: parent children; }
>>>
>>> Ok, why have you got vertical margin in this declaration as a
>>> shorthand when vertical margin do not collapse?
>> I don't follow. Vertical margins do collapse[1], and in this example the
>> elements margin-collapse is configured to be eligible for collapse with
>> parent and child elements in the DOM, just not adjacent elements.
>
> Oh, I should have said horizontal margins. :-/
>

OK, well I included the horizontal = 0 to emphasise that the margins in 
question were the vertical ones

>>> Secondly, where should my <p> be position in the following test?
>>>
>>> <style type="text/css">
>>>   .wrapper { background: yellow; }
>>>   .float {
>>>     float: left;
>>>     width: 100px;
>>>     height: 100px;
>>>     background: blue;
>>>     margin-bottom: 20px;
>>>   }
>>>   p { border: 5px solid red; }
>>>   p.test1 { margin-collapse: all; }
>>>   p.test2 { margin-collapse: none; }
>>>   .box, .wrapper { clear: left; }
>>> </style>
>>>
>>> <p>A paragraph</p>
>>> <div class="float"></div>
>>> <p class="test1">Where should I be positioned with 'margin-collapse:
>>> all'?</p>
>>>
>>> <div class="wrapper">
>>>   <div class="float"></div>
>>>   <p class="test2">Where should I be positioned with 'margin-collapse:
>>> none'?</p>
>>> </div>
>>>
>> See this illustration: http://i.imgur.com/pBTPefE.png
>>
>> The first <p> would appear as the first element in the page, with its
>> default 1em margin.
>> <p.test1> would appear exactly as it does under the current rules: It
>> would be flush with the top of the first <div.float>. Its top margin
>> would collapse with that of the first <p>.
>
> What about the <div.float>? It will still be 1em below the first 
> paragraph?

Sure, neither it or the first paragraph have any margin-collapse set, so 
they are still eligible for margin-collapse, so follow the same 
behaviour as in CSS 2.1.

>> <p.test2> is ineligible for collapse, so its top margin would be added
>> to that of the first <div.float> above it. It would appear 1em below
>> that element.
>
> Then does that mean that the float is now sitting 1em above it's 
> containing block?

No? Its containing block is <div.wrapper>, not <p.test2>.

>>> Also what happens in this situation?
>>>
>>> <style type="text/css">
>>>   .wrapper { background: yellow; margin-collapse: none; }
>>>   p { border: 5px solid red; }
>>>   p.test1 { margin-collapse: all; }
>>> </style>
>>>
>>>
>>> <div class="wrapper">
>>>   <p class="test2">Which margin-collapse win?</p>
>>> </div>
>>>
>> <p.test2>'s margin would not collapse with the wrapper. The
>> <div.wrapper> has declared that its margins are ineligible for
>> collapsing. The <p.test2> has declared that it is eligible for
>> collapsing, but its margins cannot collapse with an ineligible element.
>
> What about if I swap the style like so?
>
> <style type="text/css">
>   .wrapper { background: yellow; margin-collapse: all; }
>   p { border: 5px solid red; }
>   p.test1 { margin-collapse: none; }
> </style>
>

Same result. The <div.wrapper>'s margins are now ineligible for 
collapse, but the <p.test>'s margins aren't. Since both elements 
involved in a margin collapse have to 'agree' to the collapse, they 
can't be collapsed here.

The idea of the margin-collapse property isn't to say whether an 
element's margins definitely *will* collapse, just to say that they 
*can*. E.g. that the user agent's margin collapse algorithm can consider 
for them for collapse. In each case, *both* elements would have to 
eligible for collapse before a collapse between their margins was 
considered. And even if the are both eligibile, they still follow the 
old rules from CSS 2.1.

>>>> There could also be separate properties margin-collapse-top and
>>>> margin-collapse-bottom for controlling the collapse behaviour of the
>>>> relevant margins.
>>>>
>>>> The primary use case for this property would be for container
>>>> elements that do not want their children's margins to collapse with
>>>> their own:
>>>
>>> That is a used case for a property and value for a 'Block Formatting
>>> Context'.
>> I don't understand what you're saying here.
>
> Margins of elements that establish new block formatting contexts (such 
> as floats and elements with 'overflow' other than 'visible') do not 
> collapse with their in-flow children [2].

Right, yeah, so there are rules in CSS 2.1 around which elements can 
collapse with each other. The idea of this property wasn't to replace 
them, just to add a mechanism for a user to say, should this element's 
margins even be eligible for collapse with other elements? And if so, 
which elements? Just adjacent DOM nodes? Just parent and children nodes? 
Etc. I think it is useful to have an explicit way to control this, 
without the side effects of floating or setting overflow on an element.

>> [1] https://developer.mozilla.org/en-US/docs/Web/CSS/margin_collapsing
>
> 2. 
> http://www.w3.org/TR/2011/REC-CSS2-20110607/box.html#collapsing-margins
>
> Alan

Jon

Received on Wednesday, 30 July 2014 14:50:12 UTC