Negative margin "hovering" div goes under later elements - html

OK, so I have three <ul> tags that each have float: left; applied to them. The <li> tags have a :hover specification that causes them to increase in width and gain a negative margin equal to the gain in width, so that on hover they increase in size without moving anything.
The issue is that instead of extending out over the following floated <ul> tags, they extend "under" them. Setting z-index has not seemed to do anything about this, though I may perhaps be using it wrong. I've tried setting z-index: 5; on the :hover specification, and I also tried setting z-index: 3;, z-index: 2;, and z-index: 1; on the successive <ul> tags, but neither made any difference.
One thing that did work was to have the <ul> tags be float: right; so that the last one was actually left-most, but I don't like this solution as it means my code is in the opposite order as it appears on the page, and it will mean that I have to set manual tabindex attributes on everything to fix the tab order.
EDIT: Fixed it; can't answer my own question for 7 hours, but it turns out that z-index does not work on position: static; (the default) elements. I just added position: relative; to the <li> tags and it works fine now.

You cannot use z-index for static elements. Consider changing their positioning to either relative or absolute.

Related

Why is top:inherit; Behaving This Way?

I have a horizontal navigation <ul>, and in one of the <li>s I have a <div> element that I was conducting some positioning experiments with.
Along the way I noticed that I could position the inner div inside of the li using
li div {
position: absolute;
top: inherit;
left: inherit;
}
even though I have assigned no top or left properties to the li! Even in Firefox "Computed Styles" inspector. How exactly is it inheriting properties that don't exist? Are my browsers (newest FF & Chrome) just implicitly positioning it, or do the top: and left: properties always exist invisibly?
Also I'm guessing IE<8 will cough this back up...
Here's a fiddle: http://jsfiddle.net/xAk97/
If you have any value with inherit the element is gonna take the same value as his parent. If you don't specify a value in your CSS the inherited value is the default one for that property.
In this case if top isn't defined the element will take that value as auto.
If you check the console in this Fiddle you can check what property is been assigned.

Why display=inline-block adds uncontrollable vertical margins

I'm trying to fiddle my problem on http://jsfiddle.net and have got strangest behaviour there. Can you please explain where these (http://jsfiddle.net/C6V3S/) vertical margins come from? Does appear on jsfiddle.net (at least in Chrome and FF), do not appear when copy/pasting to local standalone file ...
works OK afer changing to simple block
Sample for standalone test file:
.btn {
padding: 0px;
border: 1px solid red;
display: inline-block;
}
.txt {
display: inline-block;
width: 12px;
height: 12px;
border: none;
padding: 0;
margin: 0;
background: #77FF77;
}
</style>
<div class="btn"><div class="txt"></div></div>
When you make the .txt element inline-block, it is taken into the text flow of the parent .btn element. At that point, the line-height of .btn kicks in, which is larger than the height of the .txt element.
So, add .btn {line-height: 10px;} (for example) and your problem is fixed. I saw you already tried to influence the line-height of the inner .txt element, so you were pretty close with your attempts. Adjusting the font-size would work as well, since the default line-height is formula-based on the font-size. Anyway, the key is to do that on the parent element, not the child element.
You don't have this problem when you make the inner element a block, because then there's no text-like content, so there's no line-height applied at all.
inline-block is brilliant and convenient for so many cases. But they come with one annoying pitfall: unnecessary whitespace. As you're nesting an inline-block within an inline-block, that results in a white-space disaster. You can read all about whitespace and inline-blocks on David Walsh's blog.
There are many ways to handle this, but my favorite (and most widely supported) solution is setting this to the parent inline-block element:
.btn {
font-size: 0;
}
Here is an example of before/after:
http://jsfiddle.net/C6V3S/1/
This is not caused by whitespace (you don't have any inside the divs in your HTML), nor by putting inline-block inside of another inline-block. This is caused because of the line-height of the outer div. As you can see from the below fiddle, the current line-height of the red-border div has a line-height that is being set by the browser (and it varies from browser to browser), and as long as there is something inside of the div that takes up space as an inline or inline-block item, the height will be affected by the line-height.
There are many ways around this, and they all pretty much do the same thing:
1) Take the inside element out of flow, and then reinsert it back in. This will make the outer div think that there is nothing inside of it, and try to become as small as possible, and then fill up space exactly around the element when it inserted back in. The easiest way to do this is by floating it.
2) Make the outer element take up no space. This will make the inside element define the height and width of its parent. If you do font-size: 0, as mentioned before, this will make the outer element think that the inline inside element takes up no space, and therefore not take up any space itself, and wrap itself tightly around the inner element. This can be done by setting line-height: 0 as well (which is a perfect fix for the problem, as the problem is line-height).
There are other ways to make the parent element not have its line-height, but that should get you started.
http://jsfiddle.net/C6V3S/4/
It's "just how it works," but it can be worked around. The easiest way to fix it would be to set negative margins on .btn. It should work for any modern browser (IE8 and above, if I recall). Floating the elements should achieve what you want, too. As a wholly different solution if your problem with it is merely aesthetic, you can just wrap the elements in a parent, set that parent's background-color to what you want, and not worry about its child elements' backgrounds. They'll be transparent to whatever is beneath them, and you'll get rid of those visual breaks.
If you want to stick with negative margins on with display: inline-block, but need that pesky first element not to jump leftward out of its parent, you could target it explicitly:
.btn {
margin-left: -4px;
}
.btn:first-of-type {
margin-left: 0px;
}
Edit: After reading another answer, I'm not sure if I understood the question -- do you mean the margin atop the elements (which would be horizontal) or the margin to the sides (vertical)?

Position Fixed Header goes behind text when Position Relative element is added

So I know there are a plethora of questions about position fixed/relative/absolute in relation with z-index, but I still couldn't figure out my question using those.
Essentially I have a header that is fixed. It works perfectly fine, everything goes behind it when scrolling down the page.
I recently wanted to add links to div ids, but in order to account for the header, I had to add the following code where link is the parent element, and then linkTo is the class of something with an ID that we actually link to. This functionality works completely, providing the correct offset so that the header is above the div we want.
.link {position: relative;}
.linkTo {position: absolute; top: -80px;}
The problem with this, is that for some reason now my div is behind everything on the page. I can still see it but the text and images are in front.
I've tried adding z-index to my header (of like 9999) but it isn't working. I don't understand why adding position relative would mess up the order of how things are displayed.
I'd like to provide an example, but my code is rather large. If this isn't enough I can try to make a jfiddle later.
Add position: relative; z-index:9999 to the parent element it will keep this element stick inside the menu.
As Ganesh said, adding position: relative to the parent element of the header was the starting step. After that adding z-index to the same parent element fixed the problem completely.
Check for a lower z-index on a parent element, it appears to override the z-index of children.
I've run into z-index issues in the past with drop down menus and jquery UI tabs. I thought it had something to do with the stacking effects created us rules like opacity or transition, but for me the problem was a parent element having a lower z-index than a child element.

CSS: position:fixed inside of position:absolute

I'm running into some extremely strange behaviors, and non-consistant across every browser i've tested.
I've a pretty complex layout, but the main issue lies here:
<div id="drop">
<div id="header"></div>
</div>
#drop has position:absolute and z-index:100
#header has position:fixed; top:60px;
As I start scrolling down Chrome ignores the position:fixed rule. If I remove either of the two styles above from #drop then Chrome starts respecting the position:fixed rule.
can't get it working on Ubuntu Chrome 23.0.1271.97 and see the same behavior on Mac Chrome 25.0.1364.99. My friend uses Ubuntu Chrome 25.0.1364.68 beta and it works correctly for him. I've tested it on firefox and it kinda works (with other symptoms)
Has anyone heard of this error? or can anyone even reproduce it?
edit
I'm using openlayers map as another div with position:fixed if I delete that layer or at least change it to display:none then this weird bug goes away.
edit
Noticed that during the presence of this bug, if I change the zoom level back and forth, then the position adjusts itself to the proper behavior. To me, this indicates a webkit issue that fails to execute some internal callback function on scroll.
Another extremely strange thing is that I have a few links inside of #header and they work if I just click the expected location, even though the the div does not appear there. Overall I've noticed that it's only the rendering that's broken. If at any point of time I force the browser to re-render by resizing the window, or changing zoom, or just doing Select-All, then the header bar jumps to the proper position, but does not remain fixed.
You mentioned in the comments that OpenLayers uses CSS transforms. That being the case:
the element with fixed positioning will become relative to the element with the transform - not relative to the viewport
Take a look at the spec: The Transform Rendering Model
Specifying a value other than ‘none’ for the ‘transform’ property
establishes a new local coordinate system at the element that it is
applied to.
.wpr
{
width: 200px;
height:1000px;
background: pink;
position:relative;
margin: 0 200px;
-webkit-transform: translateX(0);
transform: translateX(0);
}
.fixed
{
width: 200px;
height:200px;
margin: 50px;
position: fixed;
top:0;
left:0;
background: aqua;
}
<div class="wpr">
<div class="fixed"></div>
</div>
As the accepted answer says, this is the intended behavior, and is spec-compliant. Another important component of this is what it means to be using CSS transforms.
In your case, it was due to OpenLayers, but this applies to anyone using will-change: transform as well (probably a lot of the people visiting this question). This has been brought up on the Chromium bug tracker here, and marked as WontFix, because (as I said) it's intended behavior. The official comment is this:
This behavior is required by the spec
(http://dev.w3.org/csswg/css-will-change/): "If any non-initial value
of a property would cause the element to generate a containing block
for fixed-position elements, specifying that property in will-change
must cause the element to generate a containing block for
fixed-position elements."
The idea is that once will-change:transform is specified, you should
be able to add/remove/change transforms cheaply, without needing
fixed-position descendants to get re-layed-out.
Note that using other values of will-change (e.g. opacity, top) will
not change the positioning of fixed-position descendants.
As far as I am aware, the only solution is to make the child of the will-change element a sibling instead, to prevent the attribute from cascading.
As a side note, in my specific case, I was able to fix it by being more specific with the will-change attribute. Instead of using it on the div containing the performance-jarring element that required GPU offloading, I used it directly on the offending element. This was due to my original bad code, though, so it won't work for most cases.
You will have to place header outside the parent container drop to make it work.
I had slightly similar issues days back.For instance,if you set z-index of header,it will be attain the z-index of the parent dropcontainer.The z-index of header will be useless because it is already inside a container which has another z-index.
The same logic of z-index applies to position.
I want to add another possible solution because I was struggling with chrome ignoring position:fixed for quite some time until I finally found the culprit:
-webkit-perspective: 1000;
It was coming from a plugin I was using and causes ALL position:fixed elements to be ignored.
Hope it helps someone.
I think this is impossible, i don't think if two positions can be placed at the same place without one to collapse. But i think its better to use Avail height in javascript, i mean if you wanna an outer div to hold inner div, and outer div must cover the whole screen, use Availheight in js, this will get the screen height and then apply if, thereafter set all the divs in fixed position.
Add this to parent:
position: fixed;
...and this to the child:
position: sticky;
First of all, put something in your div as empty ones behave really weird. Then, what do you expect by putting a fixed into an absolute? Obviously, nobody knows what is the reference point of your fixed div. Should it be its parents position? which is not changing with scroll or the page position which changes? Try to use things that are completely meaningful and have a clear definition because if you fix it in chrome, what would happen with another browser? Do you really prefer to test is on all of them?
I suppose a small change in your divs so that pull the fixed div out of the absolute one or move the absolute div somewhere else.

Weird z-index behaviour preventing mouse interactions: bug or normal?

Every time I try to use z-index in a webpage to change the order of stacking overlapping divs, I seem to run into a problem where the div that is being forced lower becomes unresponsive to mouse events.
In my current situation I have:
<div class="leftcolumn">
<div class="leftbar"></div> <!-- a 95px wide bar on the left -->
...
<h3>header</h3> <!-- a little header sitting inside the leftbar
...
</div>
By default the h3 isn't showing - it's hidden behind the leftbar. If I add z-index: 5; to the h3, it still doesn't show.
So I add z-index: -1 to the leftbar. Now it's hidden behind the leftcolumn - but at least h3 shows.
So I add z-index: -2 to the leftcolumn. Now everything looks right - but you can't click on anything inside leftcolumn. The mouse cursor doesn't change from an arrow.
I get this exact behaviour in both Chrome and Firefox. IE7 doesn't show the leftbar at all, but at least stuff is clickable.
So, am I misunderstanding z-index, or is there a bug in both FF and Chrome here? Can z-index be effectively used for this kind of stuff, or do I have to find another way?
(I can change the HTML, but the less, the better.)
Ok, 10 seconds later I discover that using only positive z-index'es makes the problem go away. Perhaps negative z-index means the object is below the level that the mouse cursor notionally lives?
Do you know that in order for z-index to work right, you need to position your elements, even if they're simply position: relative (which doesn't change their position any but allows you to use z-index). That way, you should be able to give leftbar a position of, say, 2 and your h3 a position of, say, 3. And your h3 should be on top.
You can use any position type as long as you have one.
For recap:
#leftcolumn { position: absolute; z-index: 1; }
#leftbar { position: relative; z-index: 2; }
h3 { position: relative; z-index: 3; }
Even though the leftcolumn content is visible, the leftbar div is now sitting on top of it, likely with a transparent background. Ideally you would want to modify the HTML so that the H3 resides within the leftbar, but if that is not an option, you may need to apply z-index to specific elements within the leftcolumn in order to pull them above elements in the leftbar.