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.
Related
If I wrote this:
#element {
margin-top: -50px;
}
By general rule, it would move the element upwards by 50 pixels.
Recently, I accidentally used this bit of code instead:
.elements {
margin: -50px;
}
So I had these <div> tags, one beneath the other, and by writing margin: -50px; they all somehow got closer together.
But thinking in retrospect, I don't really see how this worked. The size of the elements didn't change (as far as I know, as they contained child elements, and the child elements were closer together as well), and they didn't seem to zoom in size or anything.
I did some research online, but all I could find was for negative margins on one or two sides at most.
Is there an explanation to this? What actually happens? Maybe it's because I'm using Google Chrome, and maybe nothing happens in other browsers?
Tha margin is not added to the appearance of the element but rather to its bounds, so basically your element looks e.g. 200x200 but its bounds are equal to that of an element of 100x100 since you substract 50px from every side. Try it for yourself:
Fiddle here.
HTML:
<div class="e1"><div></div></div>
<div class="e2"><div></div></div>
CSS:
body {
padding: 100px;
}
div {
width: 200px;
height: 200px;
float: left;
margin: -50px;
}
.e1 {
background: red;
}
.e2 {
background: yellow;
}
.e1>div, .e2>div {
width: 100px;
height: 100px;
outline: 1px solid blue;
margin: 50px;
}
I've added a padding to the body to make the elements be pushed down so you can see the overlap they cause. Updated so you can see the bounds of the squares that result.
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.
I'm having problems with a 2-column layout, using display-style="inline-block".
I have this html:
<div class="A">tekst</div>
<div class="B">tekst</div>
with css:
.A {
background-color: blue;
height: 200px;
width: 250px;
padding-left: 25px;
margin-right: -254px;
display: inline-block;
vertical-align: top;
position: relative;
box-sizing: border-box;
z-index: 1;
}
.B {
background-color: red;
height: 400px;
width: 100%;
padding-left: 300px;
display: inline-block;
vertical-align: top;
position: relative;
box-sizing: border-box;
}
http://jsfiddle.net/eaFn9/9/
But as you can see, the width of the first div is 250 pixels, but it needs a margin-right of -254px before the second div is shown "next" to it.
Why is this? I cannot figure it out. Also, most examples do not use the box-sizing, but if I remove it, the layout goes awry again.
I am using Chrome, but it seems to work the same in FF and Safari too.
Any help is greatly appreciated!
Regards,
Michael
After some attemps to find the problem, I bet you have some blank or even some Enter keystroke between the 2 divs. This problem is very hard to find out. So to solve it you just need to clear all that blank or Enter keystroke so that the 2 div tags have to be close next to each other:
<!-- place 2 divs close to each other without anything between. -->
<div class="A">tekst</div><div class="B">tekst</div>
Here is the expectedly working fiddle
For anybody with the same problem:
It seems that adding 'font-size: 0' to the parent container fixes it for every browser, just not for Safari for Windows (all other Safaris work as expected).
Make sure that you reset the font-size to a sensible value inside the child divs if you want to have text in them (so in my example, both divs A and B would have font-size: 14px; for instance to show the text).
I assume (I have not done any research at all) this is a bug in Safari for Windows, as it's the only Safari with this issue.
sorry if the question title is weak, i can't quite sum my problem up into one snappy tagline...
I'm working on a website (using Joomla) and i've had to insert a DIV serving as a sidebar on the right side of the page. in order for it to be displayed "above" (or "over", i mean on the z-axis) the regular page content, i'm using a negative margin on the left side of it, covering the whole width of it, so it will simply float to the right and sit there, which works fine in ff and IE.
Since i've rarely ever run into issues with Chrome that were fine in IE, i didn't bother to check until quite late:
Now i see that in Chrome, the div is just sitting below (at the bottom of) the regular content; despite the "inline" display-types and the negative margin.
Now I've tried ridiculous things to make it work, but for some reason it just won't.
Can someone tell me how i can get it to work in Chrome?
HTML:
<div class="cframe">
<div class="content">
...
</div>
<div class="sideright">
...
</div>
</div>
CSS:
div.cframe {
display: table;
vertical-align: top;
}
div.content {
display: inline-table;
width: 751px;
padding: 60px;
}
DIV.sideright {
width: 200px;
float: right;
display: block;
position: relative;
top: 320px;
margin: 0px 0px 0px -200px;
}
...this is what i'm stuck with right now, it's all quite ugly.
[link to live-page removed as the solution has already been applied]
(The sidebar is the div classed sideright, and contains a module titled Archiv)
Thank you in advance
Change the div.content css to:
div.content {
display: inline;
float: left;
}
You're using float, but then setting the position to relative. You should remove the relative part of your css for the siderright and it should fix the issue
Edit: even better you should change the position to absolute.
Set your container div to position:relative and then position:absolute your sidebar in relation to that.
.cframe {
display: table;
vertical-align: top;
position: relative;
}
.sideright {
width: 200px;
position: absolute;
top: 320px;
right: 0;
}
I didn't test the answers above but I take their word that they worked. However, your question caught my eye, because I thought you were looking for a browser hack.
There are ways that you can tell an element to behave differently on a specific browser. This happens sometimes across browsers and the best way is to hack each individual browser and give them specific instructions. For chrome, of course you'll have to use a webkit.
This would be an easy example of the syntax to follow:
<p>TEST</p>
p {color:green;}
#media screen and (-webkit-min-device-pixel-ratio:0) {
p {color:red;}
}
Try the DEMO in several browsers and notice how only chrome will display it in red
I came across a very strange behaviour of Webkit browsers today: It concerns the way a margin is calculated next to other (floated) blocks.
Though I think this must be a common problem, I couldn't find anything about it so far.
Here's my situation: I have two <aside>s followed by a <div>. They are all displayed next to each other, the <div> on the left then .#aside-1 and #aside-2. I achieve this throught the following CSS code:
aside {
margin-bottom: 30px;
padding: 0px 10px 10px;
width: 180px;
}
#aside-1 {
float: right;
margin-left: -400px;
margin-right: 200px;
}
#aside-2 {
float: right;
}
div {
overflow: auto; /* Block formatting context */
margin-right: 400px;
padding: 0px 10px 0px 20px;
}
This works fine in Firefox and IE>6.
However, what happens in Chrome and Safari is that the margin-right of the div isn't calculated from the right boundary, but is instead only calculated from the left of aside-2. This causes the div to be 200 pixels (width + padding of sidebar-2) too small.
What causes this Webkit behaviour and how can I fix it?
Anyway, thanks a lot for your help in advance!
OK, so I tested a bit more and came up with a simple solution):
Just give the div a fixed width. This of course only works if your layout is based on fixed widths, which is the case for me.
Try with CSS RESET, that should work.
Here's one : http://html5doctor.com/html-5-reset-stylesheet/