Why Doesn't Percentage Padding/Margin Work on Flex Items in Firefox and Edge

Why doesn't percentage padding / margin work on flex items in Firefox and Edge?

2018 Update

The flexbox specification has been updated.

4.2. Flex Item Margins and Paddings

Percentage margins and paddings on flex items, like those on block
boxes, are resolved against the inline size of their containing block,
e.g. left/right/top/bottom percentages all resolve against their
containing block’s width in horizontal writing modes.


Original Answer - applies to FF and Edge versions released before 2018

From the flexbox specification:

Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in different browsers.

Here's some more:

4.2. Flex Item Margins and Paddings

Percentage margins and paddings on flex items can be resolved against either:

  • their own axis (left/right percentages resolve against width, top/bottom resolve against height), or,
  • the inline axis (left/right/top/bottom percentages all resolve against width)

A User Agent must choose one of these two behaviors.

Note: This variance sucks, but it accurately captures the current state of the world (no consensus among implementations, and no consensus within the CSSWG). It is the CSSWG’s intention that browsers will converge on one of the behaviors, at which time the spec will be amended.

Flex elements ignore percent padding in Firefox

See https://lists.w3.org/Archives/Public/www-style/2015Sep/0038.html

Grid/Flex Percentages

  • The group tried to work through how vertical percentage margins
    and paddings are defined.

    • Note: Top and bottom margins in CSS have traditionally
      resolved against the containing block width instead of its
      height, which has some useful effects but is generally
      surprising. Existing layout modes must of course continue
      to do so.
    • Previous group resolution had been for option 2 (below), but
      Google felt they had new information regarding abspos
      behavior that merited reconsideration.
    • The discussion came down to three potential solutions:

      • Option 1: Always resolve percents against the width.
      • Option 2: Grid and flex resolve against height, and
        abspos items always resolve against the width.
      • Option 3: Grid and flex, including their abspos items,
        resolve against the height. Abspos elsewhere
        continue to resolve against the width.
    • In a straw poll the group was pretty evenly divided between
      options 1 and 3.
    • Microsoft would object to option 1 and Google to option 3,
      so the discussion reached an impasse and will be continued
      privately during the F2F in hopes of reaching a conclusion.

See https://lists.w3.org/Archives/Public/www-style/2015Sep/0113.html,

Flexbox % Follow-Up

  • [...] there was still no conclusion.

The current Flexbox spec warns about this:

Percentage margins and paddings on flex items can be resolved
against either:

  • their own axis (left/right percentages resolve against width, top/bottom resolve against height)
  • the inline axis (left/right/top/bottom percentages all resolve against width)

A User Agent must choose one of these two behaviors.

Note: This variance sucks, but it accurately captures the current
state of the world (no consensus among implementations, and no
consensus within the CSSWG). It is the CSSWG’s intention that browsers
will converge on one of the behaviors, at which time the spec will be
amended to require that.


Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in
different browsers.

However, more recently the CSS WG resolved (with some controversy):

Both flexbox and grid items top and bottom margin and padding percent resolves against the available inline direction.

See the updated editor's draft.

Percentage padding / margin on grid item ignored in Firefox

I found a solution:
I had to add a wrapper to the cell with a 'width: 100%' rule and it finally works on Firefox 52!

#grid{  display: grid;  grid-gap: 8px;  grid-template-columns: 100px 100px;}.cell{  width: 100%;}.inner{  background-color: red;  padding-bottom: 50%;}
<div id="grid">  <div class="cell">    <div class="inner"></div>  </div>  <div class="cell">    <div class="inner"></div>  </div>  <div class="cell">    <div class="inner"></div>  </div>  <div class="cell">    <div class="inner"></div>  </div></div>

Collapsing margin on Flexbox grid in Edge and Firefox

Margin using percent doesn't work cross browsers on flex items, so if your margin's is more related to the viewport, use viewport units (vh or vw), else you can combine px with CSS calc() (i.e. width: calc(33.333% - 20px)) to match an equal gutter between the items.

Updated codepen

body {  padding: 1.5%;  background-color: #333;}
.container { //background-color: black; max-width: 964px; margin: 0 auto; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-flex-flow: row wrap; -moz-box-flex-flow: row wrap; -webkit-flex-flow: row wrap; -ms-flex-flow: row wrap; flex-flow: row wrap;}
.item { position: relative; width: 97%; color: #fff; background-color: #4286f4; padding: 0 20px 40px; margin: 1.5vh; box-sizing: border-box;}
@media only screen and (min-width:420px){ .item { width: 47%; }}
@media only screen and (min-width:768px){ .item { width: 30.333%; }}
a { position: absolute; bottom: 20px; left: 20px;}
<div class="container">  <div class="item item-1">    <h2>Item one</h2>    <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis blandit elit vel lacus gravida, nec imperdiet ligula ornare.</p>    <a href="#">Read more</a>  </div>  <div class="item item-2">    <h2>Item two</h2>    <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus.</p>    <a href="#">Read more</a>  </div>  <div class="item item-3">    <h2>Item three</h2>    <p>Pellentesque convallis turpis nec enim consequat, vitae pellentesque purus tempus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae.</p>    <a href="#">Read more</a>  </div>  <div class="item item-4">    <h2>Item four</h2>    <p>Pellentesque convallis turpis nec enim consequat.</p>    <a href="#">Read more</a>  </div>  <div class="item item-5">    <h2>Item five</h2>    <p>Pellentesque convallis turpis nec enim consequat.</p>    <a href="#">Read more</a>  </div>  <div class="item item-6">    <h2>Item six</h2>    <p>Pellentesque convallis turpis nec enim consequat.</p>    <a href="#">Read more</a>  </div></div>

Firefox: Item inside flexbox container does not preserve aspect ratio

Browser behavior on percentage-based vertical margins/paddings in a nutshell

It is not a bug per se, but probably due to browser's different implementation how percentage-based vertical spacings (top and bottom margins/paddings) should be calculated in flex or grid layout contexts:

Percentage margins and paddings on grid items can be resolved against either:

  • their own axis (left/right percentages resolve against width, top/bottom resolve against height), or,
  • the inline axis (left/right/top/bottom percentages all resolve against width)

A User Agent must choose one of these two behaviors.

There is no consistency of choosing either resolution strategy: as you can see, Chrome and Safari will choose strategy #2, while IE, Edge, and Firefox will go for strategy #1 (which explains your bug). W3C also noted that:

Note: This variance sucks, but it accurately captures the current state of the world (no consensus among implementations, and no consensus within the CSSWG). It is the CSSWG’s intention that browsers will converge on one of the behaviors, at which time the spec will be amended to require that.

Authors should avoid using percentages in paddings or margins on grid items entirely, as they will get different behavior in different browsers.


The solution

What you can do is simply to define the circle itself as a pseudo-element. In this approach:

  • the outer #circle element has a width of 9%, but nothing else
  • the ::before pseudo-element will have a width of 100% and a padding-top of 100%, this will force it to a 1:1 aspect ratio as desired

Your updated CSS will look like this:

#circle {
width: 9%;
margin: auto;
}

#circle::before {
background: #7FFF00;
border-radius: 50%;
width: 100%;
height: 0;
padding-top: 100%;
content: '';
display: block;
}

See proof-of-concept below (or in this fiddle):

#content {  display: grid;  grid-template-columns: minmax(13rem, 15%) minmax(85%, 100%);  position: absolute;  top: 0;  left: 0;  right: 0;  bottom: 0;  width: 100%;  height: 100%;}
#circle { width: 9%; margin: auto;}
#circle::before { background: #7FFF00; border-radius: 50%; width: 100%; height: 0; padding-top: 100%; content: ''; display: block;}
.menu { background: #D2691E; grid-row-start: 1; grid-row-end: 1;}
.circle-area { background: #191970; grid-row-start: 1; grid-row-end: 1; grid-column-start: auto; grid-column-end: span 2; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;}
<body>  <div id='content'>    <div class='menu'></div>    <div class='circle-area'>      <div id='circle'></div>    </div>  </div></body>

FlexBox - container width not expanding when using percent margin

As Michael Coker commented, Authors should avoid using percentages in paddings or margins on flex items entirely, as they will get different behavior in different browsers. (CSS Flexbox margins)

When using percent we often relate that to the viewport width, so with that in mind, viewport units vw/vh can be a good option, since it works similar (responsive).

Stack snippet made of your Codepen sample

.page {  display: flex;  /*border: 5px solid orange;*/}
.container { display: flex; border: 5px solid orange;}
.item_left { flex: 1; margin-right: 25vw;}
.item_right { display: flex; flex: 1;}
<div class="page">  <div class="container">    <div class="item_left">Left</div>    <div class="item_right">Right</div>  </div></div>

margin-top/bottom % not works in firefox

Please try this code.

It's due to display:flex is not working well with % in Firefox. So here you need to used display:block to container1 div.

Use this code when you are using % in margin-bottom.

<div class="container1" style="display: block; flex-direction: column;">
<div class="div1" style="height: 100px; margin-bottom: 1%; background-color: green;"> This is div 1 </div>
<div class="div2" style="height: 100px; background-color: blue"> This is div 2 </div>
</div>

Please try this code when you are using PX not % in margin-bottom.

<div class="container1" style="display: flex; flex-direction: column;">
<div class="div1" style="height: 100px; margin-bottom: 10px; background-color: green;"> This is div 1 </div>
<div class="div2" style="height: 100px; background-color: blue"> This is div 2 </div>
</div>


Related Topics



Leave a reply



Submit