Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Makosuke

macrumors 604
Original poster
Aug 15, 2001
6,801
1,523
The Cool Part of CA, USA
I was working on a relatively simple layout recently, but got confused when Gecko added a small gap under an image that wasn't there in Safari. I messed around some and got it down to a simplified testcase that told me it's in some way related to an inline image getting line spacing below it. Here's an example:

http://steelbluepanic.com/temp/funny-margin-testcase.html

(That's a white blank png in a DIV, margins and padding of both set to zero, red lines added to illustrate.) In my layout all I needed to do was set the img to display as block, at which point everything was nifty. But I like to know why.

I'm sort of guessing this is because the image is treated as if it's sitting on the baseline of a line of text, and so there's a gap below for the descenders; anybody know if this is correct, or is there something else I'm not understanding?

Also, I'm weirded out by the fact that with my more complex layout it did NOT leave that gap in Safari, but did in Camino. Since my simplified testcase DOES show the gap in Safari as well, they were obviously interpreting some inherited style differently, which is odd because I wasn't doing anything that complicated, and I don't see what I could have done to the containing elements (not much) to cause it to leave off that space in Safari.

Any standards gurus wanna point me in the direction of enlightenment?
 
Yup you hit it, at least around the corners. I've come across this myself while helping someone else on this forum. It's a baseline issue.

Remedy, add the following CSS property to the img.

vertical-align: middle;
 
DIV's are blocklevel and so are images. Nothing is inline here.

Angelwatt's response is right on for a dynamic layout like that.

If it's a static layout you could simply define the the height property in the class for the title to 50px, same as the image. Of course in your example you display a 1px image border, so 51px would be perfect alignment (red box within red box). Using static values forces the browser to align block level elements properly across all browsers. Plus, in a real situation like a header template, more than one image is involved so I'd specify the total height and width in the CSS for your title element and also add vertical-align: top so all images display orderly since image slicing results in that type of layout.

I mention this because people doing templates will find this useful, and what you're doing will remind folks of that.

-jim
 
I see the gap in Safari, so I don't quite see the problem as you do, but add this line to your stylesheet and it should do the trick:

.title img {display:block;}
 
DIV's are blocklevel and so are images. Nothing is inline here.
Huh? I assume you mean that I should be making the image block-level (which I am) as opposed to that they are by default, which I'm pretty sure they're not.

Regardless, thanks for the tips and clarification from everybody; sounds like my semi-educated guess was correct.

Given the specifics of my actual layout (single full-width banner image) setting display: block makes much more sense than messing with the baseline and leaving it inline, but that clarification will definitely be handy the next time I'm working with a sliced or otherwise multi-image DIV.
 
Let me rephrase myself... div's are blocklevel and images inside INHERIT that property by default (due to the cascading nature of CSS2).

Block level is defined as having a line break before and after the element, inline means the opposite. Your blank line showed up BELOW (not to the right side) in Safari because it treated the image as block level. I suggested applying static dimensions so the browser to bypass formatting, another user added alignment since you used dynamic heights so the browser would position the image element regardless of the break underneath.

Not that anyone would add style="display: inline" to all images inside of div to align them properly, it's easier just to do the tricks we used here. But technically, that's proper CSS when you need to align multiple images, to override the inheritence and remove all line breaks for cross browser compatibility.

-jim
 
I do appreciate the elaboration, Jim, but I'm still not lining up what you're saying with what I'm seeing. Maybe I'm just being really dense and reading what you're saying backwards, but I do want to understand this.

Am I correct that you're saying that, in this situation, with no display property set in the stylesheet, that the IMG itself is inheriting block from the DIV it's in? If not, I honestly apologize for being dense.

If so, I'm seriously confused, because it sure seems like the IMG is being treated as an inline element. If, for example, I use Safari's Inspector on my example page, the IMG's computed display is inline. Similarly, if I explicitly set it to display: inline, it doesn't change the layout at all.

The space below it isn't coming from wrapped whitespace, it's coming from the space reserved for the descenders in the inline of text that the image appears inline in, because (as angelwatt was saying) the implied vertical-align: baseline setting puts the bottom of the image on the baseline of the line of text it's on. Adding some text beside it illustrates this pretty clearly, and it's why either adding display: block to the image or vertical-align: middle will both "fix" it, in one case by making it a block-level element and in the other by centering the image on it's implied line of text (which, since the default line-height is smaller than the height of the image, leaves no empty space above and below).

Once again, if I'm misreading what you're saying and disagreeing only with myself, my honest apologies. I just like to "get" stuff like this, and I want to make sure what I'm thinking is what's actually happening.
 
Am I correct that you're saying that, in this situation, with no display property set in the stylesheet, that the IMG itself is inheriting block from the DIV it's in? If not, I honestly apologize for being dense.

You're not dense, and you're right on the money. That's how CSS is supposed to work, but most of the browsers out there have relaxed standards in terms of the rules of inheritence. Safari, as you learned and so do all developers who deal with the frustrations of cross-browser rendering, is not so relaxed.

Since you mentioned there is no whitespace and no text - and you didn't specify a height in the parent div (important) - that line you saw below the image was a block level line feed. Changing alignment or setting static height both override the problem.

I'm pretty confident of this, but this is open to discussion if someone out there disagrees.

-jim
 
It's out of my league to debate how the box model works - I still have trouble from time to time. I know enough to validate and make it work is all.

...and don't even start on 'float!'
 
The linefeed I spoke of was from the parent div which had no height specified. Maybe the reason it displayed below the inline image was because that's the natural flow - inheritance says when the parent (blocklevel) is different than the child (inline) the parent wins, as it does also in a tie if I recall. Some browsers handle this situation differently (key: when parent static height is not set, not just block vs inline) so it takes an alignment or static height/width property to resolve the very specific situation. I'm a big fan of using widths/heights in parent settings, it solves so many potential issues with flow across all browsers, then alignment is only necessary to override the default.

This is getting silly, I admit it, but one thing is for sure -- the fixes stated work, regardless of the confusion I might be having as to cause! I think I contradicted myself about 3 times, just trying to grasp what's going on "under the hood". I'm interesting in finding out, if anyone at this point gives a crap and knows for sure. heh

-jim
 
The issue is a fairly straightforward one.

Your image is inline. In other words it is being treated somewhat like a big letter sitting on the baseline.

The space underneath is the space that would accommodate a descender in a letter. Type a 'g' in there and you'll see that.

Some people have commented on the cascade, block level elements, and inheritance:

Images are by default inline elements, and display does not inherit, so the cascade does not apply here.

inheritance says when the parent (blocklevel) is different than the child (inline) the parent wins, as it does also in a tie if I recall
This would appear to be wrong. Not all css properties inherit. Font-size does for example, but display doesn't. The display property depends on the selector, and failing a selector it takes the default value.
 
youre doc type is supposed to be strict, but you didnt type it right, and its not being parsed as strict (or transitional) as firefox. it looks like safari defaults to transitional when theres a typo in the doctype.

anyway set it to transitional, or use the proper strict tag, and it works


HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

also need to set the height of the div to 50 in strict, dont need too in transitional
 
youre doc type is supposed to be strict, but you didnt type it right, and its not being parsed as strict (or transitional) as firefox. it looks like safari defaults to transitional when theres a typo in the doctype.

anyway set it to transitional, or use the proper strict tag, and it works


HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

also need to set the height of the div to 50 in strict, dont need too in transitional

The DOCTYPE in place is correct as is. There's no need to change it. He's using XHTML not HTML.
 
my bad, the problem is the strict tag though. you need to set the height of divs in strict

Well, that's not correct either. The div does not "have to" have height set. There's no specification stating that, but setting the height does override the problem, but breaks for dynamic content. This problem was actually solved a couple days ago with a couple possible solutions. One being setting the vertical alignment (the 2nd post).
 
my bad, the problem is the strict tag though. you need to set the height of divs in strict

What? Strict is XHTML. Height is in the CSS.

The reason has already been explained. The document is displaying correctly. There should be a gap under the image, in the same way there would be a gap under a letter.
 
What? Strict is XHTML. Height is in the CSS.

The reason has already been explained. The document is displaying correctly. There should be a gap under the image, in the same way there would be a gap under a letter.

oh really? set it to transitional then
 
oh really? set it to transitional then

Safari and Firefox. Same in both (adding a 'g' to show baseline and inline effect). Remove the 'g' and it does indeed go away, but what we are concerned about here why the behaviour is happening, and the best way to see that is to set strict. It is interesting though that it goes away in transitional. This is probably to do with the interpretation of the baseline in the absence of letters.

As we said, it's displaying correctly: It's strict. It's sitting on the baseline. It's inline. Set the img to display:block and the gap goes away.
 
It's been established in an XHTML strict environment (which the OP is using, check their source) an inline image placed inside a block level div will result in a text line which is at the baseline, and we see the tiny descender area of that text line. Okay, I'm cool with that as to the "why". Now, about avoiding such issues...

Others picked up on the fact that setting height in the parent DIV resolves the issue - and I want to comment this is probably the more common solution, i.e. much like an informal best practice, compared to overriding image alignment in a strict environment. Specifying parent heights/widths ensures every image, down to the pixel, ends up where it should, spaced statically (and in some cases, absolutely) for headers, footers, sliced images with HTML in a div, etc. which are real world application of these principles.

Just trying to tie a nice little bow around this!

-jim
 
It's been established in an XHTML strict environment (which the OP is using, check their source) an inline image placed inside a block level div will result in a text line which is at the baseline, and we see the tiny descender area of that text line. Okay, I'm cool with that as to the "why". Now, about avoiding such issues...

Others picked up on the fact that setting height in the parent DIV resolves the issue - and I want to comment this is probably the more common solution, i.e. much like an informal best practice, compared to overriding image alignment in a strict environment. Specifying parent heights/widths ensures every image, down to the pixel, ends up where it should, spaced statically (and in some cases, absolutely) for headers, footers, sliced images with HTML in a div, etc. which are real world application of these principles.

Just trying to tie a nice little bow around this!

-jim

Yes, but it's hardly a solution in the many environments where the content is database driven, and where simply setting the image to be display:block is already a solution that works without for the need for this kind of once-only setting.

The rationale of the above reads very much like the content that CSS is designed to escape you from ('sliced images' and so forth). If you're going to need to specify div heights and use sliced images then there's little need in this kind of CSS anyway, and you may as well go back to tables and shims.

For those of us who are building content driven community sites, for example, the principles behind why things are happening and the CSS only solution is essential.

In fact, it seems the two CSS solutions here are the ones that actually work whatever the occasion so I'm not sure why the insistence on a more complicated solution that is more prone to error, less simple to change, less robust, and unnecessary.
 
Well, I said "common" solution, not the end all of solutions. Now I'm off subject. I'll give you and others the final word, this is getting beyond silly now - everyone here recognizes there will be exceptions to all rules/situations, the word common does not mean 100% of the time in terms of solutions, and there is more than one solution at hand even for this issue, in limited scope as it is. Use this thread as an example there are many ways to skin a cat.

-jim
 
Well, I said "common" solution, not the end all of solutions. Now I'm off subject. I'll give you and others the final word, this is getting beyond silly now - everyone here recognizes there will be exceptions to all rules/situations, the word common does not mean 100% of the time in terms of solutions, and there is more than one solution at hand even for this issue, in limited scope as it is. Use this thread as an example there are many ways to skin a cat.

-jim

No doubt. But reading through this thread there are 2 solutions given:
1. display: block; (or using vertical-align)
2. setting heights to everything, plus lots of incorrect explanations about the cascade and other things.

Yes, there are many ways to skin a cat, but if there's a simple and easy way, then there is no need to give a second way that is more complicated, doesn't work as well, and is accompanied by incorrect explanations while stating it is more common.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.