z-index not working on pseudo-element - css

I have encountered a weird issue, while trying to implement a custom background on website I'm working on.
I've written a proof of concept code piece on codepen and it works perfectly there, but when I try to implement it on website it does not.
body {
background: black;
}
.background-test {
background: white;
width: 20%;
margin: 2% 50%;
height: 250px;
padding: 1%;
position: relative;
}
.background-test:before {
width: 100%;
height: 100%;
content: "";
background: red;
position: absolute;
z-index: -1;
bottom: -3%;
left: -2%;
-webkit-clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
}
<div>
<div class="background-test">Lorem Ipsum</div>
<div></div>
</div>
https://codepen.io/Hassansky/pen/eEaQxG/
You can see that the :after pseudo element is positioned correctly - in theory. When I try to implement this into the website I'm working on, it just doesn't show. Chrome Dev tools shows it's there, just not displaying it. It does show up when I disable the z-index on dev tools, but then it stacks on top of the parent, as it should.
I tried to look for stacking issues, but I'm at wits end and cannot find any reasonable explanation for this.
This is a Wordpress website loaded with theme, but this should not present an issue with z-index stacking, especially when I cannot find any rule regarding z-indexes there.
Page url: http://polkrys.pl/cukiernia/podklady-cukiernicze-okragle-biale/
I've marked which elements should have pseudo-elements on them.
I'm adding SASS code that relates to elements in question:
.polkrys_shadow {
position: relative;
&:before {
width: 100%;
height: 100%;
content: "";
background: red;
position: absolute;
z-index: -1;
bottom: -3%;
left: -2%;
-webkit-clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
}
The margins and paddings are defined within wordpress visual composer. I suggest inspecting mentioned elements with Dev Tools - you'll see it should work - but it doesn't.

The parent element of the :pseudo-element requires a z-index declared as well in order for the z-index of the :pseudo-element to function as intended. But doing so will stack the :pseudo-element over the parent element, concealing the background and nested content.
To rectify this, nested content should have a higher z-index declared. And an additional :pseudo-element (:after) should be declared to overlay the initial :pseudo-element (:before) with the background fill applied (e.g: "white"), to conceal the initial pseudo-element only allowing the overflow to reveal.
.logistic-bg .polkrys_shadow:after { /* Additional pseudo-element added */
content: "";
background: white;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.logistic-bg .polkrys_shadow { /* Adjustments made on parent element */
z-index: 9;
}
.logistic-bg div:first-child { /* Adjustments made on nested element */
position: relative; /* required for z-index to apply */
z-index: 99;
}

I found this solution:
el {
transform-style: preserve-3d;
}
el:before {
transform: translateZ(-1px);
}

<div>
<div class="background-test">Lorem Ipsum <div style="z-index:100;color:blue;background-color:yellow;">vgghuu</div>
</div></div>
body {
background: black;
}
.background-test {
background: white;
width: 20%;
margin: 2% 50%;
height: 250px;
padding: 1%;
position: relative;
z-index: 1;
}
.background-test:before {
width: 100%;
height: 100%;
content: "";
background: red;
position: absolute;
z-index: -1;
bottom: -3%;
left: -2%;
-webkit-clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
clip-path: polygon(2% 4%, 100% 0, 99% 97%, 0 100%);
}

Related

Bug or Intention - fixed CSS gradient is cropped to 50%

When setting a background gradient to background-attachment: fixed it is suddenly cropped to 50% of the page width. It seems related to the position left: 50%. I wonder if this is a bug or if I'm using the CSS wrong here:
.container {
position: relative;
height: 80px;
margin: 10px 0
}
.container:before {
content: '';
position: absolute;
top: 0;
bottom: 0;
width: 100vw;
background: #f0f0f0;
background-image: repeating-linear-gradient(315deg,rgba(0,0,0,.03),rgba(0,0,0,.03) 10px,rgba(0,0,0,.06) 0,rgba(0,0,0,.06) 20px);
left: 50%;
transform: translate(-50%);
}
.container.fixed-bg:before {
background-attachment: fixed; /* <-- This line causes the problem. Why? */
}
<div class="container">...</div>
<div class="container fixed-bg">...</div>
I know that I can bypass the issue by removing the styles left: 50%; and transform: ... but that's not a practical solution in my case. The container has an unknown left margin and the pattern needs to reach from edge to edge.
Does that mean my CSS is wrong? What CSS would display the fixed background pattern in full width?
Update
I notice that there is a different behavior across browsers:
The bug seems to be related to transform. Use margin instead
.container {
position: relative;
height: 80px;
margin: 10px 0
}
.container:before{
content: '';
position: absolute;
top: 0;
bottom: 0;
width: 100vw;
background: #f0f0f0;
background-image: repeating-linear-gradient(315deg,rgba(0,0,0,.03),rgba(0,0,0,.03) 10px,rgba(0,0,0,.06) 0,rgba(0,0,0,.06) 20px);
left: 50%;
margin-left:-50vw;
}
.container.fixed-bg:before{
background-attachment: fixed;
}
<div class="container">...</div>
<div class="container fixed-bg">...</div>

Background-blend-mode not working on mobile

I used background-blend-mode: lighten; to essentially lighten the intensity of the black background image (refath.github.io/Survey). While it works perfectly on Desktop, I checked the site on my phone, and for some reason, the black background simply overrides the background-blend-mode, if that makes sense. I even tried using !important to override any libraries that may be interfering with the design, but to no avail. Here's the relevant code:
CSS:
body{
padding: 20px;
margin: 0;
background-image: url("https://wallpaperplay.com/walls/full/2/b/1/99126.jpg");
background-color: rgba(255, 255, 255, 0.95);
background-blend-mode: lighten !important;
max-width: 100%;
overflow-x: hidden;
}
<body>
</body>
On Desktop (Chrome):
On iPhone X (Chrome):
Any help would be greatly appreciated. Thanks.
I don't see Chrome for iOS on caniuse's list, but browser support for that css rule is still spotty. It could be that there simply isn't support for it yet. Since Edge doesn't support it, it's typically good to have a backup plan for when it fails. Have you tried other browsers on iOS?
Why not using overlay of color on a body
body{
padding: 20px;
margin: 0;
background-image: url("https://wallpaperplay.com/walls/full/2/b/1/99126.jpg");
max-width: 100%;
overflow-x: hidden;
position: relative;
}
body:before{
content: '';
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(255, 255, 255, 0.95); /* Your desire color */
z-index: 2;
}
OR
<div id="overlay"></div>//place inside body tag
#overlay {
position: fixed; /* Sit on top of the page content */
display: none; /* Hidden by default */
width: 100%; /* Full width (cover the whole page) */
height: 100%; /* Full height (cover the whole page) */
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5); /* Your desire color */
z-index: 2; /* Specify a stack order in case you're using a different order for other elements */
}

Multiple U shapes divs

I'm trying to obtain some nice U shapes divs.
This is the expected result (it must look nice and be responsive):
This is the solution I found for footer (the shape is not so good as I want):
footer:after {
content: "";
display: block;
position: absolute;
border-radius: 0px 0px 50% 50%;
width: 100%;
height: 140px;
background-color: white; /* but if I choose a bg image for about us this solution is wrong */
left: 0;
top: 0px;
}
I will have multiple sections similar to #about-us. Can you suggest a nice starting solution here? Please keep in mind in brand section background I have an animation, in footer a background image. This is why I can't use in about-us the solution I used for footer. It's kind of let's cut this div with an oval and make this section transparent.
UPDATE:
My current header / about us annoying merge. Adding a gray shape (inside header or in top of about us) is not a solution.
.u-shape {
height: 120px;
right: -100px;
left: -100px;
z-index: 1000;
position: absolute;
margin: 0 auto;
}
.u-shape.top {
top: -120px;
background: radial-gradient(ellipse at 50% 0, transparent 69%, white 70%);
}
.u-shape.bottom {
top: 0;
background: radial-gradient(ellipse at 50% 0, white 69%, transparent 70%);
}
Usage:
<header>...</header>
<div class="u-shape top"></div>
<div id="about-us"></div>
<div class="u-shape bottom"></div>
<footer>...</footer>
Useful:
https://codepen.io/thebabydino/pen/wFvmA

Is it possible to cut specific parts of an image?

Sometimes images just explain things better than 1000 words
assumed the black border is my image I want to cut off the top left/right edge - like marked by the red lines.
Would it be possible (if yes: how) to cut an image this way with CSS?
Just in case its not clear what I mean by cut: I want
By cut I mean, that the image will look like this
Without using a wrapper element, you can use clip-path, though the support isn't great.
img.cut {
-webkit-clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
clip-path: polygon(50px 0, calc(100% - 50px) 0, 100% 50px, 100% 100%, 0 100%, 0 50px);
}
<img class="cut" src="http://lorempixel.com/200/300/">
This uses calc (widely supported), so you can specify exact pixel values to clip by.
CSS Pseudo
If you know you're background is going to remain a solid colour, you can achieve this using pseudo elements in a number of ways.
1st option
A very simple solution is to use the pseudo elements with borders to which should get you the effect you want.
div {
height: 300px;
background: red;
position: relative;
}
div:before {
content: '';
position: absolute;
top: 0;
left: 0;
border-top: 80px solid white;
border-right: 80px solid red;
width: 0;
}
div:after {
content: '';
position: absolute;
top: 0;
right: 0;
border-top: 80px solid white;
border-left: 80px solid red;
width: 0;
}
<div></div>
2nd Option
Using a single pseudo element which is larger than the parent and rotating it to get the desired effect.
This is a much cleaner effect and also means the use of background images is supported and easier to implement.
div {
height: 200px;
width: 200px;
background: transparent;
position: relative;
z-index: 9;
overflow: hidden;
}
div:before {
content: '';
width: 200%;
height: 200%;
position: absolute;
transform: rotate(45deg);
background: red;
left: -50%;
top: 20px;
<div></div>

CSS Background-Blend-Mode over two Elements

Lets assume I have a div with a Gradient applied as a background-property.
I now want to overlay a black PNG (of smaller size) and set the PNG to have a background-blend-mode of overlay. Unfortunately I have no idea on how to achieve this.
I know I can have a working background-blend-mode when I render the Gradient into the CSS of the Div with the PNG image like:
background: url(../img/plus.png), linear-gradient(to bottom, #24cae4 0%, #1f81e3 100%);
background-blend-mode: overlay;
This however results in the Gradient being as small as the actual PNG, which is not a desired effect, like this:
What I want to achieve is this with pure CSS (if possible):
Here a Codepen to illustrate what I'm trying to do: http://codepen.io/anon/pen/zxOXGP
Notice the Black Icon. I wanna overlay this.
Try using mix-blend-mode instead of background-blend-mode and switch to simple text for the plus-sign or a webfont for more custom figures.
Example Codepen of the below:
.placeholder {
position: relative;
width: 400px;
height: 300px;
background-image: -moz-linear-gradient(#ff0000, #0000ff);
background-image: -webkit-linear-gradient(#ff0000, #0000ff);
background-image: linear-gradient(#ff0000, #0000ff);
}
.center {
position: absolute;
top: 25%;
width: 100%;
font-size: 120px;
}
.center span {
display: block;
text-align: center;
color: red;
mix-blend-mode: screen;
}
<div class="placeholder">
<div class="center"><span>+</span>
</div>
</div>
The gradient sandwich
Ingredients
The :before forms the bottom z-layer with z-index: 1, it is full opacity
The .content div forms the filling, central z-layer, with z-index: 2. It needs position: relative to take its z-index.
The :after forms the top z-layer with z-index: 3 and completes our lunch item. It is half opacity.
This is the tasty result:
Full Example
I have removed all but the standard CSS3 gradient for simplicity. View in a supporting browser.
.gradient {
position: relative;
height: 200px;
padding: 20px;
}
.gradient:before,
.gradient:after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
display: block;
background-size: 100%;
background-image: linear-gradient(to bottom, #24cae4 0%, #1f81e3 100%);
opacity: 0.5;
}
.gradient:before {
opacity: 1;
z-index: 1;
}
.gradient:after {
z-index: 3;
}
.overlayed_image {
position: relative;
width: 64px;
height: 64px;
display: block;
margin: auto;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
background-image: url(http://cdn.flaticon.com/png/256/9029.png);
}
.content {
position: relative;
z-index: 2;
}
<div class="gradient">
<div class="content">
You can see me!
<div class="overlayed_image"></div>
</div>
</div>

Resources