Why is ::before pseudo element appearing on top of the element? - css

From my understanding, ::before should appear below the element, and ::after should appear above of the element (in terms of z-index).
In the following example I am trying to make just the background color darker (not the foreground color) when one hovers over the button. Even though I used ::before it still appears in front. Why? I know I could fix it with z-index, but according to this comment which has 6 upvotes:
I think it's better to use :before so you get the right stacking order without playing with z-index.
I should not have to, and the order should be correct?
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
button:hover::before {
display: block;
content: "";
position: absolute;
top: 0; left: 0; width: 50%; height: 100%; /* width is 50% for debugging (can see whats below) */
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>

There's no difference between ::before and ::after regarding the z-index or z-axis order. By default both will be placed in front of their parent, covering it (if their position is defined accordingly). To achieve z-axis layering beyond that, you need to actually use a z-index (besides a combination of relative and absolute position).
Addition after comment:
In the snippet below there are two variations of the situation. The only difference if that once ::after is used, once ::before, both times without a z-index, and both time with the same result, i.e. the pseudo element covering its parent:
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
.parent:nth-child(1) button:hover::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
.parent:nth-child(2) button:hover::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>
<div class="parent">
<button type="button">CLICK ME</button>
</div>
So, to come back to your question in your second comment: Yes, they are wrong - you need to use a z-index to move the pseudo element behind the parent.
So your actual solution should look like this, using a negative z-index: -1; for the pseudo element (and you could as well use ::after here, it doesn't matter...).
.parent {
--my-color: red;
}
button {
color: blue;
background-color: var(--my-color);
padding: 8px 16px;
position: relative;
}
button:hover {
background-color: transparent;
}
button:hover::before {
content: '';
position: absolute;
z-index: -1;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: var(--my-color);
filter: brightness(80%);
}
<div class="parent">
<button type="button">CLICK ME</button>
</div>

Related

How to get a background color low opacity overlay on a featured image? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
He everyone i am strugling to find a css that will work to get a overlay on my feautured image so you can see my title more clear. For the site www.quinstudio.nl/gallery. Any idea how i can get this to work?
? {
background: #000;
opacity: .1;
}
There are several ways you could approach this. There's no real difference in how they'll turn out; you can use whichever works better with the markup you have. The first option is a little simpler because there's no empty div being added as a color overlay.
Option 1: Make the colored background opaque, and the image partially transparent.
.image-wrapper {
display: inline-block;
background: #0cd;
/* You need this line for the centered h1 below to work. */
position: relative;
}
.image-wrapper img {
opacity: 0.5;
display: block;
}
.image-wrapper h1 {
/* Here's a trick for centering your title, if you want. */
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
margin: auto;
color: #fff;
}
<div class="image-wrapper">
<img src="https://loremflickr.com/320/240" alt="Kitten">
<h1>Kitty!</h1>
</div>
Option 2: Make the image opaque, and put a partially transparent overlay on top of it.
.image-wrapper {
display: inline-block;
position: relative;
}
.image-wrapper img {
display: block;
}
.image-overlay {
background: #000;
opacity: 0.5;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 2; /* puts this div 'in front' of the image */
}
.image-wrapper h1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
z-index: 3; /* puts the text in front of the dark overlay */
}
<div class="image-wrapper">
<img src="https://loremflickr.com/320/240" alt="Kitty!">
<div class="image-overlay"></div>
<h1>Kitty?</h1>
</div>
While #jack's answer is good, I'd like to share an alternative one that doesn't use an <img> element and instead uses the :after pseudo-element.
This allows you to use the CSS background image on the container and essentially add a fake element that has the color overlay on it:
.container {
background: url(https://loremflickr.com/320/240);
width: 320px;
height: 240px;
position: relative;
}
.overlay > * {
z-index: 1;
position: relative;
color: #fff;
}
.overlay:after {
content: "";
background: #0095ee;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: .65;
}
<div class="overlay container">
<h1>Title</h1>
</div>
Edit:
Your situation is a little different. You can just lower the opacity of the image and add a black background to it's parent container. Try the following:
.edgt-justified-layout .edgt-ni-inner .edgt-ni-image-holder .edgt-post-image img {
opacity: .75;
}
.edgt-justified-layout .edgt-ni-inner .edgt-ni-image-holder .edgt-post-image {
background: #000;
}
It will lower the opacity of the image (which will make it look "whiter", so we can add a black (or whatever color you want) background to it's parent container to compensate and darken it instead.

Why are my pseudo-classes overriding display:none?

I have a div that appears as an "X" (used to close a window):
<div class="alertwrapper" style="display:inline-block;">
<div class="obj"></div>
<div class="x"></div> //<-----ELEMENT IN QUESTION
</div>
The following are the CSS properties of this element:
.x {
display: none !important;
position: absolute !important;
left:0;
top:0;
transition: transform .25s ease-in-out;
z-index:999;
}
.x:before {
content: "";
position: absolute;
//Here, I've also tried display:none !important;
left: 48%;
margin-left:-495px;
right: 0;
top: 115px;
bottom: 0;
width: 32px;
height: 0;
border-top: 3px solid black;
transform: rotate(45deg);
transform-origin: center;
z-index:999;
}
.x:after {
content: "";
position: absolute;
//Here, I've also tried display:none !important;
left: 48%;
margin-left:-495px;
right: 0;
top: 115px;
bottom: 0;
width: 32px;
height: 0;
border-top: 3px solid black;
transform: rotate(-45deg);
transform-origin: center;
z-index:999;
}
This div should not be displayed until another element is clicked, at which point, it should appear, as defined by the following code:
<script type="text/javascript">
$(document).ready(function () {
$('body').on('click', '.ActiveQuestionCycler', function() {
$("div.x").fadeIn(300).delay(1500);
$("div.obj").fadeIn(300).delay(1500);
});
});
</script>
When the page loads, however, the div "x" is visible, before .ActiveQuestionCycler is clicked. (The display is not set to none.) I think this has to do with the pseudo-classes before and after overriding this but I can't figure out why.
(div.obj DOES fade in when .ActiveQuestionCycler is clicked.)
There are no error alerts in the source.
This comment /// STYLE SETTINGS FOR THE QUESTION CONTAINER AND CLOSE "X" BUTTON on line 109 is invalid. Change it to:
/* STYLE SETTINGS FOR THE QUESTION CONTAINER AND CLOSE "X" BUTTON */
and it should work. Remember to drop that display: none; into the .x
So it will look like:
.x {
display: none;
/* your other styles */
}
While // comment is normal for most programming languages, regular css does not accept it and css comments go like this /* comment */

How can I create a straight "beveled" corner (or two) with an outline using CSS?

Similar to these, but with a separate border. I asked this question earlier, but didn't realize there were other methods besides using linear gradients.
Examples: http://i.imgur.com/TqVR67J.png
It's not pure CSS (and probably not exactly what you're looking for), but you could just do a larger element first that just forms the border, and then have a smaller sibling element with offset afterwards:
<div id="background"></div>
<div id="foreground"></div>
and then the css:
#background{
position: absolute;
}
#foreground{
position: relative;
top: 5px;
left: 5px;
}
(Obviously, you would have to add all of the styling and extra tags for the beveling.)
Take a look at this fiddle. This might gave you an idea of how to create it with css.
Beveled border with css
HTML
<div class='box'>
<img src="http://placehold.it/350x150" />
<img class='cart' src="http://www.rotweinelang.at/themes/wein/img/elements/smallShoppingCartIcon.png" />
</div>
CSS
.box {
width: 350px;
position: relative;
}
.box::after {
content: "";
position: absolute;
top: 0;
right: -2px;
border-style: solid;
border-width: 0 40px 40px 0;
border-color: transparent #fff transparent transparent;
}
.cart {
position: absolute;
top: 0;
right: -4px;
z-index: 1;
}

Firefox css transition doesn't start when preceded by generated content

** Update **
If anyone else encounters this issue, a bug has been filed with Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1011153
http://jsfiddle.net/ZEzc9/3/
Found this today and setup a fiddle for it. The best I can tell right now is that if a target element is preceded by generated content where a transition effect applied, the transition fails to start.
html:
"Some text" animates up and down smoothly on hover.
<div>
<div>
<span> Some text</span>
</div>
</div>
"Some text" should animate in and and out. In Firefox, the generated content on div > div:hover::before stops the inital animation.
<div>
<div>
<span> Some text</span>
</div>
</div>
CSS:
div {
width: 300px;
height: 100px;
position: relative;
outline: 1px solid #cc0000;
}
div > div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 2px solid #000;
}
div > div > span {
bottom: 10px;
}
div > div > span {
position: absolute;
bottom: 20px;
left: 20px;
-webkit-transition: bottom 250ms;
transition: bottom 250ms;
}
div:last-child > div:hover::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #cc0000;
}
div > div:hover span {
bottom: 50px;
}
I am only seeing this behavior in Firefox. Is there a reason this is happening or does it seem to be a bug in FF?
Looks like a bug, I see the same thing using Fx 29.0.1, Win7 x64.
However, for what it's worth, it will work if you create static invisible generated content without the :hover pseudo-class, i.e.
div:last-child > div::before {
content:'';
/* … */
background:transparent;
}
but make it visible on hover, i.e.
div:last-child > div:hover::before {
background:#cc0000;
}
I updated your fiddle to show this.

Can't get text content to be above a masking div

I have a div with a background image that should be covered with a mask effect. On that div should be some content. I'm trying to get the content to be over the mask but for some reason it isn't working.
I added a jsFiddle:
http://jsfiddle.net/FHt9d/
Here is the code:
Html:
<div id="container">
<div id="mask"></div>
<div id="content"><h1>This is a header</h1></div>
</div>
Css
#container
{
width: 100%;
height: 246px;
position: relative;
background-repeat: no-repeat;
background-size: 100%;
background-image: url('http://upload.wikimedia.org/wikipedia/commons/d/d8/Skyline_oklahoma_city.JPG')
}
#mask
{
z-index: 1;
height: 100%;
width: 100%;
background-color: rgba(75,139,228,.8);
position: absolute;
top: 0;
left: 0;
}
#content h1
{
z-index:2;
font-size: 32;
color: #fff;
}
The text should not be covered by the mask. Any help would be greatly appreciated,
Thanks!
try this (you missed a position: relative;):
#content h1 {
color: #FFFFFF;
position: relative; //missed
z-index: 2;
}
The elements that have
position: absolute
are always on top. Same thing applies to
position: fixed;
They always float above the elements in a browser.
To minimize this, you use
z-index: value;
For the elements with position value set, you can use:
z-index: 1;
and change it for the element you want to be above others
z-index: 2; /* or more than 2 */
This will do the job.
You missed a position: relative; on the #content h1. Indeed, z-index applies only on positionned elements.

Resources