::before pseudo-element with negative z-index not displaying behind parent - html

I swear I've done this a hundred times, but for the life of me, I can't figure out why my :before pseudo-element's background is displaying behind the text but not behind the anchor's background. Thoughts?
.button {
background: tomato;
padding: 10px 30px;
margin: 20px 0;
display: inline-block;
}
.button:hover {
margin: 18px 0 22px 2px;
position: relative;
z-index: 2;
}
.button:hover:after {
position: absolute;
background: red;
top:-2px;
left: -2px;
content: "";
z-index: -10;
width: 100%;
height: 100%;
}
<a class="button" href="#">Meow</a>
Sample here: http://jsfiddle.net/cfree/hnKLr/

When you add a z-index value to an element, you create a new stacking context. Every child of that element will stack on top of it.
So when you want to place an element behind its parent, simply don't create a stacking context on the parent. You still need to use a negative z-index though, because the default stack level of the parent will be 0 (in whatever context the element is)

The ::before and ::after pseudo-elements are named a bit confusingly – they behave as if they were children of the matched element, not its siblings.
In this particular case, it seems like a box-shadow would be most appropriate:
.button:hover {
box-shadow: -2px -2px 0 red;
}
Is this the effect you were looking for?

Related

How to show the border css over the div element?

Image attached in this link
In number 9 cell border is over the background color
How do I show the border over the div or background Color and it should be responsive?
<div className="borderOverDiv"><div>
<div className="backgroundClr"></div>
.borderOverDiv{
position: absolute;
border: 1px solid red;
width: calc(100% - 94%);
height: 30px;
border-radius: 10px;
}
.backgroundClr{
background: blue
}
this code as I tried, seems not working
I am assuming that you are new to css so I will try to explain what is going on with this code the best that i can.
The fun part is in .element.active:after
There is a few thing
position: absolute this will allow us to set this element absolutly to container. But witch container? First that has position set to a different value than static or its initial value. That is why .element has position: relative which doesn't do anything on its own.
top, right, bottom, left which tell that this element will be exceeding parent element on every side by 5px.
z-index Simply the higher the value the "closer" this element is to user. initial value is 0 so 1 is placing this element above every other element.
content is required in pseudo-element :after in order to show them. This property just needs to be set and doesn't have to have any value specified.
The reis is just to make it look nicer.
And thats it.
You can use other element inside .element if you feel like it.
For example
<div class="element">
<div class="overlay"></div>
</div>
and it will work just fine if you will follow point form 1 to 3 (point 4 is required, as I said earlier, only in pseudo-element) but it will be less responsive. For example what will you have to do when other element needs this overlay? You will have to use javascript to append .overlay element to .element and with pseudo-element you just need to append class. or just show this overlay on hover. Other advantage is that it look prettier and doesn't bloat you html.
.container {
padding: 5px;
display: flex;
}
.element {
position: relative;
background-color: #0000ff;
padding: 10px 20px;
display: inline-block;
color: #ffffff;
}
.element.active:after {
content: '';
position: absolute;
top: -5px;
right: -5px;
bottom: -5px;
left: -5px;
border-radius: 40px;
background-color: rgba(200, 200, 200, .4);
border: 1px solid rgba(200, 200, 200 ,.8);
z-index: 1;
}
<div class="container">
<div class="element">7</div>
<div class="element active">8</div>
<div class="element">9</div>
</div>
replacing className with class should do the trick

Multiple box with triangle on bottom of div

I'm fighting with css code to obtain something that should be pretty easy:
adding a triangle at the bottom of multiple div on the same page.
Here it's the code I'm working with:
.areatitolo {
background-color: #bb0000;
color: #fff;
font-size: 18pt;
font-weight: bold;
text-align: center;
padding:5%;
margin-top:100px;
width:100%;
margin-bottom:60px;
}
.areatitolo:after{
content:'';
position: absolute;
top: 100%;
left: 0;
right: 0;
margin: 0 auto;
width: 0;
height: 0;
border-top: solid 50px #bb0000;
border-left: solid 100px transparent;
border-right: solid 100px transparent;
}
There shouldn't be any problem, apart from the fact that only the first one works and I need to use the same effect 3 times...
Do you know where I made the mistake?
https://jsfiddle.net/federico_feroldi/0zrfL4q1/4/
Thank you for your help.
Add position: relative; to .areatitolo.
you should use position :relative to the class .areatitolo .Because you have used absolute for ::after. whenever you use position absolute to a child element ,you should use position relative to parent if not the absolute child will take body as relative parent by default ,thats why the first triangle appears at the top all the other triangles get overlaped on top
For a child element to be absolutely positioned, the parent must have a position: relative; property applied to it. This gives the child a reference point for it's positioning.
Additionally, consider using ::after instead of :after for a more modern CSS3 syntax. See MDN for more information.

stacking pseudo-elements with z-index

I am having trouble properly stacking my divs using CSS z-index. In my code, if I set .nose::before and .nose::after to z-index: -1, it puts the two divs at the very back of the stack. However, I just these divs to sit behind the .nose div. Here's my code:
*, *::after, *::before {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body { height: 100%; }
body {
background: #44BBA4;
}
.head {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 375px;
width: 400px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
}
.head::before, .head::after {
content: "";
position: absolute;
height: 90px;
width: 90px;
background: #df9e27;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
.head::before {
top: -30px;
left: 40px;
}
.head::after {
top: -30px;
right: 40px;
}
.eye {
position: absolute;
top: 150px;
height: 25px;
width: 25px;
background: #000;
border-radius: 50%;
}
.eye.left {
left: 90px;
}
.eye.right {
right: 90px;
}
.eye::before {
content: "";
position: absolute;
top: -50px;
left: -37px;
height: 100px;
width: 100px;
border-radius: 50%;
border: 12px solid transparent;
border-top: 12px solid #000;
}
.nose {
position: absolute;
margin: auto;
right: 0;
left: 0;
bottom: 130px;
height: 30px;
width: 30px;
background: #000;
border-radius: 50%;
}
.nose::before, .nose::after {
content: "";
position: absolute;
height: 68px;
width: 73px;
background: #fff;
border-radius: 50%;
border: 10px solid #000;
z-index: -1;
}
<div class="head">
<div class="eye left"></div>
<div class="eye right"></div>
<div class="nose"></div>
</div>
In short: Set z-index on your head element. Move ears out of the head element.
Here is why.
z-index has stacking contexts. Each of those contexts has a root element (just any html element). Now, to become a root element it must comply with any of the following rules:
be <html> element
position other than static and z-index other than auto
opacity less then 1
So the default stacking context is with the <html> element as a root.
Once the element is inside a scope (in other words, child of a root element), it can only be positioned relative to the elements inside the scope.
Think about it as a nested list.
Wrap here is a root element, as it has position set to relative and z-index to 1. And all of its children are now inside a stacking scope with the Wrap as a root.
So, like in a nested list, children of a particular element cannot appear before its root. For example, Child2 cannot appear before the Wrap, since it is scoped inside of it. But it can appear before the Child1.
Now, in your case the structure is as follows:
Notice that the head is not a root, because it doesn't comply with the rules for becoming one (positioned elements must also have z-index other than auto). Therefore when you assign z-index of -1 to the Nose::before and ::after you get this:
The elements have been positioned all the way behind the Head, because they are in the same stacking scope. But they appear on top of Head::before, since when elements have the same z-index, they are stacked according to the order of appearance in html.
Now, to prevent head children from appearing behind it, you must add z-index to it. This will make it a root element of new stacking scope.
But this creates another problem. Now ears are positioned on top of the head. This is not possible to solve with css alone, since they are inside a stacking scope of the head. And root always lies behind every of its children.
To solve it, you must move the ears out of the head. So, it means, you won't be able to use pseudoelements (before & after) anymore. I suggest creating ear elements outside of the head and wrapping everything in some other element (named bear?) with position relative. Wrapper is needed if you still want to position ears relative to the head.
The answer is mostly inspired by this article.

HTML pseudo elements placed over actual child nodes

For some reason, when an element's pseudo child node is added, its z-index is higher than its child nodes, even though its a ::before element, which appears before the relative child nodes, but doesn't display that way. Why does this happen, and is there a way to fix it?
Here's an example where the child <h1> node should appear as if it's hovering over the black pseudo element, but that isn't the case.
https://jsfiddle.net/9u33vko0/
Is my understanding just fundamentally wrong?
div {
width: 100%;
padding: 40px 0;
border: 1px solid #DDD;
text-align: center;
color: #FFF;
position: relative;
}
div::before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: #000;
width: 100%;
}
<div>
<h1> <!-- should appear above the black ::before element -->
Hello, World!
</h1>
</div>
Even though the :before pseudo element appears before the h1 element in the DOM, it will still overlap the h1 element because it establishes a stacking context due to the fact that it is positioned (with position: absolute).
Here is a relevant quote from the CSS2 specification on stacking contexts (painting order; point 8)
All positioned descendants with z-index: auto or z-index: 0, in tree order. For those with z-index: auto, treat the element as if it created a new stacking context ...
Therefore you could establish a stacking context with the h1 element by positioning it (i.e., by adding position: relative). In doing so, the h1 element will be placed above the :before pseudo element because it appears after the pseudo element in the DOM and both elements are positioned with a z-index of auto.
Updated Example
h1 {
position: relative;
}
div {
width: 100%;
padding: 40px 0;
border: 1px solid #DDD;
text-align: center;
color: #FFF;
position: relative;
}
div::before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: #000;
width: 100%;
}
h1 {
position: relative;
}
<div>
<h1>Hello, World!</h1>
</div>
Of course, you could also just give the pseudo element a negative z-index, but that's besides the point. When it comes down to it, establishing a stacking context is enough since the :before pseudo element appears before the h1 element in the DOM (as you have already pointed out).

Parent's inset Box-Shadow overlapped by child element

I have this code
http://jsfiddle.net/4fz5g/2/
<div class='A' id='AA'>
<div class='listContainer'>
This div is cutting Parents inset box-shadow
</div>
</div>
My question is why does the inset box shadow of parent do not overlap the children? Is there a way to make it overlap.
p.s: I do not want to add inset drop shadow to children instead to make it appear as if drop shadow of parent is "casting shadow" over its children.
You need to play with z-index to set the order / visibility of the elements.
The problem is that in the A element, you have also a background. If you set the z-index of the child negative, it will be hidden by the background.
One posibility to solve that would be to create a pseudo element, and set the shadow on it:
.A {
width: 80%;
position: absolute;
top: 0;
height: 300px;
background-color: #408800;
padding: 0px;
}
.A:after {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
width: 12px;
box-shadow: -12px 0 10px -10px #000000 inset;
z-index: 2;
}
demo
While i don't know if there's a way to avoid this,
adding box-shadow: inherit; to the child element should fix the appearance
as it adds the same inset shadow to it.
example: http://jsfiddle.net/4fz5g/3/