Background blend mode on PNG images - css

Long story short, I want my (any) image to change the color on hover, but I can't make it work well on PNG images. The problem is with transparency. I don't want to apply my color on transparent space. My CSS looks like this:
background-blend-mode: color-burn;
background-color: #edeb52;
Here is the full jsFiddle example. All I want is to get rid of that color around the icon, which should be transparent.

6 months late to the party but you could use the mask-image CSS property. Its experimental but fairly well supported:
.maskedimage {
display: inline-block;
width: 200px;
height: 200px;
background-image: url("https://gameartpartners.com/wp-content/uploads/edd/2015/06/goblin_featured.png");
background-size: cover;
-webkit-mask-image: url("https://gameartpartners.com/wp-content/uploads/edd/2015/06/goblin_featured.png");
-webkit-mask-mode: alpha;
-webkit-mask-size: cover;
mask-image: url("https://gameartpartners.com/wp-content/uploads/edd/2015/06/goblin_featured.png");
mask-mode: alpha;
mask-size: cover;
}
.maskedimage.blue {
background-blend-mode: luminosity;
background-color: blue;
}
.maskedimage.red {
background-blend-mode: luminosity;
background-color: red;
}
.maskedimage:hover {
background-blend-mode: multiply;
background-color: red;
}
<div class="maskedimage original"></div>
<div class="maskedimage blue"></div>
<div class="maskedimage red"></div>
Alternatively you can get a similar effect using css filters:
.filteredimage {
display: inline-block;
width: 200px;
height: 200px;
background-image: url("https://gameartpartners.com/wp-content/uploads/edd/2015/06/goblin_featured.png");
background-size: cover;
}
.filteredimage.blue {
filter: sepia(1) hue-rotate(170deg) brightness(45%) saturate(1000%);
}
.filteredimage.red {
filter: sepia(1) hue-rotate(313deg) brightness(45%) saturate(1000%);
}
.filteredimage:hover {
filter: sepia(1) hue-rotate(313deg) brightness(25%) saturate(1000%);
}
<div class="filteredimage original"></div>
<div class="filteredimage blue"></div>
<div class="filteredimage red"></div>
Your mileage may vary.

This can be done with css, but unfortunately browser support is very bad (may be webkit only).
https://jsfiddle.net/devefrontend/fowzemd2/2/
.image .img {-webkit-mask-box-image:'YOURIMAGEURL';}
and this may be the same question as you:
Is there any way to colorize a white PNG image with CSS only?

Its is a Example
you can more learn it
https://www.w3schools.com/howto/howto_css_image_overlay.asp
.container {
position: relative;
width: 50%;
}
.image {
opacity: 1;
display: block;
width: 100%;
height: auto;
transition: .5s ease;
backface-visibility: hidden;
}
.middle {
transition: .5s ease;
opacity: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%)
}
.container:hover .image {
opacity: 0.3;
}
.container:hover .middle {
opacity: 1;
}
.text {
color: white;
font-size: 16px;
width:400px; height:350px;
}
<div class="container">
<img src="http://www.kaptest.co.uk/sites/kaptest.co.uk/files/pictures/icon-lightbulb-grey.png" alt="Avatar" class="image" style="width:100%">
<div class="middle" ">
<div class="text">example</div>
</div>
</div>

Try like this. See if it is helpful. I have used filter property here.
.image {
display: inline-block;
}
.image .img {
width: 375px;
height: 360px;
background-image: url('http://www.kaptest.co.uk/sites/kaptest.co.uk/files/pictures/icon-lightbulb-grey.png');
background-size: cover;
-webkit-filter: opacity(.5) drop-shadow(0 0 0 yellow);
filter: opacity(.5) drop-shadow(0 0 0 yellow);
}
<div class="image">
<div class="img"></div>
</div>

Does it have to be PNG? Preferably you could use an inline svg. This way you can not only apply a fill color of your choice via css but you also get all the benefits of vector based graphics: Crispy on any size and smaller file (be sure to optimize with svgo)

Related

Image Hover Border Radius Safari Issue

I am creating a card that contains an image and text. When the card is hovered, the image scales to 1.5. When you hover, the image will scale but then it will have this flicker where the corners will be sharp and then round out again.
.box {
width: 100%;
max-width: 19.375em;
background-color: green;
border-radius: 1em;
overflow: hidden;
}
.box:hover .box__image img {
transform: scale(1.5);
}
.box__image {
overflow: hidden;
}
.box__image img {
display: block;
height: 12.5em;
width: 100%;
object-fit: cover;
transform: scale(1);
transition: transform 500ms ease;
}
<div class="box">
<div class="box__image"><img src="https://via.placeholder.com/576x200"/></div>
<div class="box__desc">
<p>hello</p>
</div>
</div>
Works perfectly fine on Chrome and Firefox

Can i apply filter: inver(1) with transform-origin in CSS?

I am trying to animate image by filter: invert(1) going from right side to the left side.
filter: invert(1);
transform-origin: right;
Seems to not be working. Is there any easy way to do it?
That's because you aren't changing the image with a transform, you're changing it with a filter. The transform-origin property will not affect a filter in any way, only transforms. If I were you I would try something like my example below. Hover the image to see the effect.
.image-container {
position: relative;
overflow: hidden;
}
.image-container:before {
content: '';
background: white;
position: absolute;
height: 100%;
width: 100%;
mix-blend-mode: difference;
transform: translateX(100%);
transition: 1s ease;
}
.image-container:hover:before {
transform: translateX(0);
}
<div class="image-container">
<img src="https://picsum.photos/id/10/400/300" alt="" />
</div>

how to draw a path of moving object in css animation without svg?

I have a moving box (a div changed into a tiny box) on a html page. The box is moving in a curve path that I am describing in animation frames of css.
Now I have to draw a line following this box move, just to mimic a pencil move, so it looks like the line has been drawn by the moving box. As the box moves, a line should start appearing behind it, e.g. just like we draw a line by pen or pencil.
Not sure, if it is possible only in css but if you have any suggestion, please feel free to advice me. Thank you.
here is code
test.html
<html>
<head>
<link rel="stylesheet" href="box.css">
</head>
<body style="background-color: white;">
<div id="box">
<div id="line"></div>
</div>
</body>
<script src = "logo.js"></script>
</html>
css file: box.css
body{
width:100%;
height:100vh;
background-color: black;
}
#box {
margin-top:300px;
margin-left:30px;
top:0;
left:0;
width:30px;
height:40px;
background-color: red;
animation:move-line;
animation-duration: 5s;
animation-iteration-count: infinite;
}
#keyframes move-line {
0%{
transform:translateX(0px)translateY(0px) ;
}
50%{
transform:translateX(280px)translateY(0px) ;
}
60%{
transform:translateX(300px)translateY(-100px) ;
}
70%{
transform:translateX(300px)translateY(100px) ;
}
80%{
transform:translateX(320px)translateY(0px) ;
}
90%{
transform:translateX(330)translateY(0px) ;
}
100%{
transform:translateX(400px) ;
}
}
javascript file: logo.js
currently it is empty but if you have a solution feel free to use it with javascript too however css is preferred.
Here is a snippet to demonstrate the idea.
An after pseudo element attached to the red box has a solid white background.
As the box moves, the pseudo element 'goes before it' revealing what is already underneath.
In this demo just the first part of the line has been drawn. You'll need to add the other lines with additional linear-gradients, 3 being at angles and positioned suitably and the last one horizontal again.
Alternatively you could put an image there instead of using linear gradients but I note your question says no SVG so I assume that maybe it isn't allowed a jpg either.
<style>
body {
width: 100%;
height: 100vh;
background-color: black;
}
.container {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background-image: linear-gradient(transparent 0 calc(300px + 20px), black calc(300px + 20px) calc(301px + 20px), transparent calc(301px + 20px) 100%);
background-size: 280px 100vh;
background-repeat: no-repeat;
background-position: 0 0;
}
#box {
margin-left: 30px;
top: 300px;
left: 0;
width: 30px;
height: 40px;
background-color: red;
animation: move-line;
animation-duration: 5s;
animation-iteration-count: infinite;
position: relative;
}
#box::after {
content: '';
position: absolute;
top: -300px;
left: 100%;
height: 100vh;
width: 100vw;
background-color: white;
display: inline-block;
}
#keyframes move-line {
0% {
transform: translateX(0px)translateY(0px);
}
50% {
transform: translateX(280px)translateY(0px);
}
60% {
transform: translateX(300px)translateY(-100px);
}
70% {
transform: translateX(300px)translateY(100px);
}
80% {
transform: translateX(320px)translateY(0px);
}
90% {
transform: translateX(330)translateY(0px);
}
100% {
transform: translateX(400px);
}
}
</style>
<html>
<head>
<link rel="stylesheet" href="box.css">
</head>
<body style="background-color: white;">
<div class="container">
<div id="box">
</div>
</div>
</body>
<script src="logo.js"></script>
</html>

Why does rotated blurred element get cropped off?

This is the example: https://jsfiddle.net/0w4bcy93/
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
transform: rotateX(40deg) rotateY(0deg) rotateZ(0deg);
}
.circle--1 {
filter: blur(10px) opacity(1);
}
<div class="circle circle--1"></div>
<div class="circle circle--2"></div>
Both has the same styling except .circle--1 has filter blur. Is this a browser issue?
edit: You can also try increasing the rotateX and the cropped area will be bigger
edit2: I logged a bug in Chromium https://bugs.chromium.org/p/chromium/issues/detail?id=1108298
In case of it's a chrome bug itself. There's a cheat way to work around. By using a parent
filter layer to blur.
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
transform: rotateX(75deg) rotateY(0deg) rotateZ(0deg);
}
.blur-filter {
filter: blur(10px);
width: 100px;
height: 100px;
}
.circle--1 {
filter: opacity(1);
}
<div class="blur-filter">
<div class="circle circle--1"></div>
</div>
<div class="circle circle--2"></div>

Fullscreen infinite scrolling background

I'm trying to implement a full-screen infinite scrolling background effect, which must extend on the entire height and width of the viewport.
Here's the demo.
The solution I've tried was to take a wrapper element that has 100vh and 100vw of the viewport, then place 2 divs inside it, 100% of its height, that have the same background-image and background-size: cover property. The size of the image I've used is: 1,920px × 808px.
Then I've applied the following animation on the wrapper element:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-100%);
}
}
But the problem is that on some viewport sizes, the images are not repeating correctly (because of background-size: cover property):
.
Here's the full code I've tried:
<div class="animated-scene">
<div class="animated-scene__frame animated-scene__frame-1"></div>
<div class="animated-scene__frame animated-scene__frame-2"></div>
</div>
And the css:
.animated-scene {
width: 100vw;
height: 100vh;
position: fixed;
min-height: 400px;
animation: infiniteScrollBg 50s linear infinite;
}
.animated-scene__frame {
width: 100%;
height: 100%;
background-size: cover;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg');
}
Do you have any idea on how could I implement this effect?
Thanks for your help.
For scrolling background, I used background-position instead of using additional element and animate it using transform css properties.
Why you might asked?
Pattern will be seamlessly stitched by the browsers
cleaner HTML code. We just need one element to do this.
The only const doing this method is you need to know the dimension of image you are using.
Example :
/*
specify the scroll x (or y) with the width (or height) of the images
In this case, the image dimension is :
width: 1920px;
height: 808px;
*/
#keyframes bgScroll {
0% {
background-position : 0px 0px
}
100% {
background-position : 0px -808px
}
}
.scrollingBG {
display:block;
width:100vw;
height:100vh;
background-image:url("https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg.jpg");
animation: bgScroll 20s linear infinite;
}
<div class='scrollingBG'></div>
I have used an image element just to use the auto height of it.
Then I use a backgroiund on a pseudo that gives the ability to repeat itself as many times as needed
I have set 2 different containers with different aspect ratios to more easily check the result on different screens
.container {
border: solid 1px black;
overflow: hidden;
position: absolute;
}
#ctn1 {
width: 300px;
height: 150px;
}
#ctn2 {
width: 200px;
height: 350px;
left: 320px;
}
.inner {
width: 100%;
position: relative;
animation: scroll 5s infinite linear;
}
.inner:after {
content: "";
height: 500%;
width: 100%;
position: absolute;
background-image: url(https://i.stack.imgur.com/FlK9o.jpg);
background-size: 100% 20%;
}
.img {
width: 100%;
}
#keyframes scroll {
from {transform: translateY(-100%);}
to {transform: translateY(-200%);}
}
<div class="container" id="ctn1">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
<div class="container" id="ctn2">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
A better solution with media query used to change the way the image is used.
Notice that background-size: cover is needed when both the aspect ratio of the image and the window is unknown. Since you know the aspect ratio of your image, you can control the display with a media query based on it.
Now, when it's needed, the image will adapt not to the width of the container, but to the height of it
#media screen and (max-aspect-ratio: 4/3) {
.inner {
height: 100%;
width: auto !important;
}
.img {
height: 100%;
width: auto !important;
}
}
.container {
border: solid 1px black;
display: inline-block;
overflow: hidden;
}
#ctn1 {
width: 300px;
height: 150px;
}
#ctn2 {
width: 200px;
height: 350px;
}
.inner {
width: 100%;
position: relative;
animation: scroll 5s infinite linear;
display: inline-block;
}
.inner:after {
content: "";
height: 500%;
width: 100%;
left: 0px;
position: absolute;
background-image: url(https://i.stack.imgur.com/FlK9o.jpg);
background-size: 100% 20%;
}
.img {
width: 100%;
}
#keyframes scroll {
from {transform: translateY(-100%);}
to {transform: translateY(-200%);}
}
<div class="container" id="ctn1">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
<div class="container" id="ctn2">
<div class="inner">
<img class="img" src="https://i.stack.imgur.com/FlK9o.jpg">
</div>
</div>
The issue is with aspect ratio. You're setting the aspect ratio to the view window, and not the image size. So your image ends up getting cut off at the view window aspect.
I worked around in your codepen by changing .animated-scene__frame to this:
.animated-scene__frame {
width: 100%;
height:200vh; //easy way - increase height in animated div to prevent image cutoff. Ideally should be done through javascript using like a 3x multiple of the height of the image. Then just rely on background-repeat during the animation :)
background-size:contain;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg-slide1.jpg');
}
I would recommend to just extend the picture 3 times, with:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-66.66%);
}
}
Use some image editor and create a large image with the same pattern, take a look of this site that I made site, there you will find some infinite background pattern
You must use background-position property.
Here's fixed example http://codepen.io/azamat7g/pen/BRwRVV
Full code:
#keyframes infiniteScrollBg {
0% {
transform: translateY(0%);
}
100%{
transform: translateY(-100%);
}
}
.animated-scene {
width: 100vw;
height: 100vh;
position: fixed;
min-height: 400px;
animation: infiniteScrollBg 50s linear infinite;
}
.animated-scene__frame {
width: 100%;
height: 100%;
background-size: cover;
background-position: bottom left;
background-color: #4277a3;
background-image: url('https://andreivictor.ro/codepen/fullscreen-infinite-scroll-bg/fullscreen-bg-slide1.jpg');
}
.bottom{
background-position: top left;
}
<div class="animated-scene">
<div class="animated-scene__frame animated-scene__frame-1"></div>
<div class="animated-scene__frame animated-scene__frame-2 bottom"></div>
</div>

Resources