CSS3 columns in Chrome with child DIV elements - html

I'm having trouble with CSS3 columns, they don't work as I would have expected in Chrome 53.0.2785 - they work as I'd expect in Firefox 49, IE11, EDGE 38.14393
The first two child DIVs of my "container" DIV display under each other in Chrome, but next to each other in Firefox
HTML:
<div class="container">
<div>
Some content 1
</div>
<div>
Some content 2
</div>
</div>
CSS:
* {
box-sizing: border-box;
}
.container {
column-width: 100px;
column-gap: 12px;
}
.container > div {
display: inline-block;
width: 100px;
border: 1px solid black;
padding: 20px;
}
Test it here: https://jsfiddle.net/s7cfbqzt/3/
Now, there's a few strange things happening in Chrome:
if I only remove "display: inline-block", Chrome breaks up the DIVs (even the border gets distributed) - Firefox does not
Please note that I can't set column-count in the parent (which in combination with removing inline-block seems to kind-of-work) as it's supposed to be a fluid layout. The height of each DIV is dynamic as well, so if that's a requirement I'd have to write some JS for this (but I'd prefer to have this working without JS).
if I remove border-sizing and all properties of the child DIVs it works as expected, but as soon as I start filling the inner DIVs with some other content (that might have border or paddings or box-shadows), it breaks again
If I add a third child DIV
<div>Some content 3</div>
there will be columns in Chrome, but is displayed as
1..3
2
A fourth DIV would then be display underneath DIV3, a fifth DIV in the first "row" again.
1..3..5
2..4
Is this a bug in Chrome or am I doing something wrong?

Chrome is actually probably the one browser doing it correctly:
https://drafts.csswg.org/css-break/#widows-orphans
Name: orphans, widows
Value: <integer>
Initial: 2
IE 11, EDGE and Firefox (49) do not (yet?) support widows and orphans, even though http://caniuse.com/#feat=css-widows-orphans claims that IE11 and EDGE do support it - see https://jsfiddle.net/s7cfbqzt/13/ in IE11 and EDGE. If IE and EDGE actually would support it, they'd set the initial values to 1 instead of 2.
Fix for my use-case is to add
orphans: 1;
widows: 1;
to the container-class in CSS.
Thanks #Jay for taking the time to look into this!

You can achieve this by floating the divs within the container, you will also need to float their container, or they won't display correctly.
* {
box-sizing: border-box;
}
.container {
column-width: 100px;
column-gap: 12px;
float: left;
}
.container > div {
display: inline-block;
width: 100px;
border: 1px solid black;
padding: 20px;
float: left;
}
EDIT:
then instead of using column-gap, i would apply margin left to each of the divs inside the container. like so;
.container {
width: 100%;
float: left;
}
.container > div {
width: 100px;
border: 1px solid black;
padding: 20px;
float: left;
margin-left: 12px;
}
.container > div:first-child {
margin-left: 0;
}
EDIT:
If the height does not need to match - remove column-width from the container div. see https://jsfiddle.net/0sz6t3ft/1/

Related

Flex items overlapping item in IE11

I have two divs:
top div contains a long text that takes up several lines
lower div has min-height and flex-grow: 1
When I reducing the window to the scroll appeared, then in chrome everything is displayed correctly. But in IE11 top div is reduced to one line, and its text is on top of the bottom div.
I can fix it only with set some width for content of top div (it work with fixed width, or calc width, but not work with percentage width)
How can I fix it without setting width or with percentage width (width:100%)?
body,
html {
height: 99%;
padding: 0;
margin: 0;
}
.flexcontainer {
width: 25%;
display: flex;
flex-direction: column;
height: 100%;
border: 1px solid lime;
}
.allspace {
flex-grow: 1;
min-height: 300px;
background-color: yellow;
}
.longtext {
background-color: red;
}
.textcontainer {
border: 1px solid magenta;
/*IE work correctly only when specified width. by example: width:calc(25vw - 2px);*/
}
<div class="flexcontainer">
<div class="longtext">
section 1 with long name section 1 with long name section 1 with long name
</div>
<div class="allspace">
all space
</div>
</div>
jsfiddle: https://jsfiddle.net/tkuu28gs/14/
Chrome:
IE11:
IE11 is full of flex bugs and inconsistencies with other browsers.
In this case, the source of the problem is flex-shrink.
IE11 is rendering flex items oddly after applying flex-shrink: 1 (a default setting), which causes the lower item to overlap its sibling above. This problem doesn't occur in other major browsers.
The solution is to disable flex-shrink. It fixes the problem in IE11 without changing anything in other browsers.
Add this to your code:
.longtext {
flex-shrink: 0;
}
revised fiddle
You may also want to look into:
setting min-width: auto on flex items, as IE11 has a different minimum size default than newer browsers. See the "Browser Rendering Notes" section in my answer here: Why don't flex items shrink past content size?
setting the container to width: 100%, as IE11 may not do this automatically to block-level flex containers. Text in a flex container doesn't wrap in IE11
The use of flex-shrink: 0; mentioned in the accepted answer works to prevent overlapping. However, I'm using like flex: 0 1 15% as I intend to allow shrinking and this renders nicely in other browsers like MS Edge, Chrome, and Firefox, but not in IE 11.
To apply no shrinking (flex-shrink: 0) only for IE 11, I used the following instead as the -ms- is vendor-specific:
-ms-flex-negative: 0 !important;
problem solved:
body, html {
height: 100vh;
padding:0;
margin:0;
}
.flexcontainer{
width:25%;
display: flex;
height: 100%;
flex-flow: column;
border: 1px solid lime;
}
.allspace{
flex-grow:1;
background-color: yellow;
}
.longtext{
background-color: red;
//EDIT
flex-grow: 0;
min-height: 100px;
}
.textcontainer{
border:1px solid magenta;
/*IE work correctly only when specified width. by example: width:calc(25vw - 2px);*/
}
EDIT (screenshots on IE11)

Force divs to be on the same line

I am trying to make a div with text and a div with a button fit side by side. It works fine until you make the screen really narrow. Is there a way to force them to be on the same line and for the first div to shrink to accommodate the min-width of the second?
http://jsfiddle.net/C3877/9/
To see what I mean, resize the window, reducing the width, until the div with the button is forced onto the second line. That is what I'd like to prevent.
Note: I only care if a suggested fix works properly in Chrome.
Instead of floats, you could use display: inline-block. This will keep things all on one line, and respect the min-width as well.
Inline-block fiddle: http://jsfiddle.net/C3877/8/
In addition, since you only care about Chrome, you could look into flexible boxes
A (quick) flex fiddle here: http://jsfiddle.net/C3877/11/
You can use negative margin-left for the floated right element. Note that this solution keeps using float for both the left and right divs, without using float, you have dozens of solutions (as some of other answers pointed out).
#right_div {
...
margin-left:-100%;
}
Note that all the next content should be wrapped in a block element and use clear:both. I also added a sample of such an element with background:green in this DEMO.
Appending this does the trick I suppose:
#media (max-width:515px) {
#left_div { width: 100%; margin-right: -100px }
}
UPDATED
You could use margin and absolute positioning:
CSS
#parent_div {
width: 100%;
height: 10%;
position: relative;
min-width: 40px;
}
#left_div {
width: 80%;
min-width: 100px;
height: 80%;
float: left;
background-color: #000;
color: #FFF;
}
#right_div {
width: 15%;
min-width: 100px;
float: right;
background-color: blue;
position:absolute;
right: 0px;
}
input[type=button] {
font-size: 2rem;
}
SEE DEMO: http://jsfiddle.net/C3877/19/
You will have to play with some of the css to get it just right when you move it on your website. But this is a sure quick fix.

Difference of layout on Safari with margin-right negative

I stumbled upon a difference in layout rendering between Safari and Chrome/Firefox and I don't know which one is "right".
You can check the jsfiddle here
On Firefox/Chrome the layout is as expected, the yellow div is right after the red ones. But on Safari, the yellow div is positioned under the red ones.
After investigating what I did wrong I found out the bug comes from the CSS class E whose property margin-right (value: -11px) is bigger than the width property (value: 10px) for my div.
I think I understand why Safari renders it this way. The width of div of class B is computed as being the sum of the widths of its children as they have the property float: left;.
Here it is widthB = widthB2*2 + widthE + marginRightE + widthC or marginRightE < -widthE so widthB is not large enough to contain each div next to each other.
So my questions are:
Am I right in my understanding of what Safari does?
Why do Chrome and Firefox render differently? Are they just not decreasing the width of the parent div based on a negative margin-right?
Would the proper correction to always have a margin-right lesser or equal to the width of a div in this case?
Thank you!
HTML:
<div class="A">
<div class="C">
<div class="B">
<div class="B2"></div>
<div class="B2"></div>
<div class="E"></div>
<div class="C">
<div class="D"></div>
</div>
</div>
</div>
</div>
CSS:
.A {
background-color: blue;
height: 200px;
}
.B {
height:100px;
}
.B2 {
background-color: red;
height: 100px;
width: 100px;
float: left;
}
.C {
float: left;
}
.D {
height: 40px;
width: 40px;
float:left;
background-color: yellow;
}
.E {
height: 50px;
width: 10px;
position: relative;
left: -10px;
margin-right: -11px;
background-color: black;
float: left;
}
I'm not sure what you expect to happen with the CSS in the JS fiddle. You are delving into undefined behaviour. I say this because:
'C' is floated but does not have a defined width. This leads to issues in various browsers depending on the complexity of the layout.
None of the floated elements are ever cleared. When floating it is imperative that a clearfix of some description is used, whether it is clear:both, etc.
If you tweak the mark-up and add a clear-fix, you see that the content is always 239px. See http://jsfiddle.net/eaFn9/
However, it seems like the relatively positioned item 'E' and margin is having a negative impact on the width calculation, as Chrome's web inspector seems to always report oddly for the negative margin on this element.
If you play around with this in web inspector you can see it's almost as if the negative margin is the cause of the drop. I think it may be due to a container that does not have a width, and isn't position relative in itself.
How to fix?
Personally, I would want to re-write your layout to include fixed widths on all floats, reduce nesting of floats and clear where possible. It seems overly complex but without a real world use case it's hard to rewrite.
However, It seemed to me that you can wrap 'B2' + 'E' elements in a wrapper that is floated and relatively positioned, then use absolute positioning on 'E' to give the same affect and remove the negative margin.
This is the JSFiddle I came up with: http://jsfiddle.net/jV3Ub/
Sorry, this is not really an answer but it's too long to make it a comment...
Anyway, it took me a minute to figure this out.
I used Firefox 19 on Mac OS X 10.8.2, Chrome 24.0 (Mac) and Safari 6.0.2 (Mac as well). Using the web inspector tools, I realized the divs are not computed the same way indeed. I suck at calculations, but I took the time to sit down and look at this thoroughly, and I do understand Safari's calculations the same way you do.
In Safari, it seems that div B isn't wide enough to contain the yellow div (C) so it seems to reject it to the bottom. For the record, in my tests, I see the yellow div to the right of the red div in FF and Chrome, while Safari shows it right underneath the red, and to the upper left. I am not sure this will help, but I can only recommend you to use the web inspector tools now integrated to all modern browsers to debug this.
I'm not sure about why this happens, all I know is that by only changing the width of E by 1px, like so:
.E {
height: 50px;
width: 11px; /* added 1px to this property */
position: relative;
left: -10px;
margin-right: -11px;
background-color: black;
float: left;
}
it displays correctly in Safari.
Make the following changes to classes .D and .E:
.D {
float:left;
height: 40px;
width: 40px;
background-color: yellow;
margin-left: -11px;
}
.E{
height: 50px;
width: 10px;
position: relative;
left: -10px;
background-color: black;
float: left;
}
DEMO: http://jsfiddle.net/uryJJ/22/
I hope this helps!
SECOND EDIT:
I think we should link these two questions: https://stackoverflow.com/questions/4989930/css-negative-margin and why use negative margins? to this one.
Also See the W3C spec on margin: http://www.w3.org/TR/CSS2/box.html#margin-properties.
Section 8.3.1 Might actually explain what is going on with your sample. A collapsing margin issue not rendering correctly in Safari.
ORIGINAL POSTING:
So my questions are:
1) Am I right in my understanding of what Safari does. Why do Chrome and Firefox render differently? Sounds like that might be it, but, really, who cares? You are not getting the results you want. You should change your code unless you don't care about Safari users.
2) Are they just not decreasing the width of the parent div based on a negative margin-right?
Probably, but again, not really important.
3) Would the proper correction to always have a margin-right lesser or equal to the width of a div in this case? I would say yes. To fix the issue and get the results you want I would move the div with class E inside the right most div with class B2. Then float E to the right and remove the position, left and margin-right attributes.
.E {
height: 50px;
width: 10px;
background-color: black;
float: right;
}
http://jsfiddle.net/uryJJ/32/
FIRST EDIT
.D {
height: 40px;
width: 40px;
float:left;
background-color: yellow;
position:relative;
left: -10px;
}
.E {
height: 50px;
width: 10px;
position: relative;
left: -10px;
background-color: black;
float: left;
}
http://jsfiddle.net/uryJJ/33/
Sorry, I might be beating this to death but this fixes it:
.E {
height: 50px;
width: 10px;
margin-left: -10px;
background-color: black;
float: left;
}
http://jsfiddle.net/uryJJ/35/
I was not a fan of negative margin values until just now.

inline-block elements are line breaking for seemingly no reason?

I have some pretty basic HTML/CSS that isn't working as I expect. Basically I have my body setup to be 400px wide. I then have two divs inside of the body with explicit widths of 300px and 100px. Additionally, both of these divs are set to display: inline-block. For some reason, the 100px div breaks out of the body's content area and appears below it. I don't know why this is happening. If I set the width from 100px to 96px, it works. However, if I set it to 97px, 98px, 99px, or back to 100px, it doesn't work. I find this behavior very odd. Can someone explain what is going wrong?
Note that I am testing this on Chrome (Beta Channel). Code is below.
The CSS:
body {
margin: 4px;
width: 400px;
height: 250px;
border: 1px solid black;
}
.list-container {
display: inline-block;
width: 300px;
height: 100%;
background-color: red;
}
.button-container {
display: inline-block;
width: 100px;
height: 100%;
background-color: blue;
}
The HTML:
<body>
<div class="list-container">
</div>
<div class="button-container">
</div>
</body>
It's because of the way white-space collapses in html.
If you remove the line-breaks from between the two div elements, everything's fine:
<div class="list-container">
</div><div class="button-container">
</div>
JS Fiddle demo.
You could, also, just comment-out the between divs:
<div class="list-container">
</div><!--
--><div class="button-container">
</div>
JS Fiddle demo.
Or even set the font-size to zero for the body element (but you'll have to redefine it for the child elements, obviously:
body {
margin: 4px;
width: 400px;
height: 250px;
border: 1px solid black;
padding: 0;
font-size: 0;
}
JS Fiddle demo.
Another possibility with odd inline-block behaviour in Chrome is if you have text-render: optimizeLegibility set. I was struggling with inexplicable line-breaks in inline block elements in Chrome, and found that removing text-render: optimizeLegibility fixed the problem.
I've had at least one other hard-to-figure-out problem (inexplicable non-rendering of web fonts) that turned out to be caused by optimizeLegibility in the past, so from now on that's going to be a prime suspect when things behave strangely in Chrome.
(nb. Even if you don't think you're using it, if you're using a framework like Twitter Bootstrap you may be using it unwittingly)
It's the margin in your body:
margin: 4px;
Because the margin counts as part of the total width. 300px for the first one + 100px for the second div + 8px (4 on either side) for the margin = 408px. That forces the second div down to the next line.
I'm actually kind of surprised that it works at 96. It acts like it's only accounting for the margin on one side. I'd expect it to only work at 92 or below. Either way account for the margin size in the width of your body or set the margin to 0 and that should fix the problem.

div width changes differently in Firefox vs Chrome after resizing viewport

I noticed a small difference after reducing the viewport with a layout based on flexbox containers. The following snippet contains a few links inside two containers (.container and .subcontainer). In Chrome (45 beta), the divs with class element have the same width regardless of the viewport dimension. However, in Firefox (40), the width of each div changes depending on its content.
html,
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
display: flex;
flex-direction: column;
width: 50%;
}
.element {
flex: 1 0 0;
padding: 0.5em;
text-align: center;
position: relative;
background-color: red;
margin-right: 1em;
}
.subcontainer {
flex: 0 1 auto;
display: flex;
}
.element a {
color: black;
}
<!DOCTYPE html>
<html>
<body>
<div class="container">
<div class="subcontainer">
<div class="element"><a>abc</a>
</div>
<div class="element"><a>abcdef</a>
</div>
<div class="element"><a>abcdef</a>
</div>
</div>
</div>
</body>
</html>
I think the "Run code snippet" functionality doesn't allow to see this change, so I provide a couple of gifs showing the difference:
Chrome:
Firefox:
As you can see, the boxes share the same width in Chrome, but Firefox constrains the first box quite noticeably and the other boxes keep their proportions. What is the reason of this discrepancy and how can I fix it? I'd like to have the same width for each box. That was the purpose of using flex: 1 0 0 in the first place.
Thanks
Try to set min-width to any value you need, or just 0px:
.element
{
...
min-width: 0px;
}
Fiddle
Details
For Firefox flex items has min-width:min-content by default, as pointed here
These implementations where implementing a slightly simpler behavior
for this keyword: it computed to min-content on flex items, and it
computes to 0 on everything else.
So, if we set min-width:-webkit-min-content for Chrome, it will have the same unwanted behaviour - jsfiddle.