Clip-path SVG polygon Internet Explorer - html

This code does not work in IE, I need to use it because I have to make an arrow that follows a point on the map.
div {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
right: 0px;
background: red;
clip-path: url(#cliparrow);
-webkit-clip-path: polygon(777px 285px, 0px 303px, 777px 315px);
}
svg {
width: 0;
height: 0;
float: left;
position: absolute;
}
<div></div>
<svg height="0" width="0">
<defs>
<clipPath id="cliparrow">
<polygon points="777,285 0,303 777,315" ></polygon>
</clipPath>
</defs>
</svg>
Any suggestions? Thanks.

Internet Explorer is not (currently) compatible with using clip-path via CSS on HTML elements (see can-i-use). clip-path is currently only a candidate recommendation for HTML and not yet in the spec (http://www.w3.org/TR/css-masking-1/).
You may, however, use clip-path as an SVG attribute on another SVG element (for example, if you load the MDN page on clipping and masking in SVG, it will work in IE).
If all you need to do is embed a colored shape, and not transform HTML content per se (e.g. apply clipping against HTML text, multiple elements, etc), you could even more simply just use an appropriately shaped SVG element (directly embedded in an otherwise transparent div if needed) instead of trying to clip an HTML element. This also removes the need for the browser specific webkit prefix.
<div>
<svg width="700px" height="700px" xmlns="http://www.w3.org/2000/svg">
<polygon id="arrow" points="777,285 0,303 777,315" ></polygon>
</svg>
</div>
example fiddle (with some extra helpers): http://jsfiddle.net/taswyn/cv6m76m7/
(You'll obviously need to set height and width appropriately, this was just a quick example using your shape. Note the use of SVG CSS to apply the color on the arrow, which this method allows)
Tested in IE 10 using IE 9 and 10 browser modes (and tested in Chrome). Probably won't work in 8 and below.
If you do need to clip against text, you'll need to use SVG text instead of HTML text elements.
Aside: If all you need to do is clip in a rectangle, you could temporarily use clip CSS, which is cross-browser compatible but deprecated, until the masking module hits recommendation status and clip-path becomes available for use on HTML as a W3C standard. (obviously this doesn't apply to your situation, but it may help someone else)

Related

Transform attribute applied to SVG <symbol> works in Firefox, but not in Chrome

I have an SVG icon I want to reuse, and would like to transform it first before doing so. Here is a simplified version of the issue I'm facing:
svg {
width: 100px;
height: 100px;
background: blue;
}
.circle {
fill: green;
transform: scale(3)
}
<svg viewBox="0 0 200 200">
<symbol id="circle" transform="scale(2)" class="circle">
<circle cx="50" cy="50" r="50" />
</symbol>
<use href="#circle"/>
</svg>
The green circle is properly sized in Firefox, whether I use inline styling or a class, but in Chrome, the fill attribute is applied, but not transform, class or inline, it remains small. A comparison screenshot:
Of course, I could work around it by applying transformations to each <use> element, but I'd like to understand why it doesn't work, because in the MDN docs, the <symbol> page lists transform as a legal attribute.
Perhaps the issue is that transform is not inherited, but it still works in Firefox, so maybe the problem lies elsewhere.
As Robert Longson pointed out in the comments, <symbol> elements supporting the transform property is a new SVG 2 feature that hasn't made its way to Chrome yet.

How to use css backdrop-filter on text?

I'm trying to recreate this effect from Apples Aracde site:
https://www.apple.com/apple-arcade/
Look at the "Play Extraordinary" text, it's got a backdrop filter applied and blurs the video behind it.
I can see they are using an SVG as an mask to clip the background, but I can't seem to do the same, the text comes out stretched or upside down.
Could anyone show me how to use text as an SVG mask to cut out the div/element with a backdrop filter on it?
Screenshot of the item in question:
https://i.imgur.com/WHzO8Yj.png
As far as I know there's no way to directly apply the backdrop-filter:blur to a text element.
First solution: The Slowest One (Broken by chrome update)
Create a container
Apply a background to it (or to its ::before pseudo-element)
Use the filter:blur so that the container's background is blurred
Apply a svg mask onto the svg element and then apply the same background to the container (or to its ::before pseudo-element)
This way we have the blurried background on top that gets masked and the non-blurry version under it.
NOTE: applying the background to the container's ::before pseudo element will allow you to modify the background without touching the svg mask (usefull if you need to flip the background to create more contrast but you can't modify the original image).
Second solution: The Fastest One
Create a container
Apply a background to it
Create a svg element which will represent our "text"
Apply the backdrop-filter:blur to the svg element
Apply the svg-mask to the svg element
This way we have the effect we would have if the backdrop-filter: blur could be applied to text.
This one is the one which performs the best because it's the only method that doesn't require the svg element to duplicate the background (which would have to be repainted at every frame because of the background-attachment:fixed attribute).
Third solution: The Most Compatible One (Broken by chrome update)
(requires to have 2 copies of the background, one of which already blurred)
Create a container
Apply a background to it
Create a svg element which will represent out "text"
Apply the blurry version of the background to the svg element
Apply the svg-mask to the svg element
Great! But the contrast is low...
Let's add a shadow then!
Applying the blur effect alone will give us a low contrast-ratio (hard to read text).
To counter this I applied a shadow to the svg:
Create a svg element in the document
Inside the <defs> tag create a filter with the <filter> tag and give it a unique id
Inside the <filter> tag create a <feGaussianBlur> with a stdDeviation of your choice (4 and 5 are good initial numbers)
Still inside the <filter> tag, create a <feComposite> with the out operator and in2 set to SourceGraphics
To shape our shadow we'll use an <image> outside of the <defs> tag
Set the url of the <image>'s filter attribute to the same id you gave to the <filter> tag (see point 2 above)
Set the xlink:href attribute's value to the same one of your svg's path
This is the reference code:
<svg>
<defs>
<filter id = "trans-shadow">
<feGaussianBlur stdDeviation = "5"/>
<feComposite operator = "out" in2 = "SourceGraphic"/>
</filter>
</defs>
<image filter = "url(#trans-shadow)" x = "0" y = "0" width = "100%" height = "100%" xlink:href = "./SVG.svg" />
</svg>
Live DEMO: https://cristiandavideconte.github.io/applyBackdropFilterBlurToText/
Source Code: https://github.com/CristianDavideConte/applyBackdropFilterBlurToText
I'll leave you a code snippet which contains the first 2 solutions (one is commented) so you can choose which one fits you better:
<html>
<head>
<style>
html,body {
margin: 0;
/* UNCOMMENT THIS PART TO TRY OUT THE NON-REVERSED VERSION
background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg) 0 0;
background-repeat: no-repeat;
background-attachment: fixed;
*/
}
/* DELETE THE ::before TO TRY OUT THE NON-REVERSED VERSION */
.container::before {
content: "";
z-index: -1;
position: absolute;
width: 100vw;
height: 200vh;
background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg) 0 0;
background-repeat: no-repeat;
background-attachment: fixed;
transform: rotateY(180deg);
}
.container {
width: 100vw;
height: 200vh;
display: flex;
align-items: center;
}
.svg {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
/* DELETE THIS 4 LINES TO TRY OUT THE NON-REVERSED VERSION */
filter: blur(20px) saturate(180%);
background: url(https://wallpaperhd.wiki/wp-content/uploads/wallpapers-1920x1080-5ae1cd66635d3.jpg);
background-repeat: no-repeat;
background-attachment: fixed;
/* UNCOMMENT THIS PART TO TRY OUT THE NON-REVERSED VERSION
backdrop-filter: blur(20px) saturate(180%);
*/
/* Chrome, Safari and all webkit browsers */
-webkit-mask-image: url(./SVG.svg);
-webkit-mask-size: contain;
-webkit-mask-position: center;
-webkit-mask-repeat: no-repeat;
-webkit-mask-border: url(./SVG.svg) 25;
/* FIREFOX */
mask-image: url(./SVG.svg);
mask-size: contain;
mask-position: center;
mask-repeat: no-repeat;
mask-border: url(./SVG.svg) 25;
}
</style>
</head>
<body>
<section class = "container">
<div class = "svg"></div>
</section>
</body>
</html>
In order for this snippet to work you need the svg mask to be called SVG.svg and it has to be placed in the same folder as your html file.
And remember you cannot access an svg file for your mask's url from local storage, you need a server (node.js is fine).
Here you have 2 screenshots of the possible outcomes:
Method 3 - no shadows:
Method 2 - with shadows:

Chrome SVG background image aliasing bug?

I've been using an SVG background image on a textarea element to provide line numbering for the text displayed in the text area (the line numbers in the following images are from an SVG background image).
However, with Chrome 60.0.3112.113 on Windows 7 I get jagged SVG Display:
As I found out by fiddling, when I edit the style properties of the svg element to include opacity: 0.99, it renders as would be expected (and as Chrome did before):
The HTML code to reproduce this is as follows (change opacity to 0.99 to see the difference):
<!DOCTYPE html>
<html>
<title>SVG background image opacity/aliasing bug</title>
<style>
#ta {
font-size: 16px;
width: 100%;
height: 100%;
padding-left: 40px;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" style="fill: red; opacity: 1.0"><text x="4" y="20">0001</text><text x="4" y="38">0002</text><text x="4" y="56">0003</text></svg>')
}
</style>
<body>
<textarea id="ta" cols="40" rows="4">Line 1
Line 2
Line 3</textarea>
</body>
</html>
If I just place the SVG code into a separate file and open it as plain SVG file (rather than as background in a data-URI) using Chrome it displays as expected.
So while there's the opacity: 0.99 workaround, I'd like to know why Chrome renders this simplistic SVG incorrectly, or if there's a better workaround, or if there's something fundamentally wrong with the aproach I'm using.

Apply an SVG filter to a div's background-color

I have a <div> that has a background-color sitting in front of an image. I'm trying to apply a multiply effect using an SVG so that the background image behind the div comes through:
<svg>
<filter id="multiply">
<feBlend mode="multiply"/>
</filter>
</svg>
Unfortunately, only the solid background color is being changed, and I get no transparency through to the background.
Here's the fiddle: https://jsfiddle.net/0p58bxsp/1/
The effect I'm expecting is something like this:
I know the visual effect could be fudged using an rgba value as the background color, but I'm very specifically looking for the combination of a solid color having a multiply filter applied to it.
Is this a limitation of the current SVG implementation?
Here's the definition of a multiply blend:
Multiply blend mode multiplies the numbers for each pixel of the top layer with the corresponding pixel for the bottom layer. The result is a darker picture. , where a is the base layer value and b is the top layer value.
As such, using opacity or alpha doesn't give me the exact result that I'm looking for.
This was supposed to be possible if you stayed completely within SVG 1.1 by using the BackgroundImage pseudo input - but only IE10 ever supported it for inline SVG (Opera supported it for .svg files). Firefox, Chrome & Safari never supported it, and it's now formally declared "not to be implemented" by folks who work on those browsers.
You can import a copy of the background image using feImage and position it just right to match the actual background exactly. But depending on your design - that could take extensive javascript. And url() filters can behave strangely. https://jsfiddle.net/0p58bxsp/3/ shows how to do this - but it also surfaces a regression bug in Chrome with positioned primitives which will be fixed in next Chrome.
<div id="background">
<div id="effect">
Effect goes here
</div>
</div>
<svg width="100%" height="100%" viewBox="0 0 200 200">
<defs>
<filter id="multiply" x="0%"
y="0%" height="300%" width="300%">
<feImage x="0" width="400" height="400" y="0" preserveAspectRatio="xMaxYMax meet" xlink:href="http://lorempixel.com/400/400/" />
<feOffset dx="-100" dy="-100"/>
<feBlend mode="multiply" in="SourceGraphic"/>
</filter>
</defs>
</svg>
Safari 9(and only Safari 9) has a "backdrop-filter" that will do this, and you can also specify a mix-blend-mode which has broader support, but this is still pretty edge.
If you need a multiply blend, it might be best to just keep everything in SVG.
You should add opacity: 0.4; into effect class. It will work fine.
#effect {
color: #fff;
height: 200px;
margin: 100px 0 0 100px;
width: 200px;
opacity: 0.4;
background-color: #3d3934;
filter: url(#multiply);
-webkit-filter: url(#multiply);
-moz-filter: url(#multiply);
}
As far as I know, svg effects are limited to the elements itself. You can't use it to mix with another element.
You can however get this effect with standard CSS mix-blend-mode
#background {
background-image: url(http://lorempixel.com/400/400/);
height: 400px;
padding: 1px;
width: 400px;
}
#effect {
color: #fff;
height: 200px;
margin: 100px 0 0 100px;
width: 200px;
background-color: gray;
mix-blend-mode: multiply;
}
<div id="background">
<div id="effect">
Effect goes here
</div>
</div>

How to create a frosted glass effect using CSS?

I'd like to create a div that is fixed in one position and make it translucent - making the contents behind it partially visible and blurred. The style I'm looking for is similar to the div of the 'See All' thumbnails in the Apple website.
The only thing I can do is adjust opacity: 0.9 but I cannot blur the contents that go under the div.
Note: The div has a fixed position and the background scrolls. The background that scolls is a mix of text and photos.
CSS
CSS 3 has a blur filter (only webkit at the moment Nov 2014):
-webkit-filter: blur(3px); /*chrome (android), safari (ios), opera*/
IE 4-9 supports a non-standard filter
filter:progid:DXImageTransform.Microsoft.Blur(PixelRadius='3')
See some nice demo for the blur and other filters here.
For future reference here is the compatibility table for CSS filter. Firefox seems to be getting the feature in v35+ while even IE11 does not seem to have any compatibility.
SVG
An alternative is using svg (safe for basically IE9 and up):
filter: url(blur.svg#blur);
SVG:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter id="blur">
<feGaussianBlur stdDeviation="3" />
</filter>
</svg>
jsFiddle Demo
Javascript
You will achieve the highest browser compatibility with javascript, but usually the slowest performance and added complexity to your js.
http://www.blurjs.com/ (jquery plugin, canvas solution so IE9+, FF, Chrome support)
http://nbartlomiej.github.io/foggy/ (jquery plugin IE8+, FF,Chrome support)
You can use CSS image filter.
-webkit-filter: blur(2px);
filter : blur(2px);
More info on CSS image filters:
http://techstream.org/Web-Design/CSS3-Image-Filters
http://html5-demos.appspot.com/static/css/filters/index.html
Demo: JSFIDDLE
But in fact, they are using pre processed JPG, and just using it as a overlay in the correct position.
#background {
position: absolute;
left: 10px;
top: 10px;
width: 600px;
height: 600px;
background-image: url(http://images.apple.com/home/images/osx_hero.jpg);
background-position: 0 0;
}
#blur {
position: absolute;
left: 50px;
top: 50px;
width: 120px;
height: 500px;
background-image: url(http://images.apple.com/home/images/osx_hero_blur.jpg);
background-position: -50px -50px;
}
<div id="background">
<div id="blur"></div>
</div>
Demo: JSFIDDLE
You made me want to try, so I did, check out the example here:
http://codepen.io/Edo_B/pen/cLbrt
Using:
HW Accelerated CSS filters
JS for class assigning and arrow key events
Images CSS Clip property
That's it.
I also believe this could be done dynamically for any screen if using canvas to copy the current dom and blurring it.
This should be coming browsers in the future as a CSS filter called backdrop-filter. There's virtually no support for it at all currently. For browser support see: http://caniuse.com/#feat=css-backdrop-filter
This CSS filter will do the frosted glass without any funny business, or hacks. It'll just do it.
Someone recorded a demo of it on Vine, and it looks really good. They were using Safari nightly to get access to the CSS filter. https://vine.co/v/OxmjlxdxKxl
Just put the same image (or parts of it) with opacity .9 a few pixels left/right/up/down - voilĂ 
Some browsers support the new CSS property backdrop-filter. This property enables you to add a "frosted glass-like" effect on an element without using the pseudo classes.
Example:
element {
background: rgba(255, 255, 255, .5);
backdrop-filter: blur(10px);
}
https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter
First of all the OP states that the background scrolls. None of the available answers really allow scrolling. Based on how html is set up it is impossible. But with the use of famous/angular one can have multiple rendering engines to achieve this affect. I have it constructed here.
The idea behind it is two renderings of the site. One is the header version which is blurred. The other is the body. I used Famous/Angular and use templating to render the template in the head and body. The header needs an offset for the height of the header so that things match up. I will be having actual code posted soon here and on the site.