SVG with transparency - html

I'm aiming to create an effect just like the one found on this codepen. There's an SVG with transparency over a background video. So far I have an AI document with a path shape selected that I exported from photoshop. Ideally I want the inside of the path to be transparent, but the rest to be white just like in the example. How can I achieve an effect like this?
it looks like it has something to do with this line of code, but I'm definitely misunderstanding something.
svg > rect {
fill: white;
-webkit-mask: url(#mask);
mask: url(#mask);
}
I don't think my SVG is ready with just being a path, as if I export it it shows up as blank and if I put a stroke on the path either everything but the stroke is transparent or it doesn't appear with any transparency at all.
normally my workflow as a web developer never has me working this in depth with SVG's so I'm a little stuck on this one.

The #mask in that CSS rule, refers to this element in the SVG:
<mask id="mask" x="0" y="0" width="1920" height="1080" >
...
</mask>
You can learn about how masks work by reading the SVG specification or one of the many tutorials available on the web.

Related

Is it possible to clip a HTML element using an SVG image file as the source?

I'm trying to achieve the following effect, this is just done in photoshop with the pattern cut out of the background.
The patterns you see in the left side are cut out of the dark background to display the image that is sitting behind them.
I have the SVG file of that image and was wondering if it is possible, if so how, to clip a solid background to those shapes using the SVG file as the source?
Yes, you can do this by giving the HTML element either a mask property that references a <mask> element in your SVG file or a clip-path property that references a <clipPath> element in your SVG file.
.element {
/* just because of your example: */
background-image: url(forest-road.jpg);
/* use one of these two: */
clip-path: url(spirograph.svg#myClipPath);
mask: url(spirograph.svg#myMask);
}
<svg ...>
<!-- use one of these two: -->
<clipPath id="myClipPath">
<!-- shapes, etc., go here -->
</clipPath>
<mask id="myMask">
<!-- shapes, etc., go here -->
</mask>
</svg>
The two CSS features work slightly differently, with masking being newer and more flexible but having some residual gaps in browser support (including needing prefixes). Either way, you'll need to adjust your SVG to be suitable. A <mask> should make a pixel white for opaque and black for transparent, with greys being intermediate opacities. On the other hand, a <clipPath> defines the region that is visible as the union of a series of shapes.

Manipulating external svg file style properties with CSS

I am trying to manipulate an external .svg file via CSS.
HTML
<body>
<div class="mysvg">
<img src="decho.svg" alt="decho" width="200px"></img>
</div>
</body>
CSS
div.mysvg img {
opacity: .3;
transition: opacity 1s linear 0s;
}
div.mysvg img:hover {
opacity: 1;
}
This code works for opacity, but not for fill or other svg specific attributes like stroke. I am aware I can't do that with an img tag, but I've been looking for hours and I can't find the correct way to do it with svg or object.
So basically, my questions is, how do I achieve the same result as the code which I linked, but to be able to manipulate fill, stroke etc. properties and it must be an external file, not just an inline svg code pasted in the html.
If someone is able to show me the correct way to do it, I'd be most grateful. Thanks.
EDIT:
I managed to do it by adding a css inside the .svg file itself. It must be right after the svg opening tag.
<svg ...>
<style type="text/css" media="screen">
<![CDATA[
g {
fill: yellow;
stroke: black;
stroke-width: 1;
transition: fill 1s linear 0s;
}
g:hover {
fill: blue;
}
]]>
</style>
<g>
<path ...>
</g>
</svg>
You also need to insert it as an object in the html, otherwise it won't work.
<object data="decho.svg" type="image/svg+xml">
Hopefully this helps to someone looking for an answer like mine in future. This is what helped me http://www.hongkiat.com/blog/scalable-vector-graphic-css-styling/.
This is in my opinion the greatest flaw in svg: sandboxing.
Svg files are sandboxed: in their own document, which is why a typical 'fill:' style will not apply. Likewise, the css you write in your svg will not apply to the rest of your site.
Adding css directly to an svg: Not a good solution as you will end up rewriting the css in every svg you use.
The real solution: An "icon-system". Svg font-face or svg sprites. Read more about them here.
The reason opacity works: Opacity applies to the svg object/frame itself, not the contents of the svg (which are inaccessible).
I should also note that no matter how you load those svg's, inline, by reference, in an object, as a background, you will not be able to get inside the sandbox. This is why converting them to a font or using sprites is necessary for using hover, focus, and other effects/transitions.
This is possible providing the SVG is hosted on the same domain (thanks #FabienSnauwaert) and it does not have a fill colour defined on itself, and you do not contain a parent selector within the CSS. For example:
I have the following files:
icon-sprite.svg (my external sprite of SVGs)
buttons.scss
test.html
icon-sprite.svg
I have omitted the other SVGs for clarity.
<svg xmlns="http://www.w3.org/2000/svg" style="width:0;height:0;visibility:hidden;">
<symbol viewBox="0 0 1500 828" id="icon-arrow-3pt-down">
<title>arrow-3pt-down</title>
<path d="M1500 0H0l738.9 827.7z"/>
</symbol>
</svg>
test.html
<button class="button--large">
Large button
<svg class="svg" width="20px" height="20px">
<use xlink:href="icon-sprite.svg#icon-arrow-3pt-down"></use>
</svg>
</button>
buttons.scss
.svg {
fill: red;
}
This would not work if I was to use body .svg due to shadow DOM boundaries.
See this CSS Tricks article for more info
I recently ran into this. While SVGs are not part of the DOM for some arbitrary reason, you can move them to the DOM with a bit of javascript:
<object type="image/svg+xml" data="illustration.svg"
onload="this.parentNode.replaceChild(this.contentDocument.documentElement, this);">
</object>
This will replace the <object> with an inline after it has loaded. In case javascript is disabled, it falls back to an <object> tag, and the svg will not be themed. In my case, the styling was for a javascript-controlled dark theme, so having the correct fallback means no theming issue.
Other options considered (xlink is a good one for sprites):
Use an external library to load svgs inside the DOM (the above js is simple enough IMO)
use svg filters for chroma-keying. That makes svgs more complex to edit, might use more resources to perform the filtering, and is less flexible.
Note that I am not sure of the security implications, better save this for files you control.
Unfortunately, there's no built-in feature in Web Standards that makes it possible. SVG Symbols is an option but doesn't work with files hosted on CDNs. Additionally, you need to ensure that SVG files are defined properly to make use of <use> tag.
I have created a library, svg-loader, that makes it easier to achieve this. It uses Javascript but it's only 3kb and it's loaded asynchronously, so the impact on performance is negligible. It's plug 'n play, so you don't need to do anything except including the <script> tag.
Here's a Codepen example.

SVG as border-image on retina screens

Please consider we have simple SVG file, containing code for rounded rectangle which corner radius equals 10:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<rect fill="#FACE8D" x="0" y="0" width="100" height="100" rx="10" ry="10" />
</svg>
Here how it looks like in Chrome:
Now we use this image as a value for border-image property in CSS:
.box {
#include border-image(url('rounded-rectangle.svg') 10);
border-width: 10px;
background: #FFF;
width: 50px;
height: 50px;
}
Now let's take a look on how it looks like in different browsers and devices: brilliant, the image stretched across element's boundaries as expected.
However, when we end up viewing those on devices with retina screens, we've got some total crap: SVG seems to be grown twice. All we see is one enormous corner.
If we replace that SVG with a similar PNG, everything is fine. Take a look (iOS 5.1 painted the inner parts of elements with the image color for some reason, however, this is not a subject of this question):
Live demo
The question is: can this be dealt with? Maybe, I've got some wrong SVG? Or I need to set the viewport meta-tag with some tricky stuff to stop border-image from scaling?
The problem is quite important. First of all, SVG is being popular mostly because of retinas. It is the tool to decorate things without being worried they would look like crap on doubled pixels.
Secondly, the mechanics and syntax of the border-image property is quite similar to the -webkit-mask-box-image proprietary property, using which is still the only way to round corners of blocks which contain absolutely positioned children (for example, Google Maps v3 can be rounded in Chromes and Safaries only through it). And this property is very valuable in mobile development with web components, when we need to set some tricky contour to an UI element. Sadly, by this property doubles it's SVG dimensions just like border-image.
UPDATE. Seems that this issue may be caused by updated SVG processor introduced in iOS 6.0: on retina SVG dimensions are computed in CSS pixels, while the coordinates are computed in retina ones. There are some bugs tracked that have something similar with my issue.
Given your update about iOS6 bugs, this approach might work:
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<rect fill="#FACE8D" x="0" y="0" width="100%" height="100%" rx="10%" ry="10%" />
</svg>
Forget images you can do this with simple css
.box {
border: 10px solid #FACE8D;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
background: #FFF;
width: 50px;
height: 50px;
}
Supported since iOS 3.2 ... http://caniuse.com/border-radius
If you need an image in order for the border to have a pattern, you can simply use a web format image without transparency and use border-radius on that

What could make Safari skip clip-path AND mask with SVG?

I don't have any problems using clip-path with links to .svg files in Firefox, but Safari seemingly refuses to use them.
If you load my WIP page http://www.omakadesign.com in Firefox, you will see a butterfly pattern at the bottom of the menu, but if you load it in Safari, the menus are completely rectangular.
The relevant line appears in main.css (221) and looks like:
clip-path: url("../img/menu-news.svg#news-clip");
There seems to be very little information about clip-path and Safari, and not many questions about it on this site either (believe me I've looked). But then again, I can't even get the most basic inline svg example with clip-path to work even in Firefox, so perhaps there is something fundamental I'm missing on this topic?
(Also, though this is another subject, why these menus have both padding and margin on the bottom is a mystery to me since I zero them out using min-width...)
UPDATE:
I did a test and created a .svg with a mask tag in it and replaced the clip-path line that appears above with a css mask instead (still 221 if you want to try it with the Firefox Style Editor) and amazingly that still works in Firefox and Safari STILL skips over it:
mask: url("../img/menu-news-mask.svg#news-mask");
(Final update: Found the solution, but I'm not allowed to post it for another 5 hours... turns out, you have to use very, very specific SVG and use -webkit-mask for Safari.)
I found the solution. You have to use VERY SPECIFIC SVG code! Follow the example of this guy to the letter, and clipping will work in Safari too:
https://github.com/Modernizr/Modernizr/issues/213#issuecomment-1149691
(Sorry about posting my own answer for my own first question, but I was really desperate and I usually find that when you start asking others, that's when you stumble upon the solution...)
EDIT: Doesn't work in IE9, which I don't really care about, but just a heads up for those who do (the fallback is simply a plain rectangular menu for me which still works).
Thank you for having that link to Modernizr's github!
For a note on if you are clipping an image, what's important is the path has to be inside the clipPath.
On a side note, if you export your SVG Code from Illustrator. Just make sure to use the actual path instead of this:
<defs>
<path id="path" d="....">
</defs>
<clipPath id="clipping">
<use xlink:href="#path"/>
</clipPath>
<image clip-path=url(#clipping) ...>
to the actual path like this...
<clipPath id="clipping">
<path id="path" d="....">
</clipPath>
<image clip-path=url(#clipping) ...>
It will work in FF, Chrome, Safari, Opera and IE9 & 10.
Here's the jsfiddle
Edit
The original issue now I realized is a slightly different problem than what I had... Which is using the svg path to clip an image outside of the svg as an img tag. Unfortunately, IE, even 10 didn’t work when I tried the exact same method. Therefore, if you have have a single image, best is to embed the image inside the svg itself instead of clipping an img tag with the path. That worked for IE9&10 and then some..
For second part of your question (..why these menus have both padding and margin on the bottom..) :
main.css line 95
nav a {
background: none repeat scroll 0 0 #616161;
color: white;
display: block;
font: 12px/20px Lucida Sans Unicode,Lucida Grande,Lucida Sans;
margin-bottom: 10px;
padding: 15px 0;
text-align: center;
text-decoration: none;
}

Is Starburst effect doable in CSS3?

does anybody know if the following image could be made in CSS? Light and dark lines could and should be equal width and edges fade in to darker color so that overall background would be dark color (dark blue in this case).
Any help is well appreciated. My google skills didn't provide any help on this kind of effect, only 'starburst stickers / badges kind of things' was found.
No. Sadly, the css3 generated image specs do not include conical/angular gradients (though they might come out in the next revision!) which would be the most likely way to do this using only css. However, you can do this using css+svg. I actually had this svg document sitting around from an experiment I did once:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="512px" height="512px" viewBox="-256 -256 512 512" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Burst</title>
<defs>
<g id="burst">
<g id="quad">
<path id="ray" d="M0,0 -69,-500 69,-500 z" />
<use xlink:href="#ray" transform="rotate(30)"/>
<use xlink:href="#ray" transform="rotate(60)"/>
<use xlink:href="#ray" transform="rotate(90)"/>
</g>
<use xlink:href="#quad" transform="rotate(120)"/>
<use xlink:href="#quad" transform="rotate(240)"/>
</g>
<radialGradient id="grad" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" stop-color="white" stop-opacity="0.65"/>
<stop offset="100%" stop-color="black" stop-opacity="0.65"/>
</radialGradient>
<!-- a circle mask -->
<mask id="m"><circle r="256" fill="white"/></mask>
</defs>
<!-- added a mask and scaled it to a different aspect ratio below. scale(x,y) -->
<g mask="url(#m)" transform="scale(1, 0.75)">
<use xlink:href="#burst" fill="lightslateblue"/>
<use xlink:href="#burst" fill="darkslateblue" transform="rotate(15)"/>
<circle r="360px" fill="url(#grad)" />
</g>
</svg>
Set that as your background-image, and set the css background-size: cover. That's it. Here's a fiddle using this image in a data url.
Yes, it's possible.
But it takes some work.
I had this exact same question, and could not find any examples of this effect being done with pure CSS. And so, I decided to tinker around with it.
After a lot of experimentation, I finally came up with a solution that not only were in CSS, but also one that is rather portable (relatively speaking).
I started off with creating just the top half and the bottom half separately, using linear-gradient trickery on ::before and ::after pseudo elements, and the second step (which by far was the most time consuming step) was merging the two halves into a single element.
Working demo: http://codepen.io/pestbarn/pen/aBybeK
(the original poster wanted a vignette effect, which I've created separately in the above demo, using a div overlay with a radial gradient)
I've provided both the vanilla CSS and a Sass mixin at github.com/pestbarn/starburst.css, and you'll find some examples at the official demo page.
Is this cross-browser?
As far as I can tell, yes. You can see the current browser support in the repository.
Can I animate it?
Yes, like you would animate any other elements. Try it out for yourself!
Are there any caveats?
Alas, there is. Using two colors that are substantially different from another (e.g. in brightness) will create jagged edges. I'd therefore recommend using colors that are quite similar to one another.
Also, since the effect is created using pseudo elements, you will in some cases need to explicitly set the element's height and width.
Feel free to experiment!
There is an experimental property in a draft for CSS4 by Lea Verou:
div
{
repeating-conical-gradient(black, black 5%, #f06 5%, #f06 10%)
}
But as far as I understand, this is just a proposal and is not possible in CSS3 alone. Just stick with a background image, or you could try using triangle images in rotated elements.
With the addition of conic-gradient() to the CSS spec, it is now possible to create the effect using CSS that is intended for that type of effect.
Essentially, you'll set gradient stops like this:
background-image: conic-gradient( circle,
black 0%, black 5%,
white 5%, white 10%,
black 10%, black 15%,
...
);
Here's a working fiddle
And here's an animated version :-) The animation is a bit choppy on my browser, though. It could maybe be optimized a bit.
Note that this only works in WebKit browsers; that is, Chrome and Safari. But honestly, that covers the lion's share of users, and I'm sure the rest will add support for it soon enough.
There is currently a better solution than the "conic-gradient ()" method to extend the "marcus erronius" answer. There is a repeating-conic-gradient, which creates an image consisting of a repeating gradient.
div {
height: 500px;
background: repeating-conic-gradient(
hsl(0deg 0% 80% / 31%) 0deg 15deg,
hsla(0,0%,100%,0) 0deg 30deg
) #3c1c32
}
<div></div>
You read more about it at W3 CSS Image Values.
This property is not compatible with all browsers. Check caniuse for more information.