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).
Related
I recently designed a website (http://willryan.us/typefun01), mainly using Chrome while coding to test. I recently noticed that there are some weird things happening at the end of certain sections, (the gap after History, the overlap of Styles onto Anatomy).
I have a css reset in my stylesheet (not sure if that has anything to do with this), and I can't figure out what's causing this, and how to get the site to look like how it does when viewed in Chrome
The gap after History is due to:
#historyWide {
margin: 250px 80px 75px;
}
It could be remedied with:
div#content > div {
overflow: hidden; /* or auto */
}
You could also move the large top and bottom margins of elements inside the child divs of #content to padding on the child divs themselves. Anything will work as long as it's all contained by those child divs.
You're simply seeing the different ways that browsers handle imperfect layout.
If you want to avoid the gap after History you would want to use a padding in historyWide instead of a margin; the margin pulls aways elements while padding makes them bigger
On anatomy what's happening is that you're using the property "top" to modify #styles, this will move the element but the parent will reserve only the original space for the element. You will be better off working with margins and padding than with "top" if you have to keep a relation between the elements.
Lastly, i woulnt position elements with margins like you did with #stylesMono. I think you could better work with paragraphs to keep keep the vertical position and, from there, working with floats, margin and padding in the scope of the "p".
Ok, I am quite new to frontend development so please be nice if this is a dumb question :)
I understand that this may not be possible but when applying line-height to an element say an h1, the line-height applies extra space to both the top and bottom of that element.
This kind of makes sense, but i only want line-height to be applied to the bottom of the element so the tops of my h1, h2 etc can be alined perfectly with other elements.
This jsfiddle shows the problem: http://jsfiddle.net/zja4c/1/
This jsfiddle shows what i want to achieve but am forced to use negative margins: http://jsfiddle.net/25UTA/
The h1 with background colour of red aligns correctly to the top of the left div, but the text doesnt.
My question is therefore, is there a way to:
Apply line-height to only the bottom of an element or,
Align an element to the top of the space created by applying line-height somehow
Using line-height is your only option if you wish to maintain proper spacing across line-breaks. Padding will occur on the bottom of the block-level H1 element, as you pointed out. I think negative margins are your best bet, but you'll have to fine-tune it line up perfectly with a 50px line-height:
http://jsfiddle.net/25UTA/1/
If negative margins can't be used for some reason, you can use relative positioning and a negative top value to achieve a similar effect.
http://jsfiddle.net/25UTA/2/
Using em's or percentage font-sizes and line-heights might make this eaiser.
None of these answers reference elements with their display set to inline.
Line-height is a setting that refers to inline elements. Every answer so far has referred to using padding and margin, which don't work with inline styled text.
You can modify the positioning of text within its line with vertical-align. Here's a link to an article that goes into copious detail about the property and how it works:
http://christopheraue.net/2014/03/05/vertical-align/
A simple solution is to make the line-height 70% and add a little bit of bottom padding.
p, h2 {
line-height:70%;
padding-bottom: 3px;
}
In my knowledge its not possible to apply line-height only for bottom using css.
So you can try with padding as user1538100 said.
You could forget line height completely and use padding-bottom:
fiddle
So first a bit of meat to set the scene:
HTML
<div id="container">
<div id="inner">test</div>
</div>
CSS
#container {
width:300px;
height:150px;
background-color:#d7ebff;
}
#inner {
width:100%;
height:100%;
padding:5px;
background-color:#4c0015;
opacity:.3;
}
This will produce something that looks like this in all modern browsers:
Now I know this is the standards-compliant behavior (as I knew before, but reconfirmed in this post, and I also know that if I include this code in the inner CSS declaration:
box-sizing:border-box;
-moz-box-sizing:border-box;
-webkit-box-sizing:border-box
...it will adopt the "border-box" model and get the behavior that seems more intuitive to me, but I just found myself trying to logically justify the reasoning behind why this is the way it is and I was unable to do it.
It seems (on the surface of things) more logical to me for the inner box to always fill the container to exactly 100% of the container's width, regardless of the padding or border of the inner box. I run into this problem all the time when I'm trying to set the width of a textarea to 100% that has a border or something like a 4px interior padding...the textarea will always overflow the container.
So my question is...what is the logic behind setting the default behavior to ignore the border and padding of an element when setting its width?
The reason CSS uses the box model as:
+---------------------
| Margin
| +-------------------
| | Border
| | +-----------------
| | | Padding
| | | +---------------
| | | | Width x Height
Is because CSS is a document styling language. It was (originally) designed with research papers and other formal documents in mind, not as a way to make pretty graphics. As such, the model revolves around the contents, not the container.
CSS isn't a programming language, it's a styling language. It doesn't explicitly tell the document how it should be displayed, it suggests some guidelines the browser should follow. All of these can be overwritten and modified by an actual programming language: JavaScript.
Going back to the content-model idea, consider the following CSS:
p
{
background-color: #EEE;
border: 1px solid #CCC;
color: #000;
margin: 10px;
padding: 9px;
width: 400px;
}
height isn't specified, because the content defines the height, it may be long, it may be short, but it's unknown, and unimportant. The width is set to 400px because that's how wide the content (text) should be.
The padding is just a means of extending the background color so that the text can be nicely legible away from the edges, just like how you leave space when writing/printing on a sheet of paper.
The border is a means of surrounding some content to differentiate it from the other backgrounds, or to provide a border (go figure) between various elements.
The margin tells the paragraph to leave some space between edges, and with margin-collapsing, each group will remain evenly spaced without having to specify a different margin for the first or last element.
To maintain fluidity, width defaults to auto, which means the width will be as wide as possible:
without squishing the content unreasonably
without the padding extending beyond its container
Of course, in edge cases, the padding will extend beyond its container because the content might get squished. It's all about the content.
You might want to review the following at w3c: http://www.w3.org/TR/CSS21/box.html
The box model is such that the height and width pertain to the content area of the element. Padding is outside of that area which is why you see the inner box overflowing the outer one.
After padding comes the border, if any. Then Margin applies outside of the border. This means the elements actual width is defined as: Width + Padding + Border + Margin.
In effect, the css you have defines the inner box to have a 300px by 150px content area plus an additional 5px of padding beyond that which yields a box that is 310px by 160px.
Personally, I agree that the Width should include the padding. However, that isn't what the spec says.
As a side note, quirks mode does include the padding (and border) in the actual width. Unfortunately, quirks mode screws up so many other things that it's usually better to just deal with the w3c spec'd model than try and create all the css necessary to fix the other "quirky" things.
Another site (who agrees with you and I) is here: http://www.quirksmode.org/css/box.html
They mention that CSS3 includes the box-sizing declaration (as you've found) which is supposed to give you more control over which box model to use. It looks like just about everyone (IE8, chrome, Firefox) supports that which is good.
To answer your question, I think the logic is that it is all about the content; if you specify dimensions, these are the dimensions that the content is going to get.
But in the end it is just a choice that was made and that´s what we have to work with.
Look at the following picture:
Now consider what happens when you set the values width and height to 100% - should the padding and border just magically disappear from this picture? How would you as a developer ever handle that in a reasonable way?
width and height is width and height, border and padding is something else - to me it does't get anymore logical than that.
On the other hand
width and height is width and a height, but sometimes when you choose to set them to 100% they are also border and padding - now that would make no sense to me.
But then, one mans logic can be another mans nonsense, so i don't know if this will help you ;)
Although this may not have been an original intention of the CSS box model, another benefit is if you want something with an offset background image (e.g. the image is to the left or right of the text). Then you could specify the padding to be the width of the background image so that the text does not overlap it, and still specify a width for the text itself. For example:
.imageDiv{
width:200px;
background-image:url('someimage.png') /*this image is 50 px wide*/
background-repeat:no-repeat;
padding-left:50px;
}
Now any text entered into a div with the class imageDiv will show the image to the left of the text with any overlap.
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.
I have defined a fieldset in HTML, and applied the following (simple) CSS rules to it:
fieldset
{
margin: 2em 0;
position:relative;
padding: 1em;
border:1px solid #ccc;
}
Everything is great, no big deal, except in all versions (well, up to 7 as far as I know) of IE the top border -- but not, interestingly, the bottom border -- of the fieldset visually extends too far to the right by about 25px, beyond where the vertical border is on that side.
It is worth noting that this element's width causes it to be outside its parent element width-wise to the right, when viewed in Firebug for example.
What is causing this problem in IE? Is this a known issue, and, if so, what is the fix / hack / workaround?
I've struggled with this one for some time; tonight I finally found the answer.
http://www.sitepoint.com/forums/showthread.php?t=526881
To quote NatalieMac:
Seems that if you have an element inside the fieldset that's overflowing
to the right of the fieldset, it extends the top border. I had a
container set to a width of 100% with no padding or margins which IE7
thought was overflowing for some reason (even though the content inside
this container was right-aligned and viewable within the border of the
fieldset).
I was able to fix it just by adding overflow:hidden to the fieldset.
I can confirm that this does indeed fix the issue for me as well.
Could you post more of your code, like the HTML of what's surrounding the fieldset and the corresponding CSS rules for that?
You mentioned that you can see it's wider than its parent element in Firebug. That's almost certainly related. Can you change the CSS of the parent element to make it wide enough to contain the fieldset?
Without a little more context, it's probably going to be tough to diagnose this more accurately...