css float troubleshooting - html

i've got a very simple CSS example detailed below. The .entry class generates a simple box with a 1px black border. the example below, will render "123" within the box and "abc" and "xyz" outside the box because those elements are tagged with float left and right. My goal is to have .box1 inside .entry aligned left, and .box2 inside .entry aligned right.
<html>
<head>
<style type="text/css">
.entry
{
width: 400px;
border-style: solid;
border-width: 1px;
border-color: #000;
}
.box1
{
width: 75px;
float: left;
}
.box2
{
width: 300px;
float: right;
}
</style>
</head>
<body>
<div class="entry">
123
<div class="box1">abc</div>
<div class="box2">xyz</div>
</div>
</body>
</html>
it renders fine in IE but not firefox

Since floats are taken out of the normal flow, their surrounding boxes will collapse.
I'll first explain why it is working in IE. You have given it "layout" by setting a width or height on each element. It's width in this case. See hasLayout for more about this. This is very handy as it will also solve most of any other IE bugs you come across.
The magic bullets are:
height: 1%; /* or any other value. IE6 wrongly sees height as min-height. */
or if you aren't in a position to set a specific size, use
zoom: 1; /* A IE only property. Doesn't validate, but doesn't cause any harm either */
So, to your problem, making it working in a proper browser, there are a couple of solutions. If you set the parent of the floated elements to have float as well, the box will stretch around the child floats. Although this might cause trouble further up the DOM, I don't know how the rest of your markup is.
An easier way can then be to set overflow:hidden; which also fixes it. But now you have to watch out for long url's, code-snippets, or anything else that might accidentally push out of the div. If you're doing the whole site yourself this is normally not a big problem, if you're handing it over to someone to use in a CMS, chances are slightly larger. Still worth taking the risk though, if you can't solve a myriad of floats around your layout.
Adding an element at the end to clear the floats is also a way of doing it, but I find the former ways easier.
I better stop blabbering, you probably want to see the code:
.entry {
width: 400px;
border: 1px solid #000;
float: left; /* Option 1 */
overflow: hidden; /* Option 2 */
}
.box1 {
width: 75px;
float: left;
}
.box2 {
width: 300px;
float: right;
}

Since you have no Doctype, you are triggering Quirks mode. This renders browsers significantly more buggy then Standards (AKA Strict) mode. Internet Explorer is the worst offender here.
I suspect your problem is that you want the border of .entry to extend around .box1 and .box2. See containing floats for more detail and Methods for Containing Floats for some nicer solutions..
Of course, your problem might be something different. You were rather vague.

You need to clear your floats for FF:
.entry:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
I would do it for IE as well:
.entry { min-height: 10px;}
Otherwise, I don't see why it wouldn't work...

Try this; I've tested it and it works in FF 3, Safari 3.2, Opera 9.6 and IE 7.
(The reason I added the extra line of text in the .box2 div was to ensure that the .entry div would stretch vertically as extra content was added).
<html>
<head>
<style type="text/css">
.entry
{
width: 400px;
border-style: solid;
border-width: 1px;
border-color: #000;
}
.box1
{
width: 75px;
float: left;
}
.box2
{
width: 300px;
float; left;
margin: 0 0 0 75px;
}
.entry span
{
width: 400px;
float: left;
}
</style>
</head>
<body>
<div class="entry">
<span>123</span>
<div class="box1">abc</div>
<div class="box2">xyz<br>More text</div>
</div>
</body>
</html>

Try adding overflow:hidden (or auto) to .entry{...}

Related

Why does Firefox behave differently on collapsing margins?

Firefox renders a 100px margin at the top of div.p. It seems to be a margin collapse. But the computed height of div.p is 100px. According to the spec it should not do margin collapse. Is it a bug, or am I wrong here? Chrome renders as expect.
codepen
.s {
height: 100px;
width: 200px;
background: yellow;
float: left;
}
.p {
margin-top: 20px;
margin-bottom: 100px;
zoom: 1;
}
.p:after {
content: ' ';
display: block;
height: 0;
clear: both;
}
<div class="p">
<div class="s"></div>
</div>
I'm not sure why the traditional clearfix is not working, but here are three ways that do:
Like Kaiido said a *{overflow:auto;} works just fine to fix the issue. This also works as *{overflow:hidden;}.
If you don't want a blanket overflow, you can be more precise by putting overflow:hidden or overflow:auto to just .p. This also fixes the issue.
Finally, if you change display: block to display: table in your clearfix (.p:after), the issue also goes away.
I'm really not sure why the traditional clearfix is not working, but it isn't too hard to work around.

Responsive Layout with a Fixed Width Child Element

I want to implement the following responsive layout in a webpage (HTML5 & CSS3):
All three div tags are wrapped inside a div with max-width of 960px;
I want to keep the width of "Navigation" div fixed therefore the following styles are being applied on it:
width:90px; float:left; padding:5px;
How can I make the "Contents" div occupy all remaining space without specifying its width, while keeping the layout responsive at the same time?
Thank you.
#content{
margin: 0 0 0 90px;
padding: 10px 30px;
}
Just put everything in a wrapper div and specify it's width to 960px
It depends on the browser support you want (need), with only 3 DIVs in a IE6+ way is hard (I think it's actually impossible). You're best bet is with the CSS calc method on the Content's DIV
width: calc(100% - 90px); The CSS calc method has IE9+ support so you would need to take that into account, in IE8- you would still need to use percentages.
If you are wondering how to separate the IE9+ code, then simply use #media i.e. something like this:
#media all {
#navigator {
width: 90px;
}
#content {
width: calc(100% - 90px);
}
}
#media is IE9+ compadible and because IE8- do not can't make heads or tails of it it will not affect them. So it is safe to place the IE9+ code in it.
If you can modify the HTML a bit I would advice the following:
<html>
<head>
<style type="text/css">
#h {
background: #f00;
}
#n {
background: #0f0;
width: 90px;
float: left;
}
#c_container {
background: #005;
width: 100%;
float: right;
margin: 0 0 0 -90px;
padding-left: 90px;
box-sizing: border-box;
}
#c {
background: #00f;
height: 50px;
}
#container {
max-width: 940px;
margin: 0 auto 0 auto;
}
</style>
</head>
<body>
<div id="container">
<div id="h">head</div><div id="c_container"><div id="c">cont</div></div><div id="n">nav</div>
</div>
</body>
Note how the content has a separate container, with is floated one way and the navigator is floated the other way, this is to make sure that they are not on the same plane.
the #c_container has a margin-left: -90px to bring it to the same row as the navigator and a padding-left: 90px; to make sure that #c (the new content DIV) is now visible. The #c_container also has the #c_container DIV. Without it you would need another container DIV so the width would not be affected by the padding, but that is easy enough to add, so I'll leave it up to you.
If you would use another container DIV for the content, then that solution would be IE6+ compatible, while the one I gave you is IE8+ compatible.

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.

CSS fluid layout without tables

Everything online points me to stop using tables, which I've tried my best to do, but I've come across a problem which tables seems to be the only solution for. I have 5 inline-block elements that I want spaced evenly across 100% of the width of the page. I put a width of 20% on the style and set the margin and padding to zero. When I view the page, everything looks pretty good except for the horizontal scrollbar added to the page. If I put these elements in a 100% width table with 5 columns this isn't a problem. In this case do I need to use a table or is there a better solution?
BTW, I've tried this in both Chrome and IE8.
Update: Something I've discovered is that a ~5px gap is being inserted between my elements (found by putting a background-color on them). I have no clue why, as nothing in my styles denotes this:
<div class="links">
Previous
Current
Next
01/01/2011
01/08/2011
</div>
.links
{
white-space: nowrap;
width: 100%;
}
.links a
{
display: inline-block;
width: 20%;
padding: 0;
margin: 0;
color: White;
background-color: #4C8331;
}
Another update:
After JMC Creative pointed out my dumb mistake of putting spaces between the anchors that almost fixed the issue, but now there is one pixel of scrollbar. I see no inherited style that should cause this.
Try putting them in a container. Like so:
#container {
margin: 0;
padding: 0;
width: 100%;
}
#boxes {
float: left;
width: 20%;
}
Your html markup has a space in between the a tags. So therefore it's being rendered as 5 blocks which are 20% wide and 4 spaces of roughly 4px each. So you end up with 100% + 16px.
Edit
In order to solve the scrollbar that is plaguing you in IE, you could set up a conditional comment like so:
<!--[if IE]>
<style type="text/css"> .links { overflow: hidden; } </style>
<![endif]-->
Be sure your body and html set to margin: 0; padding: 0;.
Have you tried using overflow: hidden? Or more specifically overflow-y: hidden?
You want to float your anchors. Doing it this way works for me.
CSS:
.links {
width: 100%;
}
.links>a {
float: left;
display: inline-block;
width: 20%;
padding: 0;
margin: 0;
color: #fff;
background-color: #4C8331;
}
HTML:
<div class="links">
Previous
Current
Next
01/01/2011
01/08/2011
</div>
You may get a scrollbar or see some of the anchors wrapped to another line if there isn't room to fit them all on the page (ie, content overflows the width). I will note that I have seen IE get this wrong and incorrectly wrap when it shouldn't. It seems like a rounding issue and could be worked around.

Simple HTML/CSS positioning issue

For some reason I think I'm forgetting something here. Below is my code:
<style type="text/css">
#content {
width: 400px;
height: 100px;
background: orange;
padding: 10px;
}
</style>
<div id="content">
<h1>what</h1>
foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo
</div>
When that loads, it shows this:
http://grab.by/6Mhp
The text is not inside the box. Why...? And how to fix?
Add the style
word-wrap:break-word;
on your #content
#content {
width: 400px;
height: 100px;
background: orange;
padding: 10px;
word-wrap:break-word;
}
I don't think CSS will automatically break words into pieces to fit into the div. You could use overflow:hidden to hide the overflow. The example you already use should work fine if you have words that don't exceed the size of the div.
You can also use word-wrap:break-word but, IIRC, that requires either IE or CSS3 (though that probably represents a lot of browsers out there).