Padding-bottom/top in flexbox layout - css

I have a flexbox layout containing two items. One of them uses padding-bottom :
#flexBox {
border: 1px solid red;
width: 50%;
margin: 0 auto;
padding: 1em;
display: flex;
flex-direction: column;
}
#text {
border: 1px solid green;
padding: .5em;
}
#padding {
margin: 1em 0;
border: 1px solid blue;
padding-bottom: 56.25%; /* intrinsic aspect ratio */
height: 0;
}
<div id='flexBox'>
<div id='padding'></div>
<div id='text'>Some text</div>
</div>
The blue element maintains its aspect ratio according to its width when the page is resized.
This works with Chrome and IE and looks like :
However, in Firefox and Edge, I get the following (it's ignoring the padding on the blue box, which is what maintains the aspect ratio):
I'm too new to flexbox to really understand if this should or shouldn't work. The whole point of flexbox is to resize things, but I'm not sure why it is ignoring the intrinsic padding, and putting absolute sizes on the blue element.
I guess ultimately I'm not even sure if Firefox or Chrome is doing the correct thing! Can any Firefox flexbox experts help?

Update September 2020
Firefox and edge have implemented the behaviour from the specs and margin + padding for flex elements are both calculated according to the width of the containing block.
Just like block elements.
Update February 2018
Firefox and edge have agreed to change their behaviour on top, bottom margin and padding for flex (and grid) items :
[...] e.g. left/right/top/bottom percentages all resolve against their containing block’s width in horizontal writing modes. [source]
This is not yet implemented (tested on FF 58.0.2).
Update April 2016
(still valid in may 2017)
The specs have been updated to:
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)
source: CSS Flexible Box Layout Module Level 1
This means that chrome IE FF and Edge (even if they don't have the same behaviour) follow the specs recommendation.
Specs also say:
Authors should avoid using percentages in paddings or margins on flex
items entirely, as they will get different behavior in different
browsers. [source]
Workaround
You can wrap the first child of the flex container in an other element and put the padding-bottom on the second child :
#flexBox {
border: 1px solid red;
width: 50%;
margin: 0 auto;
padding: 1em;
display: flex;
flex-direction: column;
}
#text {
border: 1px solid green;
padding: .5em;
}
#padding {
margin: 1em 0;
border: 1px solid blue;
}
#padding > div {
padding-bottom: 56.25%; /* intrinsic aspect ratio */
}
<div id='flexBox'>
<div id='padding'><div></div></div>
<div id='text'>Some text</div>
</div>
I tested this in modern browsers (IE, chrome, FF and Edge) and they all have the same behaviour. As the configuration of the 2nd child is the "same as usual", I suppose that older browsers (that also support flexbox layout module) will render the same layout.
Previous answer
According to the specs, Firefox has the right behaviour
Explanation
Unlike block items which calculate their % margin/padding according to the containers width, on flex items:
Percentage margins and paddings on flex items are always resolved
against their respective dimensions; unlike blocks, they do not always
resolve against the inline dimension of their containing block.
source dev.w3.org
This means that padding-bottom/top and margin-bottom/top are calculated according to the height of the container and not the width like in non-flexbox layouts.
As you have not specified any height on the parent flex item, the bottom padding of the child is supposed to be 0px.
Here is a fiddle with a fixed height on the parent that shows that padding bottom is calculated according to the height of the display:flex; container.

The accepted answer is correct but I improved on the solution by using a pseudo-element instead of adding a new element in to the HTML.
Example: http://jsfiddle.net/4q5c4ept/
HTML:
<div id='mainFlexbox'>
<div id='videoPlaceholder'>
<iframe id='catsVideo' src="//www.youtube.com/embed/tntOCGkgt98?showinfo=0" frameborder="0" allowfullscreen></iframe>
</div>
<div id='pnlText'>That's cool! This text is underneath the video in the HTML but above the video because of 'column-reverse' flex-direction. </div>
</div>
CSS:
#mainFlexbox {
border: 1px solid red;
width: 50%;
margin: 0 auto;
padding: 1em;
display: flex;
flex-direction: column-reverse;
}
#pnlText {
border: 1px solid green;
padding: .5em;
}
#videoPlaceholder {
position: relative;
margin: 1em 0;
border: 1px solid blue;
}
#videoPlaceholder::after {
content: '';
display: block;
/* intrinsic aspect ratio */
padding-bottom: 56.25%;
height: 0;
}
#catsVideo {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

I used vh instead of % worked perfectly in Safari, Firefox & Edge

Related

Rendering (rounding?) issue in Chrome when zooming

Here's a simple setup with two divs next to each other in a parent container which has a border while the two children have different background colors. There's also a codepen here:
.tag {
/* Also happens with .1rem */
border: 1px solid black;
display: inline-block;
height: 50px;
}
.key {
background: black;
color: white;
display: inline-block;
height: 100%;
width: 50px;
}
.value {
display: inline-block;
height: 100%;
width: 50px;
}
<div class="tag">
<div class="key"></div>
<div class="value"></div>
</div>
On Google Chrome when zooming in I get rendering issues like this (note the white line between the border and black div on the top/left edges):
I've tried various things like flexbox, using rem for the border width etc., but at best it changes at which zoom level and on which edge the issue appears. I assume this is some kind of sub-pixel rounding issue, but I wonder if there's any way to fix this.

CSS: Browser not calculating padding % correctly

I've written up a very basic HTML and CSS page to test out my responsive web design skills but the calculation of the padding is going wrong and I can't figure out why, any help from people would be greatly appreciated.
Below I have added my code for you to see. I have one 'main' with a 'section' and an 'aside' in it. Inside both are a box of two different sizes. I calculated the size and margin of the boxes ok but the padding won't work properly. I calculated the padding by target/context=result, which in this case for the first box is 25px padding / 500px = 0.05 (5%), and for the second box is 25px/300px= 0.08333333 (8.333333%).
However this does not cause a 25px padding but instead creates a much bigger one. When I look at the Google Chrome Developer Tool it tells me that the padding for the first box is now 56.875px and the second box is 94.797px.
I've been trying to solve this for sometime now trying different things but can't manage to figure it out.
Any help on this would be greatly appreciated. Code is below.
body, section, aside, p {
margin: 0;
padding: 0;
}
main {
width:90%; /* viewport is 1264px wide, 90% width is 1137.590px */
background-color: lightgreen;
min-height: 1000px;
margin: 0 auto;
}
section {
height: 500px;
width: 44.067133%; /* 500/1137.590 */
background-color: green;
float: left;
margin: 04.398736%; /* 50.031/1137.590 */
padding: 5%; / 25/500 */
}
aside {
height: 300px;
width: 26.434279%; /* 300/1137.590 */
background-color: blue;
float: right;
margin: 04.398736%; /* 50.031/1137.590 */
padding: 8.3333333%; /* 25/300 */
color: lightblue;
}
<body>
<main>
<section class="box-green">
<p>This is a green box</p>
</section>
<aside class="box-blue">
<p>This is a blue box</p>
</aside>
</main>
</body>
When you calculate padding in percentage, that amount is calculated by the width of the containing block, not the height.
https://developer.mozilla.org/en-US/docs/Web/CSS/padding
Padding, when given in percents, is based on the containing element not the height of the element itself.
Although this is not the correct way to write a responsive code but just to make you understand the padding % is not determined from the div size but its determined from the screen size. Also the margin you are using 4.398736% is adding on both left and right side of both the divs. Plus the padding of 5% on both side of .section and padding of 8.33333% on both side of .aside. its making the total size to 115.96555%.
For your understanding if you want both the divs (section and aside) to align side by side. Use the below written css style for both of them.
.section {
height: 500px;
width: 44.067133%;
background-color: green;
float: left;
margin: 02.199736%;
padding: 5%;
display: inline-block;
}
.aside {
height: 300px;
width: 26.434279%;
background-color: blue;
float: right;
margin: 02.199736%;
padding: 5%;
color: lightblue;
display: inline-block;
}
Hope this helps..

How to add borders to div without messing up the layout?

I have the following elements:
<body>
<div id="container">
<div id="sidebar1"></div>
<div id="content">
<h3>Lorem ipsum</h3>
<p>Whatnot.</p>
</div>
<div id="sidebar2"></div>
</div>
</body>
Following this style:
/* ~~ this fixed width container surrounds all other divs~~ */
#container {
width: 960px;
background-color: #FFF;
margin: 0 auto;
overflow: hidden;
}
#sidebar1 {
float: left;
width: 180px;
/*border: 2px solid black;*/
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
#content {
padding: 10px 0;
width: 600px;
float: left;
}
#sidebar2 {
float: left;
width: 180px;
/*border: 2px solid black;*/
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
I am trying to achieve this layout: http://jsfiddle.net/QnRe4/
But as soon as I un-comment the borders it turns into this: http://jsfiddle.net/FZxPQ/
** Solved **
The border width was added to each element's total width making them too wide to fit in the container. Removing 2x the border width from each column's width solves the problem: http://jsfiddle.net/FZxPQ/4/
CSS box-sizing to the rescue! This property
alters the default CSS box model used to calculate widths and heights of elements
The border-box value means that
the width and height properties include the padding and border
/* support Firefox, WebKit, Opera and IE8+ */
#container, #sidebar1, #sidebar2 {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
However, browser support is not 100% standardized.
As other answers have already mentioned the extra width which pushes the sidebars out of alignment is because the width calculation includes the border width. box-sizing simply tells the browser that an element with a given width/height should include any border and padding values into the final width/height calculations.
The problem is that when you add in the boarder, the size of the outer divs increased by 4, 2px on each size. So, your container needs to grow in size by 8px.
So change your container to:
#container {
width: 970px;
background-color: #FFF;
margin: 0 auto;
overflow: hidden;
}
See: http://jsfiddle.net/QnRe4/13/
When you apply the borders, that goes outer the divs, so the sidebars will have 184px width which doesn't fits to the container. try addig width: 176px
http://jsfiddle.net/QnRe4/12/
#sidebar1 {
float: left;
width: 176px;
border: 2px solid black;
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
Like this? http://jsfiddle.net/QnRe4/3/
What's happening is that your elements are losing their block display properties when you remove the borders.
So, adding display: block to those elements resolves that.
I've also adjusted your element's widths by 4px in width to retain the layout, since removing those borders essentially reduces the space that those elements occupy on-page.

how to use box-sizing:border-box on a fluid element with no height assigned?

I have an issue when using box-sizing:border-box on a fluid grid I have built. I have 1 main column and then a secondary column that contains 2 grid items. If I add border-bottom: 2px solid grey to the first grid item in the secondary column box-sizing is ignored which makes the grid look off as the second column is now slightly taller that the main one. Can anyone advise how I can make these look even, I understand that this is probably because I havent set heights but I'm not sure how to work round this?
Here is my JS Fiddle http://jsfiddle.net/97qpV/
CSS
body * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.featured-news-col {
width: 66.66667%;
float: left;
margin-right: 0%;
display: inline;
border-right: 2px solid grey;
}
.m-news-thumb {
position: relative;
display: block;
}
.sub-article{
border-bottom: 2px solid grey;
}
.sub-article:last-child{
border:none;
}
img {
display: block;
height: auto;
max-width: 100%;
min-width: 100%;
}
.additional-news-col {
width: 33.33333%;
float: right;
}
You'll need to set heights if you want them to be the same height. HTML elements will, by default "shrink-wrap" their contents, and be only as tall as the contents.
box-sizing doesn't change this. What it does change is how height and width are determined when things like margins, paddings, and borders are added.
So, for example, if you have a div with the following:
div {
height: 50px;
width: 50px;
border: 5px solid black;
}
With the default box-sizing (content-box), the calculated size of that div would actually be 60x60px (the height/width, plus the size of the border on both sides). However, with box-sizing: border-box, that border is now counted as part of the box size, making its calculated dimensions 50x50px.
Jeff Kaufman has a good demonstration of how box-sizing works, and why border-box makes more sense.
The boxes only line up when the contents match the ratio 3:2 (eg those 600x400 dummy images). By adding borders the boxes no longer fit that ratio.
I don't think there is any way to make this work with CSS borders. If the final content will be images I suggest making the borders part of the image. Then they will always line up at any size.

CSS table and max-width in Chrome not working

This is my CSS code;
#wrap {
width:50em;
max-width: 94%;
margin: 0 auto;
background-color:#fff;
}
#head {
width:50em;
height:10em;
max-width: 100%;
margin: 0 auto;
text-align:center;
position: relative;
}
#css-table {
display: table;
margin: 1em auto;
position: relative;
width:50em;
max-width: 100%;
}
#css-table .col {
display: table-cell;
width: 20em;
padding: 0px;
margin: 0 auto;
}
#css-table .col:nth-child(even) {
background: #fff;
}
#css-table .col:nth-child(odd) {
background: #fff;
border-right: 4px double #b5b5b5;
}
And my HTML code;
<div id="cont">
<div id="css-table">
<div class="col">123</div>
<div class="col">123</div>
</div>
</div>
When I scale the Firefox window, the table scales fine even down to 300px width viewport...just like I want to. But in Chrome, the table looks normal only when the viewport is wider than 50em. If I narrow the Chrome window, the table bleeds out on the right side of the wrap.
Is there a reason why is Chrome doing this?
Technically Chrome is following the rules because max-width should only apply to block elements.
From MSDN docs:
The min-width/max-width attributes apply to floating and absolutely
positioned block and inline-block elements, as well as some intrinsic
controls. They do not apply to non-replaced inline elements, such as
table rows and row/column groups. (A "replaced" element has intrinsic
dimensions, such as an img or textArea.)
The table (or in your case display:table) should technically not work or be supported. FF apparently obeys it fine, but you'll probably need to come up with another solution, either removing the display:table or the max-width.
max-width property
MSDN Doc
The solution I found was using table-layout: fixed and width: 100%
Create a div and give it a styling to display block and a max width. You may use traditional <table> and give it a styling of 100% width.
I was able to use a mixin(SASS) to fix the issue.
#mixin clearfix {
&::after{
content: "";
display: table;
clear: both;
}
}

Resources