Why does opacity negate pointer events? - css

In the following setup, why does the click event (and any other pointer event) not get fired?
If you remove the opacity: 0.5 line, it will work fine.
http://jsfiddle.net/523ve/
For posterity, in case jsFiddle ever goes down (December 21 is approaching):
HTML:
<div>
<a>Click</a>
<p>Paragraph</p>
</div>
CSS:
div { position: relative; margin: 40px; }
a { position: absolute; top: 0; right: 0; }
p { opacity: 0.5; }
JS:
$(document).ready(function(event) {
$("a").click(function(event) {
alert("Alert");
});
});
(Tested in latest stable Chrome and Firefox)

"Since an element with opacity less than 1 is composited from a single offscreen image, content outside of it cannot be layered in
z-order between pieces of content inside of it. For the same reason,
implementations must create a new stacking context for any element
with opacity less than 1. If an element with opacity less than 1 is
not positioned, implementations must paint the layer it creates,
within its parent stacking context, at the same stacking order that
would be used if it were a positioned element with z-index: 0 and
opacity: 1..."
http://www.w3.org/TR/css3-color/#transparency
EDIT:
Also, your particular example has the <p> element overlapping the <a>.
http://jsfiddle.net/523ve/4/
So you could fix this by either moving the <a> so that it does not interfere, or by using z-index to re-adjust the stacking order. The latter option may have cross-browser issues but I have not tested. I recommend re-factoring your HTML so that these two elements do not overlap with each other.
EDIT 2:
Here is a related SO question, however the accepted answer is incorrect.
What has bigger priority: opacity or z-index in browsers?

you might understand by this line
The opacity CSS property specifies the transparency of an element, that is, the degree to which the background behind the element is overlaid.
Using this property with a value different than 1 places the element in a new stacking context.
source :MDN
and here p is overlapping a so either set the width of p to not overlap a or set a higher z-index

The a element comes before p, and note that p is 100% wide. This means that p is effectively ABOVE a.
You can either change a element's z-index to something above 0 (http://jsfiddle.net/523ve/5/) or swap p and a in your HTML so that a comes after p (http://jsfiddle.net/523ve/3/).
I hope what I've written makes any sense ;).

Related

will-change breaks showing position absolute div on :hover

I have an issue with will-change. I have no idea why it causes this problem but when I add will-change on wrapper in which I have list with hidden divs (which should show up on hover) it breaks showing that divs. t shows part of it or not at all (depends on browser). Do you have any idea why it breaks that functionality?
Link -> http://jsbin.com/rukanajugi/1/edit?html,css,output
Contrary to common belief, the will-change property may actually have an impact on the visual appearance of the element, as it creates a new CSS Stacking Context if used with Stacking Context Creating Properties (e.g. position, opacity, transform) BEFORE the actual transformation was made.
This may therefore change the layout, as the order of the layers (which element is above which one) may be changed.
In your case, the creation of the new Stacking Context through will-change: opacity, causes the layout issue. The hidden divs are positioned absolute, therefore don't increase the size of their parents/grandparents and are therefore cropped by the .menu-wrapper, which now has a stacking context.
You have multiple solutions for this, e.g.
Use .menu-wrapper { overflow: visible; }
Increase the Size like this: .menu-wrapper { height: 200px; }
Do not use Stacking Context creating properties on the will-changeattribute. E.g. using .menu-wrapper { will-change: border-width; } won't create any Stacking Context. As Soon as your .menu-wrapper gets properties, which create a Stacking Context (e.g. opacity: 0.9999), it will break again, however.

css opacity affecting sibling image opacity

I have a simple div with two children, a div with an image and yet another div as below:
<div style="width: 500px;">
<div class="settingicon righty">
<img src="/images/icons/setting.png" />
</div>
<div class="schedulepicker quat todaytoday">MONDAY</div>
</div>
I wanted so that when the second div is hovered, it reduces its opacity to 0.9, so in my CSS my .schedulpicker has this rule:
.schedulepicker:hover {
opacity: 0.9;
}
The problem is when it is hovered, the sibling image changes in opacity as well. Why is this so?
EDIT
Here's a fiddle
http://jsfiddle.net/VUzg9/4/
i am starting to wonder could it actually be the file itself.
EDIT 2
tested with jpg and gif, probably not the image issue.
You need to set the position (default is static) and a z-index for your image.
See jsfiddle
.righty {
float: right;
position: relative;
z-index: 100;
}
The opacity you're setting on #schedulepicker is creating a new stacking context, and stacking contexts affect z-indexes. Since you didn't specify z-indexes manually, they're being auto assigned, and #schedulepicker has a higher value than #settingicon because it comes later in the markup.
EDIT
The W3C color module says the following:
If an element with opacity less than 1 is not positioned,
implementations must paint the layer it creates, within its parent
stacking context, at the same stacking order that would be used if it
were a positioned element with ‘z-index: 0’ and ‘opacity: 1’.
Great question - it looks like a bug.
You need to put a position and a z-index on it in order to get it to work.
.righty {
float: right;
position: relative;
z-index: 1;
}
http://jsfiddle.net/VUzg9/9/
EDIT
I want to add to this answer because it's a very intriguing problem.
If we look at the spec it tells us that:
In future levels of CSS, other properties may introduce stacking contexts,
for example 'opacity' [CSS3COLOR].
As #enfredH04 pointed out in his answer, as soon as the element changes opacity, it appears to then gain a stacking context (maybe Blink implemented a part of the spec [quoted above] that has not actually been written, or at least published, yet?) It's sibling does not have it's own stacking context and, thus, appears behind the element that changes opacity.
You can see this if you give the element a starting opacity of 0.9 - http://jsfiddle.net/VUzg9/11/ - at this point it must gain a stacking context. (Interestingly a starting opacity of 1 does not give it a stacking context).
It's not changing the opacity of the "sibling", it's actually covering it up on-hover.
See two contrasting examples: jsfiddle
Setting position: relative and a z-index seem to solve the issue

the behaviour of top: auto; bamboozles me

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.

What has bigger priority: opacity or z-index in browsers?

I'm coding a "popup window" in JavaScript and I've come across an interesting thing:
The navy square under the popup window is visible even though I would expect it to be hidden. The popup was added after the square, so it should be on the top.
CSS opacity property of the navy square is 0.3. From what I've tried, it seems that every number from the interval (0,1) would yield the same result. If I change it to 1, then it behaves as expected (i.e. the part of the square under the popup is hidden).
I've tried to set the z-index property to 10 for the square and 100 for the popup, but it doesn't change anything.
What am I missing? Why is part of square displayed?
Tested browsers:
Firefox 3.6.x
Chrome 4
This is not a bug and is actually how it's supposed to work. It's a bit confusing as the elaborate description of Stacking Contexts doesn't mention anything about it. However, the visual formatting module links to the color module where this particular gotcha can be found (emphasis mine):
Since an element with opacity less than 1 is composited from a single
offscreen image, content outside of it cannot be layered in z-order
between pieces of content inside of it. For the same reason,
implementations must create a new stacking context for any element
with opacity less than 1. If an element with opacity less than 1 is
not positioned, implementations must paint the layer it creates,
within its parent stacking context, at the same stacking order that
would be used if it were a positioned element with ‘z-index: 0’ and
‘opacity: 1’. If an element with opacity less than 1 is positioned,
the ‘z-index’ property applies as described in [CSS21], except that
‘auto’ is treated as ‘0’ since a new stacking context is always
created. See section 9.9 and Appendix E of [CSS21] for more
information on stacking contexts. The rules in this paragraph do not
apply to SVG elements, since SVG has its own rendering model ([SVG11],
Chapter 3).
It's not a problem of opacity being more important than z-index, rather than z-index being relative to their stacking context (see z-index in the CSS2 specification).
In other words, z-index are only significant within the context of a positioned ancestor (whether its relative, absolute or fixed). What you need to do to fix your problem is add a position: relative; to the element that contain both your popup and your navy square, and probably add it a z-index: 1; . Seeing your screenshot it will probably be a top element such as a wrapper div.
Workaround for two elements, like divs: add a 0.99 opacity to your top element, and the order of both is reestablished.
opacity: 0.99;
An alternative to using opacity, is to use a transparent colour (with an alpha value)
So, rather than using
{
background: gray;
opacity: 0.5;
}
You could try
{
background: rgba(128,128,128,0.5);
}
It isn't identical, but I was encountering the same issue you were having, and the above fixed it.
Example code might be needed to debug this problem.
You might put overflow: hidden and possibly position: relative in a DIV which surrounds all the editor objects to try to force the elements to only be drawn within that DIV, e.g:
<div style="overflow: hidden; position: relative">
(Editor object buttons go here)
</div>
As a last resort, you could also try a iframe in between the two elements to try to stop them seeping through.
You might try to set the popup window's DIV like this using !important so the style doesn't change on applying new style or class:
background-color: white !important;
z-index: 100 !important;
opacity: 1.0 !important;
Then, make new CSS class:
.PopupElement
{
z-index: inherited;
opacity: inherited;
}
And add class to all elements in the window, like this for example:
<input value="posx" class="some_class PopupElement"/>
My guess is that this would work, since there is no priority in applying CSS attributes... as far as I know. =)
I had the same issue. Using rgba instead of color/opacity solved my problem. Working with LESS (in the Bootstrap framework), the fade() function did the conversion for me.
Although #Guillaume Esquevin already gave a great answer, I will try to expand on it in case someone ignores what a stacking context is (like I did).
As you can read here, there is something called stacking context, which refers to a group of elements sharing a parent that move together in the stack. An example could be a div and all its children.
There are three ways to create a stacking context: in the root of the document (the html element), by positioning the parent element, and by changing the opacity of the parent to something lower than 1.
Then, if you have a div with opacity lower than 1 and you want some sibling element of this div to appear behind it (and its children), you can create a new stacking context on such sibling by setting its position to relative or by changing its opacity as well.

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