Blending 2 elements background colors using CSS - javascript

I need to blend the background colors of 2 elements using CSS
I have been fiddling around with the background-blend-mode:multiply but that works only when I have the 2 colors in the same element.
I need to achieve something like this -
I have been searching a lot but haven't been able to figure it out.
Most helpful resource I found was New blending features in CSS which shows how to do it using Canvas.
Is it possible to do the same thing using CSS?
EDIT
The circles above were just an example to show what I needed. As I mentioned, I was looking for blending colors for 2 different elements. I have created a fiddle for my actual shapes that I need to blend.
http://jsfiddle.net/fmgfsr4o/2/

You can combine CSS multiple background with radial-gradients to achieve this effect:
CSS
div {
/* adjust the width of the container to adjust circle's
overlap size and shape */
width: 80px;
height: 50px;
/* for debug purpose only */
border: solid blue 1px;
background:
/* draw the red circle */
radial-gradient(red 0%, red 70%, transparent 70%, transparent 100%) 0 0,
/* draw the green circle */
radial-gradient(green 0%, green 70%, transparent 70%, transparent 100%) 0 0;
/* the red on the left, the green on the right */
background-position: top left, top right;
/* you can make then bigger or smaller */
/* but you have to change width size above too */
background-size: 50px 50px;
/* You want both circles to appears once only */
background-repeat: no-repeat;
/* you can try with other values too */
/* https://developer.mozilla.org/en-US/docs/Web/CSS/background-blend-mode */
background-blend-mode: multiply;
}
HTML
<div></div>
I have done a JSFiddle for you to try: http://jsfiddle.net/pomeh/07nLpwwj/
This is the result I get using Firefox 31:
Even if the browser support seems "correct" (see here http://caniuse.com/#feat=css-backgroundblendmode), please note that the background-blend-mode property has the Candidate Recommendation status for now, so be careful when using it (thanks to #Paulie_D for pointing that out).

Try this pure CSS3, although you will need to figure out how to position the circles.
html {
height: 100%;
background:
repeating-radial-gradient(
circle,
transparent,
transparent 3.5em,
tomato 1em,
tomato 4.5em
),
repeating-radial-gradient(
circle,
transparent,
transparent 3.5em,
dodgerblue 3.5em,
dodgerblue 4.5em
);
background-blend-mode: multiply;
background-size: 10em 10em;
background-position:
0 0,
5em 5em,
10em 5em;
}
JSFiddle

Related

Specific CSS rules for overlapping shapes/divs

I'm trying to recreate a screenshot app to better understand HTML, CSS and Electron and so far I've made a keybind that toggles the overlay of a 0.25 opacity transparent box that fills the screen. And a transparent red outlined box that can be dragged to select an area for the screenshot
As the red box is transparent and is on top of the 0.25 opacity box that fills the screen, the red box has the same opacity as the rest of the screen. I want the area inside the red box to "clear the opacity" so that it is viewed as 0.0 opacity, basically a "bright area" in the red box that looks the same as the screen would without the opacity. Like this
I tried setting the rgba to (0,0,0,0) but that didn't change anything as I expected and I cannot find any documentation for CSS about overlapping elements.
Do you have any idea on how I can implement this?
The first thing that comes to mind for me is a huge box shadow on a transparent element. I don't know how performant this is, but it works.
.screenshot {
position: fixed;
top: 50px;
left: 50px;
width: 300px;
height: 100px;
border: 1px solid red;
/* large box shadow */
box-shadow: 0 0 0 max(100vw, 100vh) #0005;
}
<div class='screenshot'></div>

How to smoothly animate position & size of an rounded rectangle?

I am implementing a "pane" view component. Similar to IntelliJ or VSCode, where each pane can be rearranged into different rows and columns. The drag-and-drop rearrange action requires a preview animation: a box that animates around the screen, showing where the new pane would be inserted if the action was finished.
Basically, I need an absolutely-positioned rounded rectangle that can smoothly animate around the screen. Ideally this would be GPU-accelerated.
My attempts:
Attempt no. 1
I simply created a <div> element and animated the height, width, top and left values. This works, and allows all other CSS effects to work on the rectangle, like borders and rounded edges. However, it's not very fast. Animating the position and size directly is recommended against because it forces a reflow on each frame.
Attempt no. 2
Instead, I created 1px by 1px colored <div>, and set its size and position by editing it's transform CSS property. This is super smooth because it uses the GPU-accelerated transform property. However, it comes with a downside: I cannot style the <div>. I cannot use border or border-radius, otherwise they become distorted by the scale transformation.
Ideas
Since a rectangle is a simple shape, could we generate an svg and interpolate between different positions? If this happens within the viewBox, would it be smooth? I'm unsure about this, because I don't have much experience with SVGs.
My question – how can I smoothly animate a div around the screen, which is styled with a border or border-radius?
I could live without the border, but the border-radius is strongly desired.
I am not entirely sure I have fully understood the problem as I am unable to recreate it in this situation:
This snippet uses transform scale and transform translate to animate an element. Evertyhing is calculated with vmin used as the basic unit just so you'll see the same aspect ratios whatever device/viewport you are using.
On my laptop the GPU usage is a pretty consistent 13%, the transforms are smooth and I can't see any distortion. So is there perhaps in the original code some absolutely defined unit used that doesn't for example scale correctly?
* {
margin: 0;
padding: 0;
}
body {
width: 100vw;
height: 100vh;
}
.container {
--containerw: 80vmin;
--containerh: 60vmin;
width: var(--containerw);
height: var(--containerh);
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
position: relative;
background-color: pink;
}
.test {
--startleft: 10;
/* where it starts (within the container as a %) */
--starttop: 10;
--endleft: 70;
/* where you want it to go to (within the container as a %) */
--endtop: 70;
--scalex: 4;
/* how much you want it to grow */
--scaley: 2;
--w: 10%;
/* its width */
--h: 10%;
/* its height */
width: var(--w);
height: var(--h);
border-radius: 1vmin;
border-width: 0.2vmin;
border-style: solid;
background-color: cyan;
animation: move 10s infinite linear;
position: absolute;
box-sizing: border-box;
}
#keyframes move {
0%,
100% {
transform: scale(1, 1) translate(calc(var(--startleft) * var(--containerw) / 100), calc(var(--starttop) * var(--containerh) / 100));
}
50% {
transform: scale(var(--scalex), var(--scaley)) translate(calc(var(--endleft) * var(--containerw) / 100 / var(--scalex)), calc(var(--endtop) * var(--containerh) / 100 / var(--scaley)));
}
}
<div class="container">
<div class="test"></div>
</div>
I figured out a fix! This allows smooth animations (using GPU-accelerated transformations) for a <div/> with rounded corners and a border, without any stretching.
It's based on the "border image" concept. Instead of animating one <div/>, we can animate 9 different divs, each representing a slice of the rectangle.
Top left corner
Top center rectangle
Top right corner
Middle left rectangle
Middle center rectangle
Middle right rectangle
Bottom left corner
Bottom center rectangle
Bottom right corner
The corners don't need to be scaled, only translated. This prevents any stretching. The rectangle edges are scaled in line with the border, and so it doesn't stretch a solid border.

How to disable linear-gradient when scroll to the bottom

I am using the answer from Fading out text at bottom of a section with transparent div, but height stays under section after overlaying div to achieve fading text at bottom
and a snippet of my code is below
<div className={styles.description}>
{description}
</div>
.description {
position: relative;
overflow: auto;
width: 640px;
height: 495px;
padding-right: 17px;
text-align: justify;
-webkit-mask-image: linear-gradient(to bottom, black 46%, transparent 100%);
mask-image: linear-gradient(to bottom, black 46%, transparent 100%);
}
and the effect is like this
however, the fading effect is fix, so when I scroll to the bottom, it still exist, therefore, some lines in the end of text would eventually unclear.
A simple way to solve this puzzle is add a extra transparent space in the end which large enough to expand the scrollbar, so that the text can get rid of fading out area. However, in my opinion, it seems not very elegant to me, so I wonder if there have methods can disable linear-gradient when scroll to the bottom.
Really appreciate your help, many thanks

Setting radial gradient with javascript

I'm trying to set a radial gradient to a div as background with JS. I want the gradient to start in the middle with something like 0.8 opacity and as it goes further to the edges the opacity becomes 0, creating soft fading effect. I tried a few things, but some didn't work at all and some worked not as good as I hoped for.
The one that worked, but not very good, was when I tried to apply it with many rgba definitions and reduce the opacity by 0.1 stop:
arrCircleDivs[i].firstChild.style.backgroundImage =
'-webkit-radial-gradient(center,rgba('+r+','+g+','+b+',0.8),
rgba('+r+','+g+','+b+',0.8),rgba('+r+','+g+','+b+',0.8),rgba('+r+','+g+','+b+',0.7),rgba('+r+','+g+','+b+',0.6),rgba('+r+','+g+','+b+',0.5),rgba('+r+','+g+','+b+',0.4),
rgba('+r+','+g+','+b+',0.3),rgba('+r+','+g+','+b+',0.2),
rgba('+r+','+g+','+b+',0.1),rgba('+r+','+g+','+b+',0))';
And these ones didn't work at all:
arrCircleDivs[i].firstChild.style.backgroundImage = '-webkit-radial-gradient
(center, circle cover, rgba(30,87,153,0.7) 0%,rgba(30,87,153,0) 100%);
arrCircleDivs[i].firstChild.style.backgroundImage = '-webkit-gradient
(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(30,87,153,0.7)),
color-stop(100%,rgba(30,87,153,0)));
I got the following error message:
Uncaught SyntaxError: Unexpected token ILLEGAL
So is there any way to set such effect with JS?
The only way i have found to do this is to use the element.style=backgroundVar and in your backgroundVar have it set to the background:...
E.G
let bg = `background:radial-gradient(circle at 0% 0%,
rgba(255,0,0,1), rgba(255,0,0,0) 75%),
radial-gradient(circle at 0% 100%,
rgba(0,0,255,1), rgba(0,0,255,0) 75%),
radial-gradient(circle at 100% 0%,
rgba(255,255,0,1), rgba(255,255,0,0) 75%),
radial-gradient(circle at 100% 100%,
rgba(0,255,0,1), rgba(0,255,0,0) 75%);`
document.getElementById("background").style = bg;
You could create it using CSS. You'll want to use all of the browser extension calls to ensure cross-platform consistency.
To create a radial gradient you must also define at least two color stops.
Example of Radial Gradient:
Radial Gradient Syntax
background: radial-gradient(shape size at position, start-color, ..., last-color);
By default, shape is ellipse, size is farthest-corner, and position is center.
Radial Gradient - Evenly Spaced Color Stops (this is default)
Example
A radial gradient with evenly spaced color stops:
#grad {
background: -webkit-radial-gradient(red, green, blue); /* Safari 5.1 to 6.0 */
background: -o-radial-gradient(red, green, blue); /* For Opera 11.6 to 12.0 */
background: -moz-radial-gradient(red, green, blue); /* For Firefox 3.6 to 15 */
background: radial-gradient(red, green, blue); /* Standard syntax */
}
Why even use JS ?
A better approach would be to simply add a class to your 'arrCircleDivs[i].firstChild' , something like .new-gradient-class.
Then On the actual CSS, you use this class to set the gradients you want.

Background-position not working when classname changed in IE7

I have an element which I am adding a class to.
the style is:
.bg{ background: url(/images/background.png) no-repeat top center #000; }
When I add the class with javascript the background image show up, and the color show up, but the positioning does not.
This works fine in everything except IE
You have defined a vertical value (top), and one that doesn't exist (middle).
The vertical values are top, center and bottom, while the horisontal are left, center and right.
When using both, the first is the horisontal and the second is the vertical, so you got them backwards.
Use:
.bg{ background: #000 url(/images/background.png) no-repeat center top; }
You're not using the CSS background: shorthand properly - you're missing the background-repeat part. It should be something like this:
.bg {
background: #000000 url(/images/background.png) no-repeat scroll center top;
} /* ^ ^ ^ ^ ^
color image repeat attachment position */
http://www.w3schools.com/css/css_background.asp

Categories

Resources