2 posts tagged “css”
After a painful struggle with an odd visual bug, I can fully declare victory and share my learning with The Internets.
To the Point
I was going to give a succinct problem and solution here, but I honestly have no idea what the reason is behind what I'm seeing. What am I seeing? Firefox rendering my markup differently once the Gecko rendering engine gets a hold of it, specifically puking when a DIV was in an A and a P inside a STRONG. With that said, there's a lot more markup and CSS involved than simply those 2 nested tag examples. This may only be helpful for you if you noticed Firefox is rendering your markup differently than it's written (thank you, Firebug!).
Background
Above is what the visual bug looked like. What was particularly
annoying about this bug was its random frequency. When you reloaded the
page, sometimes all of the member images would sit in the left corner
like they were supposed to.
I traced the problem down to the following rendering difference (using HTML 4.01 Strict Doctype):
Correct HTML
Rendered HTML:<span class="clear">
<a href="score.php?id=X&photo=X">
<img class="winner" src="img/global/scored.gif"/>
<img class="photo" src="img/submissions/0/m/xxxxx.jpg"/>
<img class="spaceball" src="img/submissions/0/m/xxxxx.jpg"/>
<div class="member">
<img class="avatar" src="img/users/0/s/xxxxx.jpg"/>
</div>
</a>
</span>
<span class="clear">
<a href="score.php?id=X&photo=X">
<img class="winner" src="img/global/scored.gif"/>
<img class="photo" src="img/submissions/0/m/xxxxx.jpg"/>
<img class="spaceball" src="img/submissions/0/m/xxxxx.jpg"/>
</a>
<div class="member">
<a href="score.php?id=X&photo=X">
<img class="avatar" src="img/users/0/s/xxxxx.jpg"/>
</a>
</div>
<a href="score.php?id=X&photo=X"> </a>
</span>
The Fail Train is highlighted in red. Firefox hits the DIV tag inside of the A tag and decides that the A tag needs to be closed. I don't know why. There's no validation rule that says a DIV cannot go inside an A tag. From that point on, it's doing all kinds of wacky stuff - inserting the A tag inside the DIV and an empty A tag following it?
I've isolated just this bit of HTML to a page and tried to reproduce the visual bug, but it seemed to work every time. When the rest of the HTML was re-introduced, the bug reappeared. No CSS was being applied to the markup.
Help me Obi-Wan
As engineers often do, I took an educated guess at a fix without fully understanding why I was getting the incorrect rendered markup. Since it was the DIV it was hitting that caused the A tag to prematurely close, what if it weren't a block-level element? After all, that was a difference between the IMG tags it was still encapsulating and the DIV it was not. So I swapped the DIV out for an EM. It worked. It worked every time I reloaded the page.
A related problem was a P tag sitting inside of a STRONG tag. Again, I don't believe there's any validation rule which states this is invalid, but sure enough Firefox would sporadically end the STRONG tag when it hit a P inside of it.
Correct HTML:
<div class="number clear">
<a href="score.php?id=X&photo=X">0 comments</a>
<strong class="no">
<p class="z">Score:</p>
<p>hidden</p>
</strong>
<p>5 scored</p>
</div>
Rendered HTML:
<div class="number clear">
<a href="score.php?id=X&photo=X">0 comments</a>
<strong class="no"> </strong>
<p class="z">
<strong class="no">Score:</strong>
</p>
<strong class="no"> </strong>
<p>
<strong class="no">hidden</strong>
</p>
<strong class="no"> </strong>
<p>5 scored</p>
</div>
Like the DIV in the A problem, I simply made the P tag an inline-level tag and Firefox was happy. This seems like a Gecko rendering bug, but I'm not certain. Hope this helps some people out.
If you find out the reason for this, please let me know in the comments. Thanks!
posted by Ryan Gillespie
Firefox 3 was released about a month ago as of this post. It's definitely zippier, which any user can love. And it's now Acid2-compliant, which CSS nerds love. The people who don't love it? Those of us who have to fix our code to play nice with its new rendering engine. Yeah, we can hear the CSS evangelists screaming "Well if you wrote it 'correctly' the first time..." (quotes on the fictional statement ours)
Below are got'chas we faced when Firefox 3 users started coming to our site. Sort of a CSS Firefox 3 vs Firefox 2 cheat sheet.
Floats
Widths and wrapping floats
The main problem here is that the width of the parent element (the red box in the image below and the 2nd LI in the code below) is unspecified, but its children elements are floated and do have specified widths. The parent's parent (the UL in the code below) has a width applied that forces the DIV element to wrap. This works as it should across all browsers. Where Firefox 3 gets you though is the actual width of parent element, despite the fact that the element wrapped, is equal to the total width of all its children widths. Before, in Firefox 2, the parent width would be equal to the right edge where the child elements stopped (the red box in the Before in the image below). Now, however, you get the wider parent width (the red box in the After in the image below).
Example Code:
<ul style="width: 300px;">
<li style="float: left; width: 100px;"><img .../></li>
<li style="float: left;">
<p style="width: 200px;">Today at 2:00p</p>
<div style="width: 100px;">John Doe</div>
</li>
</ul>
Solution:
For our purposes, we just specified a width for the parent element. If you were to need a parent element that required a mutable width, we're not sure how that would be handled.
Leading edge of the unfloated
Okay, the first was was a pretty specific and hairy one. This one's bound to be more common.
It's perfectly valid to have a non-float next to a float. The non-floated will sort of appear to float when it's really just wrapping around the float. The got'cha here is bounding box for the non-float is actually the same edge as the float now (the red box in the After in the image below) whereas before the bounding box's edge was equivalent to the opposite edge of the float (the red box in the Before in the image below). This means paddings and margins are not applied the way you would expect them anymore; also, if you are changing the background color of the non-float on :hover, it will put a gnarly colored box over your floated element.
Example Code:
<div style="float: left; width: 100px; height: 100px;">.</div>
<div style="padding: 0px 4px;">Text</div>
Solution:
For our purposes, we specified the non-float to be a float to allow our element to "push" off the other float and to prevent our :hover from putting a colored block over our other floated element.
Negative z-index
It's recognized now.
Our bitterness over overlapping struggles with Son of Suckerfish and our cavalcade of relative and absolute positioned elements aside, you can specifiy a negative z-index in Firefox now and it may have made all of your anchor tags unclickable. In IE, they are still clickable.
Example Code:
<a href="#hello" style="position: relative; z-index: -10">World</a>
Solution:
Set your HTML tag to be a negative z-index lower than the z-index you're using on your A tags. In the example above, a negative z-index of -20 applied to the HTML tag will make the link clickable.
Inline-block element
It's recognized now... and it's breaking your clearfix
Once we get over our kerfuffle with updating the code, we're sure we're going to be happy to finally have inline-block in Firefox at our disposal.
The problem, and the solution, here is simple. Clearfix (thanks, Position is Everything!) makes the tag it's applied to inline. It's pretty common that you had it previously applied to a block element that isn't explicitly defined as a block element in your CSS (like a DIV).
Example Code:
<div class="clearfix">I'm not on top until I'm declared a block</div>
<span>I'm on bottom</span>
Solution:
Obviously, specify your elements as blocks, but also push your clearfix CSS as high up in the file as you can, such that it doesn't override any of your block specifiers.