About css border, margin, padding and width - css

Playing with css border, margin, padding and width I came across an extra pixel...
I know that the total width and height of an element is the sum of its width, border, margin and padding.
If you look at this http://jsfiddle.net/Fs8HQ/ , everything seems to work. When you click the button, moving some pixels from the border to the margin create a pseudo-animation.
Now let's set a fixed width and height in http://jsfiddle.net/Fs8HQ/1/ (remove width and height from :active): in Firefox and Chrome there is one extra-height and one extra-width pixels that move all the adjacent elements. in Opera there is one extra-width and two extra-height pixels. Where they come from?
But here http://jsfiddle.net/hJTpY/ moving the pixel from the border to the padding seems to fix everything, but the pseudo-animation is not the same.
In the first two fiddles the borders are reduced approaching to content; in the last one the borders are reduced by the contents that expands.
Why does that happen? I'm missing something?

This is a problem I noticed lately:
The default boxmodel introduced by the W3C is content-box if a proper doctype is declared (in contradiction to the Microsoft boxmodel which can be triggered by using quirks-mode in IEs).
However, lately I noticed that the browsers have UA-styles which declare box-sizing:border-box (for input-elements only?). That is why your trick does not work, because the border is accounted into the width. To fix this, you have to declare box-sizing:content-box. See this question dealing with the same problem.

You problem occurs because when you fixed the width, for instance at 100px, the box with its border will have a width of 100px (due to the box-sizing property), so your increase of margin is not compensated by a shrinking of the box, which occurs when you do not set its width.
With a fixed width, and box-sizing set as border-box, you should not modify the margin property at all to avoid the other box moving.
The easy fix is of course to set back box-sizing at content-box : http://jsfiddle.net/Fs8HQ/7/
For more information about the css box-sizing property, go there.

Related

Cross-browser Issue: Min-height and collapsing margins

As you can see in this simple example:
<div id="minheight">
<p id="margin">Paragraph with a margin</p>
</div>
<div id="sibling">Sibling div</div>
#minheight {
min-height: 100px;
background: red;
}
#sibling {
background: blue;
}
http://jsfiddle.net/peterbriers/B43th
There is a difference between Chrome (35) and Firefox (29) in how it handles the collapsing margins on a block with a min-height that is larger than the child's margin.
I tried to fully understand the specifications: http://www.w3.org/TR/CSS2/box.html#collapsing-margins , but I'm still unsure which browser handles this correctly. I would say Chrome is in the wrong, but Safari (7) does it the Chrome way too.
Which browser is correct, and how can I file a bug for the one that isn't doing it the right way?
BTW: I'm not asking any fix by adding new block formatting context (adding overflow property)...
OK, so this seems to be a very peculiar case.
If you change min-height to height, the gap disappears in Chrome. Not only does Safari behave the same as Chrome, but so does IE. Firefox's behavior is unique to itself, and its behavior does not change when you make that adjustment to your CSS. This should come as a surprise, as you would not expect min-height and height to behave any differently in your given scenario.
However, the spec has something interesting to say about min-height with respect to margin collapsing:
The following algorithm describes how the two properties influence the used value of the 'height' property:
[...]
These steps do not affect the real computed values of the above properties. The change of used 'height' has no effect on margin collapsing except as specifically required by rules for 'min-height' or 'max-height' in "Collapsing margins" (8.3.1).
Because you have not specified a fixed value for the height property on the same element that has a min-height, the computed value for height remains the default auto, even though the used value is floored to min-height.
Therefore the following text from section 8.3.1 applies, and the margins between the block box and its child should collapse as a result, irrespective of min-height:
Two margins are adjoining if and only if:
both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
...
bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
Note that it goes on to list some scenarios in which margins may or may not collapse:
Note the above rules imply that:
...
The bottom margin of an in-flow block box with a 'height' of 'auto' and a 'min-height' of zero collapses with its last in-flow block-level child's bottom margin if the box has no bottom padding and no bottom border and the child's bottom margin does not collapse with a top margin that has clearance.
... but it does not state what happens when the block box has height: auto and a non-zero min-height.
Based on this, it would be safe to assume that the spec should be interpreted as I am doing. Therefore it looks like Firefox is not behaving quite correctly, and all other browsers are following the spec to the letter, despite what one might expect from the behavior of height and min-height.
You can file a bug for Firefox here, although it looks like the developers have already made themselves aware of this issue.

Different rendering from Chrome and Firefox when having floated children in a floated div with no width.

I've set up a test here
http://jsfiddle.net/WZyF7/11/
Firefox seems to differ from Chrome and IE7-9 on how to calculate the width. Instead of giving the content as much width as it needs, it makes the div as wide it's widest child element. This stacks the elements vertically in FF, while horizontally in other browsers.
Is there any way to make all browsers handle this the same way without setting a width to the parent element or using JS? And does anyone have information on exactly how this is calculated across browsers? (width:auto; ? )
The relevant spec bit is http://www.w3.org/TR/CSS21/visuren.html#floats where it says:
The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.
And the part in http://www.w3.org/TR/CSS21/visudet.html#float-width which says:
If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width.
and following. Note that the actual computation of preferred width, which is what matters here, is not all that well defined. So basically, per spec behavior in this situation is undefined.
In any case, what's happening here is that Firefox is giving the overflow: hidden block the width it should have per section 10.3.3 and then clearing it past the float, while Chrome and IE seem to take the "they may even" path. And in particular, it's assuming it will do that when computing the preferred width of the parent.
All that said, I think the Firefox behavior is more correct in this particular narrow case: your "container" is 400px wide. The "parent" has 20px of horizontal padding. The "floated" is 300px wide. The "content" has 20px of horizontal padding. That leaves 60px of width for the text inside "content", but the longest word ("available...") is about 70px wide with my fonts. In Chrome, for example, the only way "content" fits next to the "floated" is because the right padding of the "content" disappears entirely. Firefox will do the same thing if you give a fixed width to the "parent" here.... but then you're forcing a width, instead of asking the browser to pick a reasonable one via the shrink-wrap algorithm, of course.
Your best bet here is to just give the "parent" a specific width if you want it to have that width, instead of relying on shrink-wrapping to produce a width that's actually too small for the content.

CSS: why line-height disturbs the width?

How does the line-height property in CSS works? If i set the line-height equal or less than the font size, it creates the problem with layout width. Please check this jsFiddle to see the problem.
I'm using font-size 14px, and line height 14px. If you change the line-height to 15px or more, the problem will be solved. Shouldn't the line-height only change the height, not disturb the width?
Please see the image below, as you see the #wrap has width of 300px, now because of line height the two div's of width 150px are not fitting into it.
I have checked with firefox and chrome, latest versions.
Line height is an inherited property but its inheritance works in a complicated way as compared to other inherited properties.
There is an excellent slideshow to Illustrate how line-height works depending on the units you specify the line height.
http://www.slideshare.net/maxdesign/line-height.
Slide 28 onwards explains your issue.
It has nothing to do with line height... not directly atleast. The two boxes will remain 150px wide regardless of whether you specify a line height or not. The overflow: auto causes a vertical scroll bar to appear (for reasons unknown to me) which reduces the available width of your container from 300px to ~280px hence the two colored boxes cannot appear side by side anymore. If you remove overflow: auto the result will appear as expected.
Edit
Revised demo here. To counter the vertical scrollbar, I added 1px padding on the container which seemed to counter the problem. For larger font sizes, use a padding of 2px.
In Chrome, if I increase the line height to 18px, the divs will be side by side, but the width doesn't change. Apparently this has something to do with the calculation of the height of #wrap. The browser cannot decide wether to show the scrollbar in #wrap or not. But since #wrap is exactly 300 wide, and thus can hold the two divs side by side only when the scrollbar isn't displayed, you'll have to force to hide it. Change #wrap overflow to hidden, or remove this property altogether.

How to use very large font sizes in Internet Explorer with CSS that won't affect design?

The font size I need to match the design I have is 85pt, which is extremely large. In IE6 and IE7, my design is affected because the divs that contain these elements become larger than they normally are, and as a result, elements under these are pushed further down, somewhat breaking the design. I have the height defined for these elements and when I decrease the font size, the elements begin to shrink to the correct size. I've added line-height: 0; to the element and this works in all modern browsers.
Unfortunately, the design I'm working on cannot be shown publicly, but I was hoping to get some insight into other possible techniques that I could try to get the design to render correctly. The height of the parent element is 144px, which includes 10px padding on top and bottom and a top and bottom 1px border.
Unfortunately there's not a lot more that I can add to this, but I'll include whatever info I can if asked.
line-height:0 is a great start. However, I'm a little concerned about the 10px padding on the parent element. Whenever you mix padding with IE, you start to lose control over width & height.
I'd start by removing the padding-top on the parent and convert that into a margin-top:10px on the actual child element. If that still gives you trouble, remove the margin and try a position:relative on the child with a top:10px.
Finally, try adding a overflow:hidden to your parent element to force it to not budge when the font-size gets larger.
All this depends on what your child element actually is. If you convert it to an inline element (like a span, em, or strong) it might help alleviate some rendering issues, depending on your predefined styles.
Another thing to consider - are you using floats? Sometimes you'll get a double-float issue with IE and floats. A quick google for "IE double float" will show you why.
Does that help?
Convert the font-sizes to pixels and use px instead of pt. Make sure there that padding, margin and border is 0. Verify that there are no whitespace in your HTML except for between words. Whitespace can end up being displayed as a newline or space, making elements bigger than intended. Also don't set line-height to 0, set it to either auto or the same as font-size.
Thank you all for your input. Originally I needed absolute positioning on the element in question, while the parent element had relative positioning. However, using this with line-height: 0 caused the text to disappear in IE6 and 7; after trying to figure out where the text was initially, I removed absolute positioning and decided to leave the text left aligned in IE6 and 7, which affected the position of other elements as a result. I revisited the original absolute positioning and added border to the element to reveal its location. Doing this showed that it was exactly as I defined it: an element with a line-height of 0px, so the top and bottom borders were next to each other. For IE6 and 7, I defined line-height: 100%; and my text was almost where I needed it. I added top and the needed pixels and now my element is in the correct position with its line-height not affecting any of the other elements because of the positioning.
Thank you all again for your assistance.
My first thought when reading your post was to adjust the line-height, but since you've already done that, I'm not sure how much more can be done. From your summary, I gather that the design cannot be modified to account for the large font sizes.
Another answerer recommended using pixel sizes, but I would recommend using ems as they are percentage dimensions and will be more consistent across browsers, screens, and resolutions.
Line-height can be left as 0 (or set it to the height of the parent element), but you will likely see the text floating over other elements if the text's height surpasses the line-height.
Any possible way you could use an image for the text instead? That's really the only fool-proof method for getting all browsers to look consistent.

Specified min-height and 100% height together

I have been trawling the web trying to find an answer to my css nightmare question.
The main problem seems to be getting a min-height:580px and a height:100% at the same time in all the browsers.
The thing I need to achieve is:
Site to have a min height of 580px including footer so total height before scroll bars appear is 580px.
Also, a min width is needed of 930px including right and left margin of 15px each side.
left menu of 216px wide and 100% high minus the footer height of 30px.
Main part of the screen should fill all the space available. Unless the screen height is less than 580px or width less than 930px. In this case you get scroll bars.
Compatiblity ie6,7,8, Firefox and Safari.
Can it be done with no Javascript?
There may be cleaner ways, but an idea that comes to mind about the min-height (min-height isn't interpreted by IE<8 anyway):
Place an absolutely positioned, 1 pixel wide, invisible DIV in the left hand corner of the screen. Give it 580 Pixels height.
That should make the height at least 580 Pixels.
The same should be possible with the horizontal width.
You should then be able to work the menu part in the usual way.
Don't forget your HTML element needs height: 100% for height: 100% to work within the body.
First, there's no support for min-height in IE6 or IE7 without javascript, period. So the answer to your question is no.
In general, though (and I'll admit I'm not sure since I haven't tested it thoroughly) but I seem to recall that height:100% overrides the min-height property set in pixels in browsers that do support it.
You could try using a second div either inside or outside your 100% height div that's the 580px you need...

Resources