Remove mix-blend-mode from child element - css

How can I set mix-blend-mode on an element, but not it's children? Setting the children to the default value of normal does not seem to work:
http://jsfiddle.net/uoq916Ln/1/

The solution on how to avoid mix-blend-mode affects children:
Make child element position relative, give it a width and height;
Create some real or pseudo element inside the child with absolute position, and apply mix-blend-mode to it;
Create inner element inside the child for your content. Make it's position absolute, and put it on top of other elements;
Live example
html
<div class="bkdg">
<div class="blend">
<div class="inner">
<h1>Header</h1>
</div>
</div>
</div>
css
.blend {
position: relative; /* Make position relative */
width: 100%;
height: 100%;
}
.blend::before { /* Apply blend mode to this pseudo element */
content: '';
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 1;
background-color: green;
mix-blend-mode: multiply;
}
.inner { /* This is our content, must have absolute position */
position: absolute;
z-index: 2;
}
h1 {
color: white;
}

I know this was asked over two years ago, but it could be useful in the future as it could be a better solution than creating pseudo-elements.
There is the CSS isolation property that allows to choose wether the child element should be rendered in its parent's context (auto) or as part of a new context, thus without any blend mode applied to it (isolate).
Check out this page for examples

someone commented that the the whole block is rendered with the effect and that is why you're having the issue. I am able to accomplish what you're are trying to do by removing the h1 from the block, position absolute, and a z-index of 1. here is a jsfiddle to show the effect.
html
<div class="bkdg">
<h1>Header</h1>
<div class="blend">
</div>
</div>
css
.blend {
background-color: green;
mix-blend-mode: multiply;
width: 700px;
height: 35px;
}
h1 {
color: white;
position: absolute;
top: -15px; left: 10px;
z-index: 1;
}
https://jsfiddle.net/jckot1pu/

It’s impossible to remove an element’s mix-blend-mode from its children.
MDN says that mix-blend-mode:
sets how an element's content should blend with the content of the element's parent and the element's background
To achieve the desired effect, place the child in a separate stacking context and make sure it renders on top of the element with mix-blend-mode set.
You need two things to make this work:
Make sure that your opaque content (your text) is not a child of the element that sets the background and the blend mode. For example, with CSS Grid Layout.
Make sure the text is rendered over, and thus not affected by, the element that sets the background and the blend mode. Setting mix-blend-mode on your background will create a stacking context for it, and you may need to give your content its own stacking context to ensure it gets rendered above it.
Position your elements with CSS Grid:
define a grid container with one auto-sized grid area
place both the background element and the text element into that one grid area (so that they overlap)
let the text element dictate the size of the grid area
have the background element stretch to the size of the grid area, which is dictated by the size of the text element
Then, set isolation: isolate on the text element to ensure it gets rendered above, and not under the background element.
A working example
.container {
display: grid;
grid-template-areas: 'item';
place-content: end stretch;
height: 200px;
width: 400px;
background-image: url(https://picsum.photos/id/237/400/200);
background-size: cover;
background-repeat: no-repeat;
}
.container::before {
content: '';
grid-area: item;
background-color: seagreen;
mix-blend-mode: multiply;
}
.item {
grid-area: item;
isolation: isolate;
color: white;
}
h1,
p {
margin: 0;
padding: 10px;
}
<div class="container">
<div class="item">
<h1>HEADLINE</h1>
<p>Subhead</p>
</div>
</div>

An important note if you're using the excellent pseudoelement ::before/::after solution posted by Rashad Ibrahimov.
I found that I had to remove z-index from the parent element and apply it only to the pseudoelements and child elements before mix-blend-mode: multiply would work.
For example
#wrapper {
position: relative;
}
#wrapper .hoverlabel {
position: absolute;
bottom: 0;
left: 0;
right: 0;
/* z-index: 90; Uncomment this to break mix-blend-mode. Tested in Firefox 75 and Chrome 81. */
}
#wrapper .hoverlabel::before {
position: absolute;
content: "";
top: 0;
bottom: 0;
left: 0;
right: 0;
mix-blend-mode: multiply;
z-index: 90;
background-color: rgba(147, 213, 0, 0.95);
}

Related

How can I prevent content of before psuedo element from overflowing its width and height?

How can I prevent content of before psuedo element from overflowing its width and height?
CSS styles for this ::before psuedo element is:
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAASCAYAAABFGc6jAAAAAXNSR0IArs4c6QAAAc1JREFUOBHtlE8oBHEUx9+bYVknFMrBRcmJk9pEuXLWXhQHJ/vHvyJOrJKLsGxbW3KghDMOTiiSE22UIncuFLLszPNm1/xm5mftn4uT32W+n/e+772Z329mEKRFgfFaoEQPELowujQrpbMi+UZbAbReUJU1XFk8t5uLTKBYrBgur2dAex/jmApAG2Yu15WCY/WgJdaBkjyIl4bbco1iBGhnR4XLq00gmmDkIfgAqmtKNmdi8o82gPZxAgTpIYBb0OE5lr3pJzo67WNjt0gihDAyfy84m9CTq5yuSVkQX0EtG0SvV5NLFAoul4BO1t0j6gAV67IxE1NguJPj7VaO9nBl7tFiSymg3fXz5tVZIbrF6PSLxVmUTiFHlpQLB9vAOKMuG7PEZydnJgpOVvGZtjiyCjw52AZ8RtRsY0aqpIHhoCNmgApxjCwdirj+2iS0KXRq41rxJqfD+icUle4i+YbeuLnb9Ga9urARw+Ebw0P+ES/o2o/X+Jf6MyXvIUaHJHlEI6IyoXMLT+o7yu37dpCCeXslY2GDpOJC8H9QIbvl8P7h1hk/wvxXwmbN7zeVKsAPfiJcAMSkrUFmiRgHdB+IZHX5PtfFBf8m0r3DX43yh79W6TLRAAAAAElFTkSuQmCC');
position: absolute;
left: 0;
top: 0;
transform: translate(-120%,-10%);
width: 1em;
height: 1em;
(the div to which this psuedo element belongs has position: relative;
Edit:
P.S.: I don't want to change the content of the psuedo element. Is it still possible?
Edit:
I want the pseudo element to be 16px x 16px without cutting the image out
Use scale to reduce the overall width/height and obtain what you want
.box:before {
content: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAASCAYAAABFGc6jAAAAAXNSR0IArs4c6QAAAc1JREFUOBHtlE8oBHEUx9+bYVknFMrBRcmJk9pEuXLWXhQHJ/vHvyJOrJKLsGxbW3KghDMOTiiSE22UIncuFLLszPNm1/xm5mftn4uT32W+n/e+772Z329mEKRFgfFaoEQPELowujQrpbMi+UZbAbReUJU1XFk8t5uLTKBYrBgur2dAex/jmApAG2Yu15WCY/WgJdaBkjyIl4bbco1iBGhnR4XLq00gmmDkIfgAqmtKNmdi8o82gPZxAgTpIYBb0OE5lr3pJzo67WNjt0gihDAyfy84m9CTq5yuSVkQX0EtG0SvV5NLFAoul4BO1t0j6gAV67IxE1NguJPj7VaO9nBl7tFiSymg3fXz5tVZIbrF6PSLxVmUTiFHlpQLB9vAOKMuG7PEZydnJgpOVvGZtjiyCjw52AZ8RtRsY0aqpIHhoCNmgApxjCwdirj+2iS0KXRq41rxJqfD+icUle4i+YbeuLnb9Ga9urARw+Ebw0P+ES/o2o/X+Jf6MyXvIUaHJHlEI6IyoXMLT+o7yu37dpCCeXslY2GDpOJC8H9QIbvl8P7h1hk/wvxXwmbN7zeVKsAPfiJcAMSkrUFmiRgHdB+IZHX5PtfFBf8m0r3DX43yh79W6TLRAAAAAElFTkSuQmCC');
position: absolute;
transform: scale(0.7);
width: 1em;
height: 1em;
}
<div class="box">
</div>
Using background would be the ideal solution:
.box:before {
content:"";
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAASCAYAAABFGc6jAAAAAXNSR0IArs4c6QAAAc1JREFUOBHtlE8oBHEUx9+bYVknFMrBRcmJk9pEuXLWXhQHJ/vHvyJOrJKLsGxbW3KghDMOTiiSE22UIncuFLLszPNm1/xm5mftn4uT32W+n/e+772Z329mEKRFgfFaoEQPELowujQrpbMi+UZbAbReUJU1XFk8t5uLTKBYrBgur2dAex/jmApAG2Yu15WCY/WgJdaBkjyIl4bbco1iBGhnR4XLq00gmmDkIfgAqmtKNmdi8o82gPZxAgTpIYBb0OE5lr3pJzo67WNjt0gihDAyfy84m9CTq5yuSVkQX0EtG0SvV5NLFAoul4BO1t0j6gAV67IxE1NguJPj7VaO9nBl7tFiSymg3fXz5tVZIbrF6PSLxVmUTiFHlpQLB9vAOKMuG7PEZydnJgpOVvGZtjiyCjw52AZ8RtRsY0aqpIHhoCNmgApxjCwdirj+2iS0KXRq41rxJqfD+icUle4i+YbeuLnb9Ga9urARw+Ebw0P+ES/o2o/X+Jf6MyXvIUaHJHlEI6IyoXMLT+o7yu37dpCCeXslY2GDpOJC8H9QIbvl8P7h1hk/wvxXwmbN7zeVKsAPfiJcAMSkrUFmiRgHdB+IZHX5PtfFBf8m0r3DX43yh79W6TLRAAAAAElFTkSuQmCC') center/contain no-repeat;
position: absolute;
width: 1em;
height: 1em;
}
<div class="box">
</div>
If you use "overflow: hidden" on the :before element is won't overflow anymore and will cut off some of the image. Else it's better to use the image as a background image and set the width of the background image to 100%. play a little with the hieght and width of the element to make it in the right ratio
.box:before {
content: '';
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAASCAYAAABFGc6jAAAAAXNSR0IArs4c6QAAAc1JREFUOBHtlE8oBHEUx9+bYVknFMrBRcmJk9pEuXLWXhQHJ/vHvyJOrJKLsGxbW3KghDMOTiiSE22UIncuFLLszPNm1/xm5mftn4uT32W+n/e+772Z329mEKRFgfFaoEQPELowujQrpbMi+UZbAbReUJU1XFk8t5uLTKBYrBgur2dAex/jmApAG2Yu15WCY/WgJdaBkjyIl4bbco1iBGhnR4XLq00gmmDkIfgAqmtKNmdi8o82gPZxAgTpIYBb0OE5lr3pJzo67WNjt0gihDAyfy84m9CTq5yuSVkQX0EtG0SvV5NLFAoul4BO1t0j6gAV67IxE1NguJPj7VaO9nBl7tFiSymg3fXz5tVZIbrF6PSLxVmUTiFHlpQLB9vAOKMuG7PEZydnJgpOVvGZtjiyCjw52AZ8RtRsY0aqpIHhoCNmgApxjCwdirj+2iS0KXRq41rxJqfD+icUle4i+YbeuLnb9Ga9urARw+Ebw0P+ES/o2o/X+Jf6MyXvIUaHJHlEI6IyoXMLT+o7yu37dpCCeXslY2GDpOJC8H9QIbvl8P7h1hk/wvxXwmbN7zeVKsAPfiJcAMSkrUFmiRgHdB+IZHX5PtfFBf8m0r3DX43yh79W6TLRAAAAAElFTkSuQmCC');
background-size: 100%;
background-repeat: no-repeat;
position: absolute;
left: 0;
top:0;
width: 16px;
height: 16px;
}
It turns out it is not possible to contain the image inside content property of psuedo element since psuedo elements are anonymous replaced elements
from MDN:
In CSS, a replaced element is an element whose representation is outside the scope of CSS; they're external objects whose representation is independent of the CSS formatting model.
Put in simpler terms, they're elements whose contents are not affected by the current document's styles. The position of the replaced element can be affected using CSS, but not the contents of the replaced element itself.
Thus as the other answers suggest, using background CSS property will the solve the problem.
Removing the :before pseudo and using a background image at size 16px
blockquote {
margin:0;
max-width: 130px; /* demo only */
padding-left: 1.5em; /* space for quote icon */
background: 0 0.1em / 16px no-repeat url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAASCAYAAABFGc6jAAAAAXNSR0IArs4c6QAAAc1JREFUOBHtlE8oBHEUx9+bYVknFMrBRcmJk9pEuXLWXhQHJ/vHvyJOrJKLsGxbW3KghDMOTiiSE22UIncuFLLszPNm1/xm5mftn4uT32W+n/e+772Z329mEKRFgfFaoEQPELowujQrpbMi+UZbAbReUJU1XFk8t5uLTKBYrBgur2dAex/jmApAG2Yu15WCY/WgJdaBkjyIl4bbco1iBGhnR4XLq00gmmDkIfgAqmtKNmdi8o82gPZxAgTpIYBb0OE5lr3pJzo67WNjt0gihDAyfy84m9CTq5yuSVkQX0EtG0SvV5NLFAoul4BO1t0j6gAV67IxE1NguJPj7VaO9nBl7tFiSymg3fXz5tVZIbrF6PSLxVmUTiFHlpQLB9vAOKMuG7PEZydnJgpOVvGZtjiyCjw52AZ8RtRsY0aqpIHhoCNmgApxjCwdirj+2iS0KXRq41rxJqfD+icUle4i+YbeuLnb9Ga9urARw+Ebw0P+ES/o2o/X+Jf6MyXvIUaHJHlEI6IyoXMLT+o7yu37dpCCeXslY2GDpOJC8H9QIbvl8P7h1hk/wvxXwmbN7zeVKsAPfiJcAMSkrUFmiRgHdB+IZHX5PtfFBf8m0r3DX43yh79W6TLRAAAAAElFTkSuQmCC');
}
<blockquote>Charlie, from the lorem ipsum book has a nice dog called</blockquote>

Text in the DIV not showing

I need to use this shape and inside that shows a text. But, I don't know why the text is not showing.
HTML:
<div id="thebag">
<h3> Shihab Mridha </h3>
</div>
CSS:
#thebag{
position: relative;
overflow: hidden;
}
#thebag::before{
content: '';
position: absolute;
top: 0;
left: 0;
height: 50px;
width: 30%;
background: red;
}
#thebag::after {
content: '';
position: absolute;
top: 0;
left: 30%;
width: 0;
height: 0;
border-bottom: 50px solid red;
border-right: 70px solid transparent;
}
https://jsfiddle.net/kn87syvb/1/
You need to add position: relative (or position: inherit, since it's the same as the parent) to your #thebag h3 class. Currently, your CSS styles are only affecting the parent of the h3—in order for the h3 to show with the text, you need to define CSS styling for it.
https://jsfiddle.net/kn87syvb/2/
By setting a position:absolute to the #thebag::before you "broke" the flow and your text is behind your div. You have to precise, than the h3 tag will be relative depending it's container.
So you have to add this :
#thebag h3 {
position:relative
}
To precise all h3 on your #thebag section will be affected. Be careful, if you change your kind of selector, It won t work anymore.
May be it will be better to use a custom class, like this https://jsfiddle.net/kn87syvb/5/
You need to use postion:relative property:
#thebag h3{
postion:relative;
}
Small explanation:
position: relative will layout an element relative to itself. In other words, the elements is laid out in normal flow, then it is removed from normal flow and offset by whatever values you have specified (top, right, bottom, left). It's important to note that because it's removed from flow, other elements around it will not shift with it (use negative margins instead if you want this behaviour).
However, you're most likely interested in position: absolute which will position an element relative to a container. By default, the container is the browser window, but if a parent element either has position: relative or position: absolute set on it, then it will act as the parent for positioning coordinates for its children.
please check this snippet:
https://jsfiddle.net/kn87syvb/4/
You can also re-structure your HTML and CSS as follows:
HTML
<span class="start">Shihab Mridha</span>
<span class="end"></span>
CSS
.end {
height:0;
width:0;
float: left;
display: block;
border:10px solid #0f92ba;
border-top-color:transparent;
border-right-color:transparent;
border-bottom-color:#0f92ba;
border-left-color:#0f92ba;
}
.start{
height: 20px;
width: 60px;
float: left;
background: #0f92ba;
display: block;
color:#FFFFFF;
}
Reference Link : https://solutionstationbd.wordpress.com/2011/12/21/trapezoids-shape-with-css/

Move Layer between Parent and Child (z-index)

I have 3 DIVS. A Parent, a Child and a Layer (sibling of Parent). The Layer should appear between parent and child.
<div class="parent">
<div class="child"></div>
</div>
<div class="layer"></div>
CSS
div {
position: absolute;
width: 100px;
height: 100px;
}
.parent {
z-index: 1;
top: 0;
left: 0;
background-color: red;
}
.child {
z-index: 3;
top: 60px;
left: 60px;
background-color: blue;
}
.layer {
z-index: 2;
top: 30px;
left: 30px;
background-color: green;
}
Here's a JS Fiddle:
http://jsfiddle.net/PHwua/
strangely, i can't get the layer to appear between parent and child. On a live site, this works for some reason in all browsers (IE8-11, FF, Chrome) except Safari.
Now i can't even get the JSFiddle to work.
Your issue probably has to do with the stack(ing) order of HTML elements.
Basically, z-index affects elements inside the same stacking context. The parent and layer boxes are in the same context; so their z-indexes are evaluated first. Then the child box's z-index is evaluated against its stacking context (which nothing else exists in it since its a sub-context of parent).
If you take parent out of the stacking order (by making its position static, for example, or getting rid of its z-index), then child and layer will be in the same stacking context.
Forked JSFiddle here.

Invisible div over div does not work in IE8

I'm trying to create an invisible div, over the facebook comments plugin in order to disable the plugin's functionality in an Editor View. This invisible div works in all browsers except IE8. How can I fix this?
HTML:
<div id="container">
<div id="coveriframe"></div>
<div data-bind-component="fbml: fbml">(RENDER JS COMMENTS VIA KO)</div>
</div>
Try in IE8:
http://jsfiddle.net/pkbz4/19/
The above code works in ALL other Major browsers. WTF Microsoft?
Stylesheet:
#container {
width: 100%;
height: 100%;
position: relative;
}
#navi,
#coveriframe {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
#coveriframe {
z-index: 10;
}
I've done this several times in IE8. The solution that works for me is to assign a background color to the div and then set opacity to 0. IE8 then recognizes the div as "existing" above the rest of the content. I also find setting position: absolute and all four directions to 0 is more reliable than 100% width and height. Like this:
#coveriframe {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 3007;
background: #fff;
filter: alpha(opacity=0);
opacity: 0;
}
Here's my update to your jsfiddle: http://jsfiddle.net/pkbz4/21/
CSS Specification says:
The percentage is calculated with respect to the height of the
generated box's containing block. If the height of the containing
block is not specified explicitly (i.e., it depends on content
height), and this element is not absolutely positioned, the value
computes to 'auto'.
Basically, In older versions of IE (including IE8) percentage heights are based on the height of the parent element. If the parent element doesn't have an explicit height, the percentage is ignored and set to Auto (in this case, 0px).
So, to fix this, you'll either want to explicitly set the height/width of #coveriframe or its parent. One thing you could try is setting the height of html and body to 100% (I'm assuming those are the parent elements).
html, body { height:100%; }
#container {
width: 100%;
height: 100%;
position: relative;
}
#navi,
#coveriframe {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
#coveriframe {
z-index: 10;
}
why did you want to do in javascript and it works well in all browsers, I'll let my example I hope you work:
-----------------DIV-----------------
<div id="div1" style="display: block;">
<div class="mainbody">
<br />
</div></div>
-----------------JavaScript----------------
function showHideDiv(divX) {
if (divX == "1") {
document.getElementById("div1").style.visibility = "visible";
document.getElementById("div2").style.visibility = "hidden";
}
-----------------button HTML----------------
<li>click_Aqui</li>
The problem is that internet explorer up to ie9 doesn't recognize the mouse hover when hovered over a transparent background. Zach Shipley answer offers a good solutions.
But in case you want to add a border or an element to the transparent div or text the easiest way of doing this is by adding a 1px transparent png as background.
#coveriframe {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 3007;
background-image: url("pixel-transparent.png");
}
Make sure that you are putting fixed height & width to that DIV.
As Shaquin Trifonoff mentioned above sometimes 100% or any length in % may not work onIE8. Always I am trying to avoid % in such situation.
Code snippet :-
html,body{ //This makes your page expandable as per screen resolution
height:100%;
}
#your-hide-div{
height:100px;
width: 100px;
display:block;
}

child div not expanding to parent div

So I have three div's
One parent and two child.
The parent is as follows:
#parent {
overflow:auto;
margin: 0 auto;
margin-top:37px;
min-height: 100%;
width:875px;
}
the two child divs are as follows
#child1 {
overflow:auto;
min-height:150px;
border-bottom:1px solid #bbb;
background-color:#eee;
opacity:0.4;
}
#child2 {
height:100%;
background-color:white;
}
The parent div extends 100% as I can see the borders of it till the end of the page but the child2 is not extending down to the end of the page like the parent div.
height doesn't behave the way you seem to be anticipating. When you specify height: 100% that percentage is calculated by looking up the DOM for the first parent of said element with a height specified that has absolute or relative positioning.
You can cheat when it comes to the body tag, so if you had something like this:
<body>
<div style="height: 100%">
</div>
</body>
Some browsers/versions will behave the way you expect by taking up the total height of the page. But it won't work when you go any deeper than that.
Here is the approach I use to strech a div to the bottom of the page, it involves absolute positioning (nice thing about this one is that it is pretty cross-browser compliant and doesn't require javascript to pull it off):
<div id="parent">
<div id="childNorm"></div>
<div id="childStrech"></div>
</div>
#parent
{
position: absolute;
width: 1000px;
bottom: 0;
top: 0;
margin: auto;
background-color: black;
}
#childNorm
{
position: absolute;
width: 1000px;
top: 0;
height: 50px;
background-color: blue;
color: white;
}
#childStrech
{
position: absolute;
width: 1000px;
top: 50px;
bottom: 0;
background-color: red;
color: white;
}
Here is a Jsfiddle for demo: http://jsfiddle.net/t7ZpX/
The trick:
When you specify absolute positioning and then put in bottom: 0; that causes the element to stretch to the bottom of the page; You just have to worry about positioning the elements as a trade off.
Yes, this is one of the annoying things in css. min-height is not considered a "height" for purposes of calculating height. See http://jsfiddle.net/3raLu/3/. You need to have height: 100% on the parent div to make the child full height. Or, if you can have it be absolutely positioned, then this works: http://jsfiddle.net/3raLu/6/.

Resources