<img> positioning behavior - html

I can't seem to wrap my head around how img tags behave alongside text in an html page.
I've removed margins and padding, but there always seems to be some extra space under the img or some other unexpected behavior. I'm sure theres quick CSS workaround using absolute positioning or negative margins but I'm looking for a more general solution.
Question: Can someone explain how img tags are positioned, specifically why do they get offset vertically when alongside text?

If you want the <img> to be an inline element, you can use the vertical-align CSS attribute to specify how the image will be aligned relative to the line of text it appears in. This page has examples under the "vertical-align on inline elements" heading.

The key to getting your text to wrap around your image is setting the float attribute like so:
img {
float:left;
display:block;
}

CSS has two types of display: attributes: block and inline.
Inline is like text. It streams along, wraps at the end of a box, stuff like that.
Block is chunky and has margins and padding and width (either calculated or derived).
It doesn't make a whole lot of sense, but <img> is actually an inline element, along with <a>, <abbr> and many others. What's happening is that the image is actually being rendered roughly equivalent to letters, and it just happens to not be 12pt tall, but maybe 130px or whatever your image is. That's why it sticks up.
Declare <img style="display:block;" src="image.png" /> to get it to behave like the box most people think it is.

IMG elements get positioned just like any other inline element.

What you see under the img is the space needed for the descendant part of a glyph like g or j. An image behaves just like a letter and sits on the baseline.
img
{
display: block;
}
Will fix it for you.
An experiement that might shed some light:
<p style="font-size: 1em;">Lorem ipsum dolor <em style="font-size: 800%;">sit</em> amet.</p>
Think of the <em> as a ~128px high image (if 1em is 16px that is).

If you want more control over your image positioning, wrap your image in a DIV and control the positioning of the DIV. You can float the div if you want to intermingle it with your text.

This might not be relevant in this particular case (hopefully the advice from previous answers should solve your problem), but if you're finding you're getting unexpected extra space around elements, make sure that you've removed the default padding, margins etc. that browsers often add to elements (and of course different browsers often add different amounts of padding, margins etc.
If you make sure you've zeroed margins and padding etc. by using
body { margin: 0; padding: 0; border: 0; }
at the start of your CSS, you can then add any padding and margins etc. without having to worry that the browser's defaults are going to cause any unexpected spaces, and hopefully fewer inconsistencies between browsers.

Related

Mystery white space underneath image tag [duplicate]

This question already has answers here:
Image inside div has extra space below the image
(10 answers)
Closed 7 years ago.
I just changed the header image on my site from
<div style="background-image... width=1980 height=350>
to using
<img src="... style="width:100%;">
so the image would scale down which it now does...
But now I have this mysterious 10px gap or so.
I've checked the inspector in Chrome, and I just can't see what's causing the space. I've searched other posts but can't find anything that applies.
Anyone out there have any idea? Appreciate any help, Bob :)
Look at this line of text. Notice there are no letters that breach the baseline.
Now look at the following sentence:
By just crossing the bridge he probably got away.
Note the letters j, g, p and y. These letters, known in typography as descenders, breach the baseline.
Source: Wikipedia.org
The default value of the vertical-align property is baseline. This applies to inline-level elements.
Your img is inline-level by default and, like text, span, input, textarea and other inline boxes, is aligned to the baseline. This allows browsers to provide the space necessary to accommodate descenders.
Note that the gap is not created by margin or padding, so it's not easy to detect in developer tools. It's a slight elevation of content from the container's bottom edge resulting from baseline alignment.
Here are several ways to handle this:
Apply vertical-align: bottom to the img tag. In some cases bottom won't work, so try middle, top or text-bottom.
Switch from display: inline to display: block.
Adjust the line-height property on the container. In your code reference (since removed due to linkrot), line-height: 0 did the trick.
Set a font-size: 0 on the container. You can restore the font-size on the child element directly, if necessary.
Related:
Why is my textarea higher up than its neighbor?
By default, IMG is an inline element. You need to set your IMG tag to be a block element, which can be accomplished with this style:
display: block;
Add
display: block;
to the <img>.

CSS method instead of display:run-in; to position a block inline?

Since I am having trouble with Firefox about positioning a block element by nature (header) to be inline by using display:run-in; i'm asking you for your help ! been searching for quite some time now and I cant find which CSS method could be used instead of just applying display:run-in; to the element, which is supported in all the major browsers. It is crucial that i position the element this way.
Anyone knows a method how to do this ?
If you'd like to display your element as a block element, but would position it inline, then
display: inline-block;
will do the trick for you.
The MDN still lists run-in as an experimental value, so we shouldn't be too surprised if it doesn't fully function in Firefox at this time.
As for options, there are at least two you could use: display: inline and display: inline-block.
Inline might suffice if you don't need the properties of a block element on your header. Inline-block keeps it as a block element, so you can still do nice things like give it width, height, margin and so on.
View them on JSFiddle.
Alright i found a solution ! :) Using display:inline; in a combination with float:left; will make a block element by nature use space only as much as he needs, not full 100% of its parent element.
There is just one problem with this tecnhique if you are using bigger font for lets say a heading and want to add a paragraph right after it (on the same line). If the headings font-size is a bit bigger, heading could take 2 or even more lines of space in height where paragraphs text should be,and you will have a small gap between header and another row of paragraph under it. The solution is to add display:block; and margin-top:Xpx; to the paragraph element to align it as needed.

Avoid overlapping rows in inline element with a background color applied

I got a CSS question related to this fiddle: http://jsfiddle.net/r584e/
Here the relevant screenshot
Sometimes I've got to style an inline element in a such way, trying to almost avoid space between rows and applying a background only under the text. As you can see, the first paragraph has a link inside, in which I set line-height: 1em . The paragraph on the right has instead a line-height: 0.8em;. (Note: I know in this way I could roughly cut some letters - like q,g,p,... but the text is uppercase so it's not really a problem)
In the second paragraph rows are actually closer (as I want) but unfortunately each row is also partially overlapping the previous one (unless you remove the background color applied) and this is not good (e.g. see the word «uppercase» on the bottom), so here my questions:
how can I get the rows closer (like paragraph on the right) without them overlapping each other and defining a background color (no matter the element in which it is applied but it has to stay under the text, not fill a whole block)
Optionally there is a way to add an horizontal padding to each line of text?
Feel free to change the CSS and/or markup. I'm looking for a pure CSS workaround.
An optimal solution should work on modern browser and, if possible, at least from IE8+
Thank you in advance. =)
Edit:
About 2nd question, using #thirtydot solution I can add space (to the right) using white-space: pre-wrap applied on the span element
Simply add a wrapper element inside the em, such as a span, and apply position: relative.
See: http://jsbin.com/axefaf
<a href="#"><em style="line-height: 0.8em">
<span>This is an uppercase multirow text inside a link element</span>
</em></a>
span {
position: relative;
}
This works in all modern browsers and IE8, but does not work in IE7.

How to make height squeeze with css

I've got an example mht file here that will help demonstrate my issue; if you are using FF then this addon will help you view the mht file. You will prob need to download the file and view it locally since github doesn't provide the right mime type for the file.
Basically my issue is this that I have a div which is 32px in height surrounding another div which is 29px in height, and I have no idea why the former is 32px tall.. It should be 29px tall afaict.. I don't want to set height:29px tho because if you resize the window so that the nav items take two lines then the height shouldn't be 29px for either div.
So what is wrong here?
make the following changes-
(-) to make your ul and wrapper div bottoms to align change class #navigationSecondary ul.base
to have a display:table; instead of display:inline-block;
(-) to remove the 3px of blue at the bottom change class #navigationSecondary to have padding:0; as sugested by Marcel.
the use of display: inline-block; on the ul.base is the cause.
when you use that it formats an element like it were inline (it only formats the actual content of the element like a block), so ul.base will have the usual 2-3px top and bottom "padding" that a normal inline element has. It's not really padding it's the leading vertical spacing i.e. it's what gives lines enough space to provide for the ascenders and descenders of letters like g, h, p, etc.
the use of it here is to make it seem like your ul is containing the floated child list elements. To make an element contain it's floated children there are other ways to do this, one way is, on ul.base
remove: display: inline-block
add: overflow: hidden;
[UPDATED] re the tabs.. sorry I didn't see them before I started
Here's the "float everything" solution to containing child floats as it applies to your code, with some other suggestions too
.menuContainer all it needs is position:relative; and the border-right rule
.navigationSecondary float it left with a width of 100%; (you can remove z-index it's not doing anything)
.wrapper float it left with a width of 100%, remove the height
ul.base doesn't actually need anything but remove the display-inline-block.. it's not containing the child lists but there's no effect involved, if you want to you can float it left with a 100% width too
[UPDATE 2]
I just copied this to a plain HTML document and I think that just changing the DOCTYPE to an HTML4 transitional one solves the problems with no changes to the code ?? (why that should change the display be I don't quite know! - but the use of "target=_parent" is "not allowed" in Strict Doctypes so that'll be why it's not validating)
I'll put it in JSBIN so others can try it out on various browsers
I changed it to:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
jsbin (with original HTML5 doctype) is here http://jsbin.comhttp://jsbin.com/agihe5/2/ - shows gap
jsbin with changed Doctype - but no changes to CSS code - with flash video to show dropdowns are working is here : http://jsbin.com/inare6/2 - no gap!
jsbin with no changes to Doctype, suggested changes to code and the flash insert to show z-index working is here: http://jsbin.com/iriya4
with the latter, code changes are detailed in the source, they have moved to the bottom of the snapshot CSS
I've tested the changed Doctype version as working in IE7, IE8, FF3.6.15, Safari4 (Win) and Chrome
Providing a test case which requires me to use Firefox and download an extension to view it is highly annoying.
I just did it anyway (purely because of the bounty), and the only change you need to make to your test case is:
On #navigationSecondary ul.base, add vertical-align: top.
The extra height is gone.
Here's a demo based on #clairesuzy's demo titled "jsbin (with original HTML5 doctype)".
(The only change was adding the aforementioned CSS rule):
http://jsbin.com/agihe5/3
The other answers may work (I didn't test them), but (providing I've understood the issue properly), this is by far the easiest fix.
Apparently #navigationSecondary has padding:0 0 3px; set in unnamed-1.css on line 2.
Everything inside ul.base has a height of 24px. Itself has a padding of 2px. So it's height is 26px. It's parent div.wrapper has a height of 29px, 3px extra. It's not caused by the 3px padding of div#navigationSecondary. Nothing is contributing the extra 3px so I'm suspecting a float issue. Anyway I managed to fix it by floating 2 divs.
Add float: left; width: 100%; to div.wrapper and div#navigationSecondary.
Remove display: inline-block; from ul.base.
Floating div.wrapper and div#navigationSecondary collapses them to their nearest floated child element, in this case li.base, and removes the extra 3px. 100% width brings back the stretch.
Hope this helps.
<body style="zoom:0.99; -moz-transform: scale(0.99); -moz-transform-origin: 0 0;">
adjust accordingly, and change hight and width around
Of course. This is simple. A very elementary element positioning issue.
inline-block default vertical-positioning
ul.base is an inline-block. which means that it has spacing calculated like a block, but positioned like an inline-element.
The default positioning of inline-element is to align on the baseline of text. However, text goes below the baseline for letters such as g, j, q etc. This is called "descenders".
The height of a box is always from the top of the font to the bottom of the descenders.
The wrapper takes on the height of its children. Which means that the inline-block ul.base, positioned on the baseline.
Your font at that particular size happens to have a 3-pixel descender. Voila. Your mysterious 3-pixel gap is merely the text's descenders. And your inline-block element is positioned on the baseline (i.e. on top of that 3 pixels).
Tests to confirm that this is right
Change font size. You'll see that 3-pixel changes. Change font size to small enough and it'll reduce to a 1px descender. Your so-called "gap" will shrink.
Change ul.base to something other than an inline-block (of course you have to add something to clear the floats inside). It will no longer have the 3 pixels at the bottom because a non-inline element is not positioned on the baseline.
Position ul.base on the absolute bottom instead of the default (baseline). That 3-pixel gap disappears. Use this CSS rule: vertical-align:bottom
Morale of the story
You always have to be careful with baseline positioning whenever you use inline-block display style.
Off topic
Handling font descenders is especially frustrating with Asian languages. As you know, CJK languages do not have characters that go below the baseline. However, they are typically placed on the baseline (so that they can inter-mix with other European languages, which have descenders). However, when one places a block of text with a background containing only Asian characters, the text will look like it is moved to the top, with an ugly empty gap on the bottom (the descender).

CSS problem height from top

using css how do I put a span on top of other spans.
I have several spans in the page and at the end of the page I have this
<span id="lastSpan" style=" margin-left:726px; margin-top:30px;"></span>
problem with that is that it never goes to 30px down from top. and stuck at same height.
any help will be appreciated
thanks
Span's are inline elements and don't adhere to margin on top and bottom. You need to set it to display: inline-block if you want margin to work.
spans are inline elements. you cant apply margins to them. use a div if you need a generic container with margins/height.
Inline elements can't be styled the same way as block elements. For one, they are (entirely?) unresponsive to margin and height commands. The solution is to add display: block; to your styling to force block styles.
span wont accept margin properies, cos it is inline element. You can change it to block element by display:block, float:left/right or position:absolute
This might be captain pædantry to the rescue, but that spans are inline-level has little to do with this. The fact that most (all) browser's house-style sheet implicitly sets the span's property on display:inline does unless the author or the user explicitly overrule this does though. As far as I know, the W3C does not define what the house style of browsers must be, but they do give some pointers for interoperability.
Of course, this might not be as relevant here, but there are actually some places where browsers don't pick their styles all the same. Notably Safari and Chrome do not place a dashed border under abbr by default while Firefox and IE do. Also, some browsers space paragraphs by using margin-top:1em; while others use margin-bttom:1em, in most cases this doesn't matter but there are some cases where defining explicitly which of the two you want in your site is in fact needed for a consistent look.