CSS to apply gradient as mask to DIV - css

I am having a div which comes with the following color definition:
div{
background-color: #009688;
height: 100px;
}
<div></div>
Now I want to overlay a alpha gradient on this base color to get a similar effect like I would have with this definition:
div{
background: linear-gradient(-45deg, rgba(0,105,96,1) 0%, rgba(11,155,159,1) 50%, rgba(2,142,145,1) 51%, rgba(0,203,175,1) 100%);
height:100px;
}
<div></div>
The idea is that I do not want to calculate the linear-gradient behavior for every base color. Instead I want to use arbitrary base colors and add default masks to them. Is this possible with CSS3?

You can approximate it by using some white/black color over the background color. Simply adjust the alpha of each color to have the needed effect:
.b1 {
background-color: #009688
}
.b2 {
background-color: red
}
div{
background-image:
linear-gradient(-45deg, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.3) 51%, rgba(255,255,255,0.3) 100%);
height:100px;
}
<div class="b1"></div>
<div class="b2"></div>

Related

Placing a gradient background on an image with transparent background

What I would like to achieve is basically have a gradient appear on the text as opposed to the background of an image. I have created an example here:
https://codepen.io/BenSagiStuff/pen/BaYKbNj
body{
background: black;
}
img{
padding: 30px;
background: linear-gradient(to right, #E50000 8%, #FF8D00 28%, #FFEE00 49%, #008121 65%, #004CFF 81%, #760188 100%);
}
<img src="https://upload.wikimedia.org/wikipedia/commons/9/95/Transparent_google_logo_2015.png" >
As you can see, currently the background of the image has the gradient, but, what I would like is for the text "Google" to have the gradient and the background of the png should stay as black.
Ultimately the goal would be to have the gradient transition underneath the image as well, so the gradient slides horizontally under the image as well.
Use the image as a mask on a common element
body{
background: black;
}
.box{
--img:url(https://upload.wikimedia.org/wikipedia/commons/9/95/Transparent_google_logo_2015.png);
width:300px;
aspect-ratio:3;
background: linear-gradient(to right, #E50000 8%, #FF8D00 28%, #FFEE00 49%, #008121 65%, #004CFF 81%, #760188 100%);
-webkit-mask: var(--img) 50%/cover;
mask: var(--img) 50%/cover;
}
<div class="box"></div>
There's a little problem with your implementation.
PNG is transparent, but it's a square piece of image. You might be successful using a svg image or just applying this gradient background in a text tag.
on your HTML you make this way:
<div>
<h1>Google</h1>
</div>
Your CSS this way
body{
background: black;
font-family:helvetica;
}
h1{
background: linear-gradient(to right, #E50000 8%, #FF8D00 28%, #FFEE00 49%, #008121 65%, #004CFF 81%, #760188 100%);
font-size: 160px;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
div {
display:flex;
}
It's also better for performance.
Also, you can animate easily.
Such as the example in this codepen https://codepen.io/shshaw/pen/YpERQQ
:)

Setting linear gradient height AND width

I am aware that you can set the width of a linear gradient using
.grey-block { background: linear-gradient(to right, #f9f9f9 0%, #f9f9f9 35%, white 35%, white 100%); }
As well as the height
.grey-block { background: linear-gradient(to bottom, #f9f9f9 0%, #f9f9f9 65%, white 65%, white 100%); }
However, is there a way you can set BOTH the height and the width using a the same css line?
To clarify, the code in the question is not setting the height and width of the gradient. It's adjusting the color stops, which results in a grey rectangle.
In order to adjust the actual dimensions of the gradient, we need to use the background-size property (as well as background-repeat) to set the height and width of the gradient.
With background-size in control of the gradient's dimensions, we can rewrite the CSS to be as follows:
.grey-block {
background-color: white;
background-image: linear-gradient(#f9f9f9, #f9f9f9);
background-size: 35% 65%;
background-repeat: no-repeat;
}
What's happening is that we're defining a "gradient" of a solid color and confining it's size. The background-repeat is disabled so that it will only render a single grey block.
.grey-block {
background-color: white;
background-image: linear-gradient(#f9f9f9, #f9f9f9);
background-size: 35% 65%;
background-repeat: no-repeat;
}
/* non-relevant styles */
body {
background-color: #222;
}
.grey-block {
height: 200px;
width: 200px;
}
<div class="grey-block"></div>
You can specify an angle. That should do the trick.
.grey-block { background: linear-gradient( 135deg, #f9f9f9 0%, #f9f9f9 65%, white 65%, white 100%); }

Create an Intersecting Linear Gradient

I know I can make a linear gradients as a background of a div element. But is it possible to make intersecting line gradients? See image below:
Yes, it is very much possible to create such patterns by using two linear-gradient images. When multiple background images are assigned to an element, the UA would by default set them as layers where the first one from the right is the lowermost layer and last one from right becomes uppermost.
Below is a sample snippet for both the patterns.
(Note: In the angled lines pattern, I've set the color stop points differently to avoid jagged lines. The angled linear gradients always tend to produce them.)
div {
height: 200px;
width: 200px;
margin: 10px;
border: 1px solid;
}
.checkered {
background: linear-gradient(to right, black 1px, transparent 1px), linear-gradient(to bottom, black 1px, transparent 1px);
background-size: 10px 10px;
background-position: 5px 0px, 0px 5px;
}
.angled {
background: linear-gradient(45deg, transparent 7px, black 7px, transparent 8px), linear-gradient(315deg, transparent 7px, black 7px, transparent 8px);
background-size: 10px 10px;
}
<div class='checkered'></div>
<div class='angled'></div>
Not sure if this is what you are after:
HTML
<div id="red2blue"></div>
<div id="blue2red"></div>
CSS
div{
width:100px;
height:100px;
opacity: 0.5;
position:absolute;
top:0;
left:0;
}
#red2blue{
background: linear-gradient( 45deg, red, blue );
}
#blue2red{
background: linear-gradient( -45deg, blue, red );
}
https://jsfiddle.net/9na275fn/

Is it possible to make a hard-edged gradient on a large element?

I ran into a problem using a linear-gradient on a particularly large element.
On smaller elements, a hard edge can be achieved with the following:
background-image: linear-gradient(180deg, #000, #000 33%, #0f0 0);
However when the element has a very large height, the edge is soft. You can see in the following image and example below, the second version has a soft edge when the element is very large and the same gradient is applied.
I have tried many variations on the linear gradient and have been unable to achieve a hard edge on the large version. Is there a way to apply a gradient with a hard edge on a large element?
HTML example:
div {
height: 5000px;
background-repeat: no-repeat;
margin-bottom: 1em;
background-image: linear-gradient(180deg, #000, #000 20px, #0f0 0);
}
div:first-child {
height: 100px;
}
<div></div>
<div></div>
Edit
The goal of this gradient is for use with another background image, so I prefer techniques that are compatible with the following (don't cover the image):
div {
height: 5000px;
background-repeat: no-repeat;
margin-bottom: 1em;
background-image: url(http://placehold.it/600x20), linear-gradient(180deg, #000, #000 20px, #0f0 0);
}
<div></div>
Edit 2
Thanks to #Tarun, this appears to be browser related. The above image is a screenshot from Chromium 45. Safari and Firefox appear to render correctly.
Edit 3
There is an open bug report for chromium about this issue.
I've found an alternative using gradients to achieve the same effect, however I think it should be possible to achieve this with 1 gradient, so I consider this a work-around.
The trick is to use multiple backgrounds with 2 gradients that don't change color. Then just define background-size to achieve the hard edge effect. See the working snippet:
div {
height: 5000px;
background-repeat: no-repeat;
margin-bottom: 1em;
background-image: linear-gradient(#000, #000), linear-gradient(#0f0, #0f0);
background-size: 100% 20px, 100%;
}
div:first-child {
height: 100px;
}
<div></div>
<div></div>
This works for me.
background: linear-gradient(to bottom, black 0% ,black 20% ,green 20% ,green 100%);
edit: I've tried to do exactly what you're doing in the question, and I'm getting a hard edge on both boxes. Your problem must be related to your browser.
edit 2: confirmed
You could use box shadow for the same effect.
div {
height: 5000px;
}
div {
background: #0f0;
box-shadow: inset 0 100px 0 0 #000;
}
<div></div>
You need to repeat each color, and each percent rate of linear-gradient in a tricky, but expressive way. Let's see it in a six colors sample to understand the principle.
This approach works for any size of block.
div {
height: 100px;
background-repeat: no-repeat;
margin-bottom: 1em;
background-image:
linear-gradient(90deg,
red,
red 17%,
orange 17%,
orange 34%,
yellow 34%,
yellow 51%,
black 51%,
black 68%,
green 68%,
green 85%,
blue 85%);
}
<div></div>
You could use a bit more codespace and set up your gardient like following:
background: #4c4c4c;
background: linear-gradient(to bottom, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313',GradientType=0 );
The solid background setting is there to make sure your page is showing some color if the browser somehow fails to support this type of gardient or its filter.
It is also preferred to include -moz, -o and other browser-based fixups to make sure.

CSS tricks: underline with alpha-gradient on both ends

I need to underline my elements (menu items) with a line which has an gradient on BOTH ends.
It can't simply be a graphic (even stretched one), since the width of elements may vary significantly.
The desired effect:
What I did, was to create a line, 1000px wide, with gradient on both ends, then append following HTML <div><div class="right"> </div></div> to every element to be underlined.
The CSS is following
#navmenu li div
{
height: 1px;
background-image: url('images/1000glight.png');
background-repeat: no-repeat;
}
#navmenu li div.right
{
width:35px;
float: right;
background-position: -965px 0;
background-image: url('images/1000glight.png');
background-color: #212121;
}
This however is not truly alpha. I need to specify the background color of "right-side" div in order to "cover" the image (1000px line) which is below.
Any ideas how could I improve it, keeping pure CSS?
Using an approach similar to this, with the gradient being the background image of a wrapping div with padding-bottom to show only the lower part of the background:
<div class="wrap">
<div class="content">Some Text!</div>
</div>
And CSS:
.wrap {
float: left;
padding-bottom: 5px;
/* IE10 */
background-image: -ms-linear-gradient(right, #fff 0%, #000 25%, #000 75%, #fff 100%);
/* Mozilla Firefox */
background-image: -moz-linear-gradient(right, #fff 0%, #000 25%, #000 75%, #fff 100%);
/* Opera */
background-image: -o-linear-gradient(right, #fff 0%, #000 25%, #000 75%, #fff 100%);
/* Webkit (Safari/Chrome 10) */
background-image: -webkit-gradient(linear, right top, left top, color-stop(0, #fff), color-stop(0.25, #000), color-stop(0.75, #000), color-stop(1, #fff));
/* Webkit (Chrome 11+) */
background-image: -webkit-linear-gradient(right, #fff 0%, #000 25%, #000 75%, #fff 100%);
/* Proposed W3C Markup */
background-image: linear-gradient(right, #fff 0%, #000 25%, #000 75%, #fff 100%);
}
.content {
background-color: #fff;
}
Works, but does omit IE<10; which might be do-able with some kind of filter, but that'll take more reading before I can post such.
JS Fiddle demo of current implementation.
Unfortunately the DX.transform option doesn't appear able to allow for multiple stops that the above uses, reference: Simulating color stops in gradients for IE
So, perhaps you'd have to use a background-image fallback for IE<10, which is far less than ideal.
Use the border-image gradient CSS3.
div {
width:200px;
border-style:solid;
border-width:15px;
text-align: center;
-webkit-border-image:
-webkit-linear-gradient(left, rgba(255,255,255,1) 1%,rgba(0,0,0,1) 50%,rgba(255,255,255,1) 100%) 0 0 100% 0/0 0 15px 0 stretch;
}
Demo here.
This will only work with Webkit browsers (Chrome, Safari etc). There should be some vendor specific equivalents.
You can use an empty div with a CSS3 Gradient... check out the presets here: http://www.colorzilla.com/gradient-editor/ - of course you'll have to change the orientation of the gradient. I use this a lot for similar issues. It's a great alternative to images.

Resources