the behaviour of top: auto; bamboozles me - css

Hi
I'm really confused about some basics with absolute positioning.
<!DOCTYPE html>
<html>
<head>
<link href="http://yui.yahooapis.com/3.0.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css" />
<style>
#containingBlock {
position: relative;
background: green;
}
#abs {
position: absolute;
background: blue;
top: auto;
}
</style>
</head>
<body>
<div id="containingBlock">
<p>foo</p>
<div id="abs">bar</div>
</div>
</body>
</html>
With the markup arranged as above, div#abs does not overlap the foo paragraph.
I know I could make it do this by giving top a value of 0 rather than auto, but since div#containingBlock has no padding, I thought auto and 0 would do the same thing.
However, if the paragraph and div#abs are switched in the source order -to make bar come before foo -top: auto; works exactly as I expected.
Any explanations appreciated!

You didn't really position these elements, you just declared what type of positioning you want to use. In this case, the auto value isn't really doing anything, because the #abs element is being placed right where it normally would anyways. If you removed the top: auto; segment outright, it would have no effect on the element.
"bar" is not overlapping "foo" because you haven't positioned it to do so. It is contained within the #containingBlock element, and is placed below the block element <p> because "foo" takes up a discrete amount of space. You want to override that? Set the top or other corresponding position values. To reiterate what others have said, top:auto just positions the top of that element as high up as room permits (which is what the element would have done normally).
For future reference, the auto value is used for when a parent CSS property overrides the child element's styling. For example let's say you had more complicated code which had a rule to apply a margin to every div within #containingBlock. If you want to change that back to normal, you would include margin:auto; in your containingBlock CSS.

When you set position absolute (relative etc) and do not specify a new position for the element, it will be placed where it would normally stay if there was no position:absolute.
Setting it to auto is like not specifying a top position and thus it gets placed under the paragraph where it would normally stay if no special positioning was applied.

it's easy (J/K!), auto and 0 are not the same thing.. well I mean most times they are
auto is when the render agent (the browser) attempts to decide what you mean. in the case #1 above the render agent is smart enough to know there is a preceding element, so it allows for it
as you rightly pointed out if you explicitly tell it to go to 0 it will do what it's told
swapping the source order is the same, it's then smart enough to know there is no longer anything preceding it so auto will mean 0 in that case

Using auto for top (or left) tells the browser to position an element in the exact same way it would if the element had 'position: fixed'.
This jsfiddle demonstrates what I mean: http://jsfiddle.net/kUmKW/
Try changing the value of left or top from auto to see what happens.

Related

CSS Inline margin issue

Hopefully an easy one.
I am concentrating heavily on the CSS side of things in my project, but am having an issue with block vs inline elements, and I don't really want to move on as I know it's fundamental to learning CSS. So the misunderstanding...
I have a span element which is inline.
<span>Please Login With Your Details Below</span>
There is a margin-left of 40px on this span which shows
However if I shrink the viewport small enough it does this
Issue: So on the new line it doesn't keep the margin...
However if I change the span to display:block it does this
which is what I want.
However I read this on https://www.impressivewebs.com/difference-block-inline-css/ regarding inline elements
Will ignore top and bottom margin settings, but will apply left and
right margins, and any padding
So it may be that I have misread it totally, but from what I understand it should have applied the left margin. Can someone explain why it didn't?
Thanks
When the user agent decides that inline content cannot fit the containing block, it will split the inline content into multiple inline boxes in order to accommodate the wrapping required to properly display without overflowing the containing block (if possible).
So in your example, Please Login With Your Details Below would overflow the containing element when you shrink the viewport, and therefore gets broken into two inline boxes:
Please Login With Your Details and Below.
According to the W3C recommendation:
When an inline box is split, margins, borders, and padding have no visual effect where the split occurs (or at any split, when there are several).
They provide this specific example that demonstrates what you are encountering:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
<HEAD>
<TITLE>Example of inline flow on several lines</TITLE>
<STYLE type="text/css">
EM {
padding: 2px;
margin: 1em;
border-width: medium;
border-style: dashed;
line-height: 2.4em;
}
</STYLE>
</HEAD>
<BODY>
<P>Several <EM>emphasized words</EM> appear here.</P>
</BODY>
</HTML>
The margin is inserted before "emphasized" and after "words".
The padding is inserted before, above, and below "emphasized" and after, above, and below "words". A dashed border is rendered on three sides in each case.
Your described behaviour is totally fine and correct.
However, the information is correct that left and right margins are applied to the inline element.
The information you did not had is, that actually inline elements left margin only indent the first line.
Think of it as an element meant to be in one single line, where this line can have horizontal margin. Having the text break in multiple line is a nice feature. But from the point of view of the margin property its still one a line.
You can use this property
text-align: justify;
text-align-last: justify;

What exactly does "auto" mean for the CSS top property? [duplicate]

Hi
I'm really confused about some basics with absolute positioning.
<!DOCTYPE html>
<html>
<head>
<link href="http://yui.yahooapis.com/3.0.0/build/cssreset/reset-min.css" rel="stylesheet" type="text/css" />
<style>
#containingBlock {
position: relative;
background: green;
}
#abs {
position: absolute;
background: blue;
top: auto;
}
</style>
</head>
<body>
<div id="containingBlock">
<p>foo</p>
<div id="abs">bar</div>
</div>
</body>
</html>
With the markup arranged as above, div#abs does not overlap the foo paragraph.
I know I could make it do this by giving top a value of 0 rather than auto, but since div#containingBlock has no padding, I thought auto and 0 would do the same thing.
However, if the paragraph and div#abs are switched in the source order -to make bar come before foo -top: auto; works exactly as I expected.
Any explanations appreciated!
You didn't really position these elements, you just declared what type of positioning you want to use. In this case, the auto value isn't really doing anything, because the #abs element is being placed right where it normally would anyways. If you removed the top: auto; segment outright, it would have no effect on the element.
"bar" is not overlapping "foo" because you haven't positioned it to do so. It is contained within the #containingBlock element, and is placed below the block element <p> because "foo" takes up a discrete amount of space. You want to override that? Set the top or other corresponding position values. To reiterate what others have said, top:auto just positions the top of that element as high up as room permits (which is what the element would have done normally).
For future reference, the auto value is used for when a parent CSS property overrides the child element's styling. For example let's say you had more complicated code which had a rule to apply a margin to every div within #containingBlock. If you want to change that back to normal, you would include margin:auto; in your containingBlock CSS.
When you set position absolute (relative etc) and do not specify a new position for the element, it will be placed where it would normally stay if there was no position:absolute.
Setting it to auto is like not specifying a top position and thus it gets placed under the paragraph where it would normally stay if no special positioning was applied.
it's easy (J/K!), auto and 0 are not the same thing.. well I mean most times they are
auto is when the render agent (the browser) attempts to decide what you mean. in the case #1 above the render agent is smart enough to know there is a preceding element, so it allows for it
as you rightly pointed out if you explicitly tell it to go to 0 it will do what it's told
swapping the source order is the same, it's then smart enough to know there is no longer anything preceding it so auto will mean 0 in that case
Using auto for top (or left) tells the browser to position an element in the exact same way it would if the element had 'position: fixed'.
This jsfiddle demonstrates what I mean: http://jsfiddle.net/kUmKW/
Try changing the value of left or top from auto to see what happens.

Positioning things inside a DIV (css-related)

i'll try to make my question really simple 2 you
Basically, i have a DIV, in which i have a picture
What CSS styles should i apply to the picture to position it correctly inside the div
with the condition that everytime i resize the browser window it stays there (inside the div) at the same distance from the borders
Sorry for wasting your time but i'm still a newbie which needs help, thank you alot!
EXAMPLE HERE
code
html
<div id="super_div">
<img id="eyes" src="images/eyes.png" />
</div>
css
that's the question :)
You need to look at absolute positioning. First, you set the containing div's position attribute to relative. For example:
#super_div
{
position: relative;
}
Then, you set the image's position property to absolute and use the top and left or right properties to place it inside the parent div. So, for example:
#eyes
{
position: absolute;
top: 20px;
left: 20px;
}
That's how you make the image keep its current position no matter what. Here's a link to an article explaining the basics. Hope this helps.
This will get it horizontally centered:
margin:auto;
If you need it vertically centered as well then things get a bit more tricky. You can either resort to tables, use a background image (if this is appropriate to your situation) or fiddle with the css. I used the code on http://css-tricks.com/snippets/css/absolute-center-vertical-horizontal-an-image/ as a basis for solving a similar situation I had a while ago..

How can a URL fragment affect a CSS layout?

Compare these 3 URLs (look at the top navigation bar in each case):
http://fast.kirkdesigns.co.uk/blog
as above but with the url fragment #navigation
as above but with the url fragment #node-2655
Note, that the only difference is the URL fragment on the end.
The first two pages display absolutely fine (in Firefox at least). It's the third one where the problem lies. The fragment #node-2655 pushes the top navbar off the top of the screen. When you then scroll back up to the top of the page, the navbar has been cut in half. This happens when using any URL fragment that causes the navbar to be out of the initial viewport when the page is first loaded.
So, how can using a url fragment affect the css layout like this?!
THE SOLUTION:
as suggested below, removing the overflow: hidden on the container element that held the navbar fixed the problem. I'd love to understand why though!
Remove the overflow:hidden on #main in css_75afd7072eaf4096aaebf60674218e31.css
I'd say it's a rendering bug in FireFox as it's fine in Opera. There shouldn't be anyway an anchor would change the CSS like you say (unless you are using jQuery or something).
I am having this problem too, and think I can see what is happening.
The "column" block with the massive (5678 pixel) margin and padding makes that block very tall. In browsers other than Firefox, the positive and negative values cancel each other out, but FF really does make it that tall - kind of.
FF also knows the two cancel each other out, but seems to look at the 5678px padding and decides the column block is poking out the bottom of the #wrapper block. This is overflow - and with overflow set to auto on #wrapper, you see the true size of #wrapper with a scroll-bar down the side.
With overflow set to hidden, FF takes away the scrollbar, but still seems to scroll the contents of #wrapper so that the item the fragment points to is at the top of the page. This is normal behaviour for fragment links in scrollable blocks, but since there is no scrollbar, you cannot scroll the content back down again, hence it looks like the layout has been effected by the fragment.
So in short, I suspect that FF is operating an invisible scrollbar in this example. That could be considered a bug, but it is probably correct behaviour. Being able to scroll the content up and down inside a non-overflowed fixed-sized block using URL fragments, is a technique that can be used effectively to implement image "sliders" that work even in the absence of JavaScript.
Hope that helps. This has been puzzling me for years, and this explanation suddenly struck me out the blue. My current workaround for this is to use jQuery "scroll to" plugin to scroll the whole page down to the fragment, as this seems to prevent the contents of #wrapper from scrolling internally.
You can also take "display: hidden" off #wrapper, but your page then ends up half a mile long.
I'll just point out that there may be some weird inheritance from the 30+ stylesheets linked to in the head. There may not, either, and it's probably a rendering bug (possibly related to :target styling) that Dan suggested. I just felt it worth pointing out that if you've got more than thirty stylesheets, you likely to start seeing some weirdness, whatever else might happens.
The reason is the column with the large padding has expanded it's container, but the expansion is then hidden but overflow:hidden; but with the use of the fragment it is being scrolled into the position of the fragment, effectively chopping off anything above that. You can use javascript and set scrollTop to 0 and it scroll it back to the normal position.
Basically a wierd edge case which browsers do not seem to handle very well.
Sorry this isn't an "answer," tho it is a response to the other comments here. This problem is just flabbergasting. It is very easy to isolate (i.e., has nothing to do with number of stylesheets), and doesn't have a proper "solution," as there is no way to achieve the desired rendering.
<!DOCTYPE html>
<html>
<head>
<style>
#container {
margin: 1em auto;
width: 40em;
}
#wrapper {
overflow: hidden;
position: relative;
}
#c1 {background-color: #aaf;}
#c2 {background-color: #ccf;}
.column {
float: left;
margin-bottom: -5678px;
padding-bottom: 5678px;
width: 50%;
}
#footer {
background-color: #eee;
padding: 1px;
text-align: center;
}
p {margin: 1em;}
</style>
</head>
<body>
<div id="container">
<div id="wrapper">
<div id="c1" class="column">
<p>This is some content in a short column. We would need some Javascript to change its height if we wanted a different background color for each column to stretch the full height of the respective columns...or we can use large padding together with an equal negative margin.</p>
<ul>
<li>Jump to P1</li>
<li>Jump to P2</li>
<li>Jump to P3</li>
</ul>
</div>
<div id="c2" class="column">
<p id="p1">The desired effect is to have the height of the two columns appear the same. We use 'overflow:hidden' on the containing div (#wrapper) to wrap it around the floated columns.</p>
<p id="p2">These paragraphs have fragment identifiers. Problem comes in when clicking one of the links on the left. Instead of scrolling just the page, the browser scrolls the div with 'overflow:hidden' so the target is at the top. It does this even if the target is already visible.</p>
<p id="p3">Opera does not exhibit this behavior. This occurs in Chrome/Safari, Firefox, and IE. (Interestingly, IE also works as expected if we completely remove the DOCTYPE declaration.)</p>
</div>
</div>
<div id="footer">
<p>Footer stuff.</p>
<p>To see why 'overflow: hidden' (or any other piece of the CSS) is needed, just try disabling it.</p>
</div>
</div>
</body>
</html>
Just as a side-note, the above technique is generally used to provide flexible-width mulit-column layouts. This is probably becoming less important these days as fixed-width layouts are becoming a lot more comment - browsers are able to magnify the web page to see small text, and fixed-width makes it a lot easier to control the typography of a page, e.g. set the width (in ems) to display the ideal nine words per line regardless of what font size and magnification the user chooses.
Sorry if that does not sound like an answer, but it is basically suggesting to discard this old model and consider moving to fixed-width columns (which is a whole new subject).
I was able to solve this with some javascript to scroll the body to the position the overflow hidden element was scrolled to.
setTimeout(() => {
let intendedScroll = document.getElementById("fragmentfix").scrollTop;
document.getElementById("fragmentfix").scrollTop = 0;
window.scrollTo(0, intendedScroll);
}, 0)

IE 6 & IE 7 Z-Index Problem

http://madisonlane.businesscatalyst.com
I'm trying to get the div#sign-post to sit above the div#bottom. This works fine in all browsers except IE6 & IE7. Can anyone see what the problem is here?
Also IE6 is displaying an additional 198px to the top of div#bottom.
Most of the answers here are wrong; some work, but not for the reason they state. Here is some explanation.
This is how z-index should work according to the spec:
you can give a z-index value to any element; if you don't, it defaults to auto
positioned elements (that is, elements with a position attribute different from the default static) with a z-index different from auto create a new stacking context. Stacking contexts are the "units" of overlapping; one stacking context is either completely above the another (that is, every element of the first is above any element of the second) or completely below it.
inside the same stacking context, the stack level of the elements is compared. Elements with an explicit z-index value have that value as a stack level, other elements inherit from their parents. The element with the higher stack level is displayed on top. When two elements have the same stack level, generally the one which is later in the DOM tree is painted on top. (More complicated rules apply if they have a different position attribute.)
In other words, when two elements have z-index set, in order to decide which will show on top, you need to check if they have any positioned parents which also have z-index set. If they don't, or the parents are common, the one with the higher z-index wins. If they do, you need to compare the parents, and the z-index of the children is irrelevant.
So the z-index decides how the element is placed compared to other children of its "stacking parent" (the closest ancestor with a z-index set and a position of relative, absolute or fixed), but it doesn't matter when comparing to other elements; it is the stacking parent's z-index (or possibly the z-index of the stacking parent's stacking parent, et cetera) which counts. In a typical document where you use z-index only on a few elements like dropdown menus and popups, none of which contains the other, the stacking parent of all the elements which have a z-index is the whole document, and you can usually get away with thinking of the z-index as a global, document-level ordering.
The fundamental difference with IE6/7 is that positioned elements start new stacking contexts, whether they have z-index set or not. Since the elements which you would instinctively assign z-index values to are typically absolutely positioned and have a relatively positioned parent or close ancestor, this will mean that your z-index-ed elements won't be compared at all, instead their positioned ancestors will - and since those have no z-index set, document order will prevail.
As a workaround, you need to find out which ancestors are actually compared, and assign some z-index to them to restore the order you want (which will usually be reverse document order). Usually this is done by javascript - for a dropdown menu, you can walk through the menu containers or parent menu items, and assign them a z-index of 1000, 999, 998 and so on. Another method: when a popup or dropdown menu becomes visible, find all its relatively positioned ancestors, and give them an on-top class which has a very high z-index; when it becomes invisible again, remove the classes.
Agree with validator comment - validating usually helps. But, if it doesn't heres a few pointers for z-index in IE:
1) elements who's z-index you're manipulating should be on the same level ie. you should be setting the z-index of #bottom and #body
if this is not feasible then
2) IE sometimes wont apply the z-index correctly unless the elements ou are applying it to have a position:relative. Try applying that property to #bottom and #body (or #signpost)
let me know how that works out
Darko
I just had this problem and the fix I found (thanks to Quirksmode) was to give the direct parent of the node you are trying to set a z-index of it's own z-index that is at less than the z-index of the node you are trying to set. Here is a quick example that should work in IE6
<html>
<head>
<style type="text/css">
#AlwaysOnTop {
background-color: red;
color: white;
width: 300px;
position: fixed;
top: 0;
z-index: 2;
}
#Header {
color: white;
width: 100%;
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<div id="Header">
<div id="AlwaysOnTop">This will always be on top</div>
</div>
<div id="Content">Some long amount of text to produce a scroll bar</div>
</body>
</html>
Welcome, I solved the problem with:
.header {
position: relative;
z-index: 1001;
}
.content {
position: relative;
z-index: 1000;
}
Looks to me like you have some malformed HTML in there. I tried counting, and perhaps I lost count of the opening and closing tags, but it looks like div#container isn't closed. Try running your page through a validator (such as W3C's HTML Validator, or something) and fixing some of the errors. That's helped me with these sorts of problems in the past. Good luck!
I've recently had an ongoing problem displaying one layer above another. In my case I was programmatically creating two layers in Javascript, one for diaplaying a custom control and one for creating a full screen layer behind it. FF was fine, bu IE displayed the full screen layer always on top of everything else.
After numerous trawls over the interweb, trying everyone's suggestions, the only way I eventually get it working was to remove position: attributes from both layers, and tweak the margin-top: attribute until I got a satisfactory result.
A bit of a hash, but it works and it'll be fine until IE 8 sorts out all of the current bugs......
the only reliable solution is, to put the top elements below in the code and then push them over the other stuff with absolute positioning.
e.g. Wordpress:
put the navigation in the footer file, but still inside the page wrapper.
might also bring some advantages for search engines, because they can directly start with the content, without crawling through the menu first...
UPDATE:
I need to correct myself. While putting the element below and then pushing it over is still the easiest way, there are certain cases when this is not possible in reasonable time. Then you have to make sure that each and every parent element has some kind of positioning and some senseful z-index. Then the z-index should work again even in IE7.

Resources