Why is the outline larger than its div? - html

UPDATE
To get the input back to the size I want it to be, I had to get rid of padding and borders. The following accomplished this:
*{padding:0; margin:0; border:0;}
Thanks to CBroe, I discovered this is unique to FF which adds to the input a default border of .75px and a padding of 1.5px. For a total of about 4.5px. Chrome does not.
UPDATE 2
The above fix only gets the child element back to the size I thought it should be. The accepted answer below shows that FF has a bug which explains why the outline didn't behave as it should, which is to outline the parent only and not expand for absolute positioned descendents.
I have two div elements stacked vertically with their outline property set to 1px. The div elements have a height of 117px.
I expect where the two div elements meet to have their outlines contiguous. It does so with no content.
When I place an absolute positioned input with top = 97px and height = 20px into the top div , the outline of that div is pushed down.
Here is a fiddle which shows this. If you remove the input, you will see how the top div outline sits next to the bottom div.
There are two things (at least) that I do not understand:
1) In examining the box using the browser's dev tools (Firefox), I see that the top div is in fact still 117px high. The outline should be drawn around the div, but appears not to be. Why?
2) The input has a top of 97px plus a height of 20px. Why would this affect the position of the outline? It looks like the outline is pushed down 4px.

That's because outlines are implementation dependent. It's not only the size:
Outlines may be non-rectangular.
From CSS3 UI,
This specification does not define the exact position or shape of the
outline, but it is typically drawn immediately outside the border box.
Firefox has historically had a tendency of making outlines bigger in various situations, e.g.
outlines are drawn outside (i.e., expanded by) box-shadow and other visual overflow
outlines are drawn outside (expanded by) outlines on descendant elements
The former was fixed, the latter seems the same as your problem.

I've 2 answers for you:
1) In examining the box using the browser's dev tools (Firefox), I see that the top div is in fact still 117px high. The outline should be drawn around the div, but appears not to be. Why?
The outline appears to be drawn around everything inside. So if an element stand out 100px at the bottom. The outline will also be moved 100px. In this case the input element stands out 8px. So the outline is 8px longer than you expected.
The input has a top of 97px plus a height of 20px. Why would this affect the position of the outline? It looks like the outline is pushed down 4px.
You were almost right there, 97px+20px is indeed 117px height. But you forgot to count 8px from the input element. This comes from a 3px thick border + 1px thick padding.

Related

How do margin rules apply to elements not in the DOM flow?

So I asked this question: google chrome issue with fixed position and margin-top which finally got me to realize that top and margin-top are not the same thing. I don't know how I've missed that all these years.
Anyways that got me thinking what is the difference exactly between margin-top and top, which is how I found this question: CSS: Top vs Margin-top.
I already knew what margin-top did. But I had never extrapolated that out to think "hmm, this element is not in the DOM flow so what exactly is margin-top pushing it away from?"
From the question I asked I know that margin-top behaves in very unexpected ways when applied to an element with a fixed position. And that in Chrome at least this can lead to some crazy rules (like margin-top: -273%;).
So my Question is: How do browsers apply margin rules to elements not in the DOM flow (i.e. elements with a position value of fixed or absolute . And what about the way they are applied and rendered leads to rules, like the one described above, actually rendering the element inside the view-port?
The top property simply determines how far from the top of the containing element that the box-model should start being rendered. In the case of position: fixed, that is the window itself. In the case of position: absolute, it is the next parent element with a non-static position.
Margin, on the other hand, is part of the box-model itself. Adding margin to the top of the box increases the empty space present above the box.
Consider the following layers for a position: fixed box:
top:10px
margin-top:10px
------------border-top:1px------------
padding-top:10px
content
All of the margin, border, and padding are part of the box model. That entire element, or "piece", is just one big square when positioning. So, if you have a margin of 10px on the top of the box, and position the element 10px from the top, it will have the appearance of having 20px of margin between the top of the window and where the visible box starts.
I've also made a very simple example in jsFiddle.
If you like graphics, take this example, where the red box has a position: fixed:
As you can see in the first section, only setting position: fixed on the element doesn't actually move it anywhere. It just removes it from the flow of the document.
In the section section, adding a margin-top: 10px makes the element move down 10px because the box now has 10px of margin on the top of it. However, it hasn't actually moved anywhere. The box has just gotten taller because the box model has changed.
In the third section, using a top: 10px actually moves the box to be 10px from the top of the window container. It has the exact same box model as in the first section.
Section four is like the second section above it, except the negative margin causes it to move up ten pixels. The box model is still taller and the box still hasn't moved.
When you set an absolute position on an element, the element doesn't move at all if you don't set any other position properties. So, without a top, right, bottom, or left property set, the element stays in the position it would have been in if it had been rendered as part of the flow, it's just now removed from the flow. So adding a margin, either positive or negative, makes it appear to move up or down from that position. In reality, you're just changing the element's box model though.
You also have to realize that using a percentage on top and bottom margins (and even paddings) has nothing to do with the height. It actually uses the width to figure out how much margin is there. Saying margin-top: 10% will make that value 10% of the available width, not the available height, and making it negative will just negate that value. I mentioned this because it is relevant to that first question you linked where you were using percentages for margin-top.
I hope this covered what you were looking for. I couldn't tell what exactly you were confused about so I just explained as much as I could.

Wanting DIV background to stretch outside parent DIV in IE

I have a list of items, like a menu, where the current item has a background image that is kind of like a big pointer to the right. This background image pointer thing should escape the bounding box of the div it's contained within. Here is a screenshot of how it appears in Chrome and FF, which is as i expected it to appear:
I've set up a jsfiddle with the code, minus the background image thing as I can't be bothered uploading it anywhere. But I've set the background colour so you can see what I'm referring to
The code is here: http://jsfiddle.net/V8TNm/
So in Chrome and FF, the yellow background of the active item will stretch past the grey gradient box. But in IE9, it's cut off.
Any ideas why, and what an easy fix may be?
Simply add position:relative.
#nav_mod_list div.current {
position: relative;
}
http://jsfiddle.net/V8TNm/3/
The selector #nav_mod_list div.current has a width of 210px as well as padding and margin where as the container is 200px. Change the 210 to 200 and remove the margin and padding.
Edit:
You could also just remove width property altogether. That way it will simply extend the width of the container.

Preventing repeating background from appearing through offset transparent child elements?

So, I have a layout where I have a repeating transparent shadow element set to the background of my parent container element. Set atop this, and supposedly hovering over the topmost edge of this background, is supposed to be an image with a frame and drop shadow.
However, because the image frame continues the parent element, the background image also continues upward. This is visible as the vertical lines above the top edge of the frame's drop shadow. See screenshot below:
This happens regardless if I use a transparent image or CSS3's box-shadow property. Setting negative margins doesn't work to bring it out of the parent element, nor does setting positioning as relative or absolute.
Normally I'd try to "fake" the transparency effect by setting a solid image at the top edge of the image frame, but there's a repeating stucco pattern set as the body background, which means there'd be a visible, unnatural-looking edge. (Insert cursing re: repeating patterns here.)
Any suggestions how I could prevent a parent element's background from showing through a child element, or offsetting the image frame somehow?
Many thanks!
I figured it out.
I was modifying the WordPress TwentyEleven theme, which has #primary and #secondary divs as floats atop the main content div. In order to make the background extend all the way to the bottom of the content div (I.e., past the two floats), I had overflow: set to auto.
Since I don't need to float anything (It's one column with no sidebar now), I removed both floats and removed the overflow declaration I had. Tah-dah, totally works now.
If someone else finds him/herself in this issue, have a look at my jsFiddle, which I used to figure it out. Thanks to Paker for the suggestion.

Why this behaviour (on ALL browsers) with margin-top?

This is my code :
HTML
<div class='father'>
<div class='son'>Son</div>
</div>
CSS
.father
{
background-color:blue;
}
.son
{
margin-top:50px;
background-color:red;
height:50px;
}
Where is the background-color blue of the father?
I know how to fix this problem (putting padding-top:1px to the father) but I'd like to know why of this behaviour!
For me it doesnt make sense, because on every browsers, not only IE, this is the behaviour.
This is a result of Collapsing Margins. You can read a good article by Eric Meyer on this topic where he illustrates this exact behavior. The following image is from his article.
Here's what the CSS2 specification has to say about it.
8.3.1 Collapsing margins
If the top and bottom margins of a box are adjoining, then it is
possible for margins to collapse through it. In this case, the
position of the element depends on its relationship with the other
elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as
the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved.
The position of the element's top border edge is the same as it
would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through
have no effect on the positions of the other elements with whose
margins they are being collapsed; the top border edge position is only
required for laying out descendants of these elements.
Source: http://www.w3.org/TR/CSS2/box.html#collapsing-margins
This is because the div is a block-level element. Certain block-level elements don't contain any padding by default. Divs are one such element. Block-level elements will take up the entire height and width of the container while respecting any padding it may contain.
W3C Visual formatting model
The parent element's height is set to its content's height by default. Once you set a height on the parent, that's no longer the default. Checking up on it, I believe that the padding adds to the height. So, the height is originally determined by the content unless otherwise stated in the CSS. Then, in most cases (IE 6 may be the exception), the padding is added to the height.
Good thing about SO, it helps us be much more detailed in our responses. :)
In CSS, block level elements naturally fills the elements content area, so your "son" div is filling your "father" div completely. Of course, you can bypass this by adding margin/padding/height to your parent div.
You're setting blue explicitly:
.father {
background-color:blue;
}
It's overridden (thanks to the "C" in CSS a.k.a cascading) but the style remains on your parent element (here, appropriately named "father").
If your .father box receives any height at all (check in the Firebug/Chrome dev tools inspector) than the blue is going to show through. I am guessing this is what you're seeing in IE (that or perhaps there's a flash of content before your child element style comes in). I don't think the IE debug tools show bounding boxes but you can test the element for it's height using JavaScript.
Moving outwards from the content, you have padding, border, and margin (as you probably know). Background covers only padding, but not margin.

What is it with the Box Model? Child margin affecting parent

HTML and CSS boggle my mind sometimes.
A DIV with a border shows its background color for the full height of the element and its contents. Why is it that without a border, a DIV will assume (reverse inherit?) its child's margins?
As an example, here is a JSFiddle illustrating the behavior with and without borders.
http://jsfiddle.net/ahNUX
http://jsfiddle.net/ahNUX/1/
Does anyone care to explain how this is a "feature" and not some kind of bug?
Update: adding 1px of padding to the parent is a quick fix.
Sure. In CSS, by default, adjacent top and bottom margins overlap each other. This was a sensible workaround before the adjacent sibling selector (+) was thought of/became well-supported, as it meant that if you wrote h2 {margin-top: 3em;}, you’d have 3ems worth of space above your h2s even if there was a paragraph before it with a bottom margin of 1em.
In your second example, because the <div> doesn’t have any top or bottom padding or borders, its top and bottom margins are adjacent to the <h1>'s default top and bottom margins. Even though the <div>’s margins don’t have any height, they’re still treated as if they exist, and so the <h1>’s margins have to overlap them. As the <div>s margins are by definition outside of the background-color area of the <div>, the <h1>’s margins have to be positioned outside too.
In your first example, because the <div> has a border, its margins are no longer adjacent to the <h1>’s margins, so no overlapping occurs. You can get the same effect by adding top and bottom padding to the <div>: http://jsfiddle.net/ahNUX/7/
(I’m not sure what you mean about the <div> “reverse-inheriting” its child’s padding though. In your examples, neither the <div> nor the <h1> have any padding. The space inside the <div> in your first example is created by the <h1>’s top and bottom margin.)
This is a result of collapsing margins. See http://www.w3.org/TR/CSS2/box.html#collapsing-margins
In a nutshell the top and bottom margin on the <h1> element in your example may have its margin collapse (or overlap) with another element that's above or below it, which would result in a conflict with the background color, so it's not shown. On the other hand, if you have a border, the rules change.
The spec explains it pretty well, albeit in a dry and somewhat technical tone.