W3C home > Mailing lists > Public > www-style@w3.org > July 2014

Re: [css-box] margin-collapse property

From: Alan Gresley <alan@css-class.com>
Date: Thu, 31 Jul 2014 01:53:16 +1000
Message-ID: <53D914EC.90407@css-class.com>
To: Jonathan Rimmer <jon.rimmer@gmail.com>, www-style list <www-style@w3.org>
On 31/07/2014 12:49 AM, Jonathan Rimmer wrote:
>
> 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.

I have the following for the first <p>.

  p.test1 { margin-collapse: all; }

I have the following for the second <p>.

p.test2 { margin-collapse: none; }

Now what happens if the second <p> has a margin-top of 2em?

>>> <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>.

Well the containing block for <p.test2> is also <div.wrapper> and the 
below style prevents it from collapsing.

p.test2 { margin-collapse: none; }

Than means that <p.test2> is 1em below <div.wrapper> since we can not 
have collapse through. The png here http://i.imgur.com/pBTPefE.png shows 
that the <div.wrapper> with a yellow background is 1em below the top of 
the float.


>>>> 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.

So this would mean that there would be a margin of 1em above and below 
the inner <p.test2>. What happens if I have something like as follows?

#container .wrapper { background: yellow; margin-collapse: all; }

How does specificity work?

> 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.

Doesn't the following work?

*>*:first-child { margin-top: 0 }

Also Tab has some CSS3 that has 'min-height: contain'.

Also, why not have a new value in the margin property instead?

margin-top: no-collapse;

margin: 1em auto no-collapse;

>
>>> [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


Alan
Received on Wednesday, 30 July 2014 15:53:46 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:39:23 UTC