Is it possible to achieve this with mix-blend-mode? - html

I'm trying to achieve something with mix-blend-mode and I'm wondering if it's possible. I want to use mix-blend-mode to create a "multiply" effect, while keeping the text within it a solid white. I have seen similar issues discussed here, but slightly different than my situation, I believe...
My (simplified) HTML:
<div class="box">
<div class="content">
<div class="container">
<h1 class="header">HEADLINE</h1>
<div class="description"><p>Subhead</p></div>
</div>
</div> <!-- .content -->
</div>
...and my CSS:
.box {
display: flex;
align-items: flex-end;
height: 300px;
width: 700px;
background-image: url(https://heroshockey.com/wp2021/wp-content/uploads/2021/07/program-billboards-future-stars.jpg);
background-size: cover;
background-repeat: no-repeat;
}
.content {
float: left;
width: 100%;
}
.container {
background-color: red;
mix-blend-mode: multiply;
}
h1, p {
color: white;
margin: 0;
padding: 10px;
}
Here's a fiddle of the result:
https://jsfiddle.net/cosmocanuck/7zhwgo0s/55/
But I need the text to remain white, not "cut out".
I'm trying to follow Rashad's response here:
Remove mix-blend-mode from child element
But my situation, while very close, is somewhat different (including using flexbox to bottom-align the element containing the text), and so far I've failed to crack this one despite many attempts.
Can anyone point me in the right direction? Thanks!

Make sure the blended background and the text are in separate stacking contexts, and that the text is rendered over the background, not under it.
The reason your current code doesn’t work is that the text element is a child of the container element that sets the mix-blend-mode. mix-blend-mode will blend all of the content of the container, including the text — there’s no escaping that.
You need two things to make this work:
Make sure that the text is not a child of the element that sets the background and the blend mode.
Make sure the text is rendered over, and thus not affected by, the element that sets the background and the blend mode.
The challenge is that the size of the background must be dependent on the size of the content. One way to do this is with CSS Grid Layout:
define one auto-sized grid area
place both the background and the text into that one area (so that they overlap)
let the text dictate the size of the area
have the background stretch to the size of the area, which is dictated by the size of the text
Then, set isolation: isolate on the text element to ensure it gets rendered above, and not under the background element.
.container {
display: grid;
grid-template-areas: 'item';
place-content: end stretch;
height: 300px;
width: 700px;
background-image: url(https://heroshockey.com/wp2021/wp-content/uploads/2021/07/program-billboards-future-stars.jpg);
background-size: cover;
background-repeat: no-repeat;
}
.container::before {
content: '';
grid-area: item;
background-color: red;
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>

Related

How to achieve this sticking out image layout without using negative margins?

This is the layout image:
As you can see in the image, the images of the phones are sticking out of the blue container.
I have tried several things, such as:
I tried to use a grid with 5 rows where a <div> tag expanded all the rows and was set to have its background as the phone images. Then I set the blue background box to use only the rows form 2-4.
This somehow did the trick, but when the browser window was resized the image started to shrink and be positioned in a funky way.
As a newcomer to CSS I want to avoid negative margins because I have read they are "evil".
Is there any way to accomplish this in a clean/non-hacky way?
You can use the transform property to move the images where they need to be.
You'll need to build your layout as usual, but without the images being raised/lowered outside their default position.
Once you've done that, you can use transform: translateY(-100px) to raise or lower the images into their target position.
A quick example of this can be shown using <div> tags:
/* Setup some basic layouts to mimic the layout required */
.container {
padding-top: 100px;
padding-bottom: 100px;
}
.banner {
height: 200px;
background: blue;
display: flex;
justify-content: center;
align-items: center;
}
.image-1 {
height: 200px;
width: 200px;
background: red;
transform: translateY(-50px); /* move the image up */
}
.image-2 {
height: 200px;
width: 200px;
background: green;
transform: translateY(50px); /* move the image down */
}
.example-filler {
}
<div class="container">
<div class="banner">
<div class="image-1"></div>
<div class="image-2"></div>
<div class="example-filler">Lorem ipsum</div>
</div>
</div>
If you don't wan't to use negative margins (which are fine in this situation). You can try to give these styles to your image.
img {
position: relative;
top: -100px;
}
You can learn more about the "position" property here.
It is very important for beginners to understand how it works.

How to change the div overflowing behaviour using flex?

I have two div elements which I want to center within an 'li' element. I found out that this could be done by using a flex layout. My parent div has the following properties:
display: -webkit-flex;
justify-content: center;
align-items: center;
This works and the two child divs are centering within the 'li'. Those are an image and a text element. But the additional behaviour this has, is not what I want. When the screen is too small for one line text, it is overriding the image. It looks like the following:
The more I shrink the page, the more the image dissappears. Does anybody know how this comes and how I can fix it?
EDIT Currently I am finding out how to add a working code snippet. For now, I have an image with the content structure, maybe this helps a bit.
I fill the image using the following css code:
.img_info_icon_png {
background: url("adapter-images.png") no-repeat -432px -0px;
width: 24px;
height: 24px;
}
Although the width is set to '24px', it is changing within the browser.
EDIT The following url is pointing to an example with the same behaviour: https://jsfiddle.net/Lkpxhux0/
As the flex-shrink defaults to 1, it allows for the items to shrink when not fit its parent.
Add flex-shrink: 0 to the .img_info_icon_png rule.
.outer {
display: flex;
justify-content: center;
align-items: center;
}
.outer .image {
background: url(http://placehold.it/50/f00) no-repeat;
width: 24px;
height: 24px;
flex-shrink: 0;
}
<div class="outer">
<div class="image"></div>
<div class="text">
This is some text that should not overlap the left aligned image
</div>
</div>

Hide DIV background-image without rest of content

so my use case is that I have a div with a big background image and some other divs with text inside. In my css file I have a media query for max-width, so that below that width the image should disappear.
I have tried both visibility:hidden and background-image:none, but in both cases the text also disappears.
Is there a way to not make the other divs disappear? Or an alternative way to construct this structure to accomplish the goal stated above?
HTML:
<div id="teaser">
<span id="teaser-text"> Text </span>
<div id="attributes"> Some Text</div>
</div>
CSS:
#teaser {
width: 100%;
height: 0;
padding-top: 66.44%;
background-image: url('/static/main/freude2_bright1.jpg');
background-size: contain;
position: relative;
color: white;
margin-bottom: 20px;
}
Thanks a lot! :)
Is #teaser on a white background? If so, you're text may not be disappearing, but could be white on white after you've removed the image.
Try:
#media all and (max-width:480px) {
#teaser {
background-image: none;
color: #000;
}
}
If I understand correctly you want to remove the background image (or maybe color?) of a div but not effect the other content within it?
.main-div {
background-color: none;
background-image: none;
}

when overlapping an img-tag it renders background / border behind and text in front of img

For a simple landing page I wanted to let some text box overlap an header image. To make it simple, I just have a structure like:
<header>
<img src="path/to/img.png" />
<h1>Awesome headline</h1>
</header>
All elements are set to display:block and the h1 is dragged inside the image with a negative margin. I also gave the headline some padding and background:white.
Now the problem: The headline text is shown on top of the image but the background colour is behind it! You can see an example here: https://jsfiddle.net/cv12evLn/
My guess is, that a browser renders all sibling blocks in layers, starting with all backgrounds and borders, then rendering images (img-tags) and finally text on top of everything else.
Is that right? And why the actual… I mean, that seems crazy unexpected to me.
To solve the issue, I've put the headline in a wrapper and set this to position:absolute. See here for a live example: https://jsfiddle.net/f5sd1u6o/
Use position:relative rather than negative margin. Then the z-index works automatically.
#container {
width: 500px;
height: 300px;
margin: auto;
}
#container img {
display: block;
width: 100%;
}
#container h1 {
display: block;
width: 50%;
height: 1em;
margin: auto;
padding: .5em 1em 1em;
font-size: 3rem;
background: yellow;
text-align: center;
border: 1px solid red;
position: relative;
top: -4.6rem;
}
<div id="container">
<img src="//placekitten.com/500/300">
<h1>
headline
</h1>
</div>
To get the Z-index to work, you need to apply position:relative anyway but you can still use negative margin if that is a design requirement.
JSfiddle demo (with negative margin)
Basically, backgrounds are rendered first before anything else (as I understand it) so they always come at the bottom of the stacking order. You just need to create a new stacking context and changing the position property does that.
As it happens so does changing the opacity of the element so a quick fix is to set opacity:.9999;
JSfiddle Demo (opacity 'hack')

How to extend HTML container objects around relative child elements

I have the following:
HTML:
<div class="banner-success">
<span class="banner-text">
You were successful! Yay! Some long reason what your success
implies goes here.
</span>
</div>
CSS:
/*Add future banners to this style, this is generic banner styling*/
.banner-success
{
background-position: 5px 5px;
background-repeat: no-repeat;
min-height: 42px;
padding-left: 47px;
margin-bottom: 10px;
}
/*Create a new entry in this section for each banner, with appropriate image and
colors*/
/*----------------------------------------------------------------------*/
.banner-success
{
color: #004400;
background-color: #DDF2E4;
background-image: url("../Images/Success.gif");
}
/*----------------------------------------------------------------------*/
.banner-text
{
position: relative;
top: 5px;
}
This allows for a standard banner, each with an image and arbitrary lines of text, assuming a consistent image size. My issue is that the div is being sized as if the text within isn't being pushed down, and so the bottom line of the text reaches outside of the div.
Is there a way to tell a div, or any container element, 'be as big as your constituent elements are, AFTER they've been relatively positioned to you'?
Apply overflow:hidden to the .banner-success.
I made a couple of tweaks to even out the padding around your text (and subbed a background
image so you could see it working w/ an image in place):
http://jsfiddle.net/qTsgL/
Cheers!