Essentially I'm trying to create an gradient alpha mask in using SVG and CSS (like this), and since the mask property is no longer on the standards track I'm exploring the filter route.
I've created a vertical alpha mask in Sketch, with the top being 0% #000000 and the bottom being 100% #000000, then exported it as an SVG and tweaked it using guidance from this O' Reilly article. It now looks like this:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<!-- Start by creating our vertical linear gradient -->
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="alphaLinear">
<stop offset="0%" style="stop-color: #000000; stop-opacity: 0%;" />
<stop offset="100%" style="stop-color: #000000; stop-opacity: 100%;" />
</linearGradient>
<!-- Create a rectangle and apply the gradient as its fill -->
<rect id="boxRect" x="0" y="0" width="100%" height="200" style="fill: url(#alphaLinear);" />
<!-- Using that rectangle, we'll create a filter -->
<filter id="alphaGrad">
<feImage xlink:href="#boxRect" result="grad"/>
<feDisplacementMap scale="10" xChannelSelector="R" yChannelSelector="G" in="SourceGraphic" in2="grad"/>
</filter>
</defs>
<use id="gradientBox" fill="url(#alphaGradient)" xlink:href="#boxRect"></use>
</svg>
My knowledge of SVG isn't the greatest so I'm suspecting this is where I've gone wrong.
Next, I applied the filter using filter (and -webkit-filter) along with referencing the filter ID #alphaGrad:
-webkit-filter: url('http://blahblah.com/alphagradient.svg#alphaGrad');
But, of course, this it doesn't work. Can anyone help me get the hang of this? Or is this even possible? If not, can someone recommend a method of how to achieve this?
Thanks in advance!
Update: here's a pretty basic fiddle of what I'm doing...
There are many errors and misconceptions in your example (why did you think a displacementMap would help you?)
Why don't you start from the code below - pure SVG using an SVG mask and an SVG image.
<svg width="600px" height="600px" viewbox="0 0 600 600">
<defs>
<linearGradient id="alphaLinear">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0%" />
<stop offset="100%" stop-color="#999999" stop-opacity="100%" />
</linearGradient>
<mask id="Mask">
<rect x="0" y="0" width="600" height="600" fill="url(#alphaLinear)" />
</mask>
</defs>
<image xlink:href="http://upload.wikimedia.org/wikipedia/commons/7/71/Anadama_bread_(1).jpg" width="600" height="600" x="0" y="0" preserveAspectRatio="xMinYMin meet" mask="url(#Mask)"/>
</svg>
Few remarks:
SVG (and CSS) opacity value is not percertentual range but 0.0 - 1.0 range.
Mentioned mask property appears to be just prefixed in Webkit and unprefixed in Gecko.
If your target environment is HTML + CSS, you might not necessarily need SVG: you could get similar effect using linear-gradient and RGBA
background-image: linear-gradient(to bottom, rgba(0,0,0,1) 0%,rgba(0,0,0,0) 50%); on some overlay (pseudo) element. pointer-events: none; could be useful then.
Related
I tried to make it with border but gradient makes it impossible. Maybe I can make four divs and make it like that?
CSS might not be the best way to create such shapes. You should use SVG instead.
We can use SVG's path element to create a pointing arrow like shape and fill it with gradient created with linearGradient.
Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.
Here is a detailed information about SVG paths:
body {
text-align: center;
background: #333;
margin: 20px;
}
<svg width="400" height="400" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient">
<stop offset="0" stop-color="#212121"></stop>
<stop offset="1" stop-color="#a7a7a7"></stop>
</linearGradient>
<path id="arrow" x="0" y="0" d="M0,200
A200,200 0, 0, 1, 200,0
L225,25
L200,50
A150,150, 0, 0, 0 50,200
L25,175" fill="url(#gradient)" />
</defs>
<use xlink:href="#arrow" transform="translate(0,400) rotate(270)"></use>
<use xlink:href="#arrow" transform="translate(400,400) rotate(180)"></use>
<use xlink:href="#arrow" transform="translate(400,0) rotate(90)"></use>
<use xlink:href="#arrow"></use>
</svg>
I found this SVG code, and I was wondering how do I apply it to a background image?
<svg width="600px" height="600px" viewbox="0 0 600 600">
<defs>
<linearGradient id="alphaLinear">
<stop offset="0%" stop-color="#FFFFFF" stop-opacity="0%" />
<stop offset="100%" stop-color="#FFFFFF" stop-opacity="100%" />
</linearGradient>
<mask id="Mask">
<rect x="0" y="0" width="600" height="600" fill="url(#alphaLinear)" />
</mask>
</defs>
<image xlink:href="/media/images/body-bg.jpg" width="600" height="600" x="0" y="0" preserveAspectRatio="xMinYMin meet" mask="url(#Mask)"/>
</svg>
In the <image> tag I replaced the href url with the image I want to use. I then call the svg from the css like so:
body{
background: url('/media/images/gradient.svg') center top no-repeat;
}
Nothing seems to be happening, all I am getting is a white background.
There are a few things wrong:
For external files, you will need the xmlns and xmlns:xlink namespace declarations in the <svg> tag.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="600px" height="600px" viewbox="0 0 600 600">
viewbox should be viewBox
SVG files used as an external image in <img> or as a background-image need to be self contained. They cannot refer to other external files as you are doing here.
You can embed the external JPEG as a Data URI though if you want.
<image xlink:href="data:image/jpeg;base64,...Base64 encoded JPEG data here...">
So I know I can swap out a gradient fill on an svg with css, something like;
<svg width="100" height="50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style type="text/css">
rect{fill:url(#GradientSwap1)}
</style>
<defs>
<linearGradient id="GradientSwap1">
<stop offset="5%" stop-color="#F00" />
<stop offset="95%" stop-color="#999" />
</linearGradient>
</defs>
<rect width="100" height="50"/>
</svg>
and using ng-class I can swap out more than one of these gradients, except I can only get it to work if I include the <linearGradient> in the defs embedded into each SVG.
My question is, and what I can't seem to figure out. Is there a way to pull these gradient defs out of the SVG and make them into a resource I can use in others? Like in the .NET / XAML world, it would be really easy for me to pull them out, throw them in a resource dictionary, and use the same ones all over the place for whatever I like.
So is there an html5/css3/angular approach to the same conundrum? The idea of having to have to multiple SVG's with potentially multiple of the same Gradient defs reiterated for every single one just sounds wrong.
You should be able to define the gradient once and then call it in the CSS to apply anywhere. You could apply to all svgs or give it a class.
<svg>
<defs>
<linearGradient id="GradientSwap1">
<stop offset="5%" stop-color="#F00"></stop>
<stop offset="95%" stop-color="#999"></stop>
</linearGradient>
</defs>
<section>
<svg class="icon shape-facebook">
<path d="M28.3,62V35.2h-5.5v-9.4h5.6v-7.7c0,0,0.3-9.8,9.8-9.8s9.5,0,9.5,0v9.2H42.1c0,0-2.699,0-2.699,2.7c0,2.7,0,5.8,0,5.8H48
l-1.1,9.4H39.6V62H28.3z"></path>
</svg>
<svg class="icon shape-heart" x="0" y="0">
<path d="M35.645,59.413c0,0,26.949-19.601,26.949-34.12c0-16.752-22.049-22.047-26.949-1.674
c-4.9-20.373-26.95-15.078-26.95,1.674C8.695,39.812,35.645,59.413,35.645,59.413z"></path>
</svg>
.shape-heart { fill: url('#GradientSwap1'); }
http://jsfiddle.net/v6osyy5v/1/
Ive been creating css3 text gradients. They work perfectly find in browsers, but when you view them on the web. there is always a line or a box around the text. Similar to what happens on this page: http://www.paulund.co.uk/playground/demo/css_text_gradient/
Is this a webkit bug?
Thanks to Michael's advice using an svg bg over a css3 generated one fixes the mobile issue.
Here is the code for the css:
background:url(../img/grad.svg) 0 -116px;
background-size: 100% 100%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
And then the grad.svg:
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="60">
<linearGradient id="normal" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#ffffff"/>
<stop offset="100%" stop-color="#000000"/>
</linearGradient>
<rect x="0" y="0" width="100%" height="60" fill="url(#normal)" />
</svg>
I've seen this technique used quite a lot. Like say a separator border (like bottom border for stackoverflow header) which fades at both ends. How do I achieve this with compass? I've searched their documentation and google and can't find any examples of how to do this.
I've never used Compass CSS, but how about mixing CSS and SVG?
Your SVG file:
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="div" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(255, 255, 225);stop-opacity:0"/>
<stop offset="50%" style="stop-color:rgb(153,153,153);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255, 255, 225);stop-opacity:0"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#div)" />
</svg>
The CSS:
div.separator
{
width: 80%;
height: 16px;
background-image: url(gradient_file.svg);
}