Blend mode on svg image - css

Why blend mode works on a normal image (img tag) but not inside an svg (image tag)?
Look at the example below to understand what I'm trying to achieve (I also want to keep the background clipped like the first image):
.image-wrapper {
width: 100%;
background: #70C053;
}
.image-wrapper image {
filter: grayscale(100%);
mix-blend-mode: multiply;
}
img {
width: 100%;
height: auto;
filter: grayscale(100%);
mix-blend-mode: multiply;
}
<div class="image-wrapper">
<svg viewBox="0 0 250 250" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="user-space" clipPathUnits="userSpaceOnUse">
<path fill="#FF0066"
d="M49.5,-65.4C58.2,-51.8,55.1,-30.5,54.2,-12.9C53.4,4.7,54.7,18.5,49.1,28.6C43.6,38.6,31.1,44.8,17.6,50.9C4.1,57,-10.5,62.8,-22.5,59.5C-34.5,56.1,-44.1,43.5,-53.7,29.7C-63.3,15.8,-73,0.6,-73.4,-15.7C-73.8,-32,-65,-49.4,-51.2,-62.2C-37.4,-75,-18.7,-83.1,0.9,-84.1C20.4,-85.2,40.9,-79.1,49.5,-65.4Z"
transform="translate(100 100)"></path>
</clipPath>
</defs>
<image width="100%" height="auto" preserveAspectRatio="xMinYMin slice" xlink:href="https://source.unsplash.com/random"
clip-path="url(#user-space)"/>
</svg>
</div>
<div class="image-wrapper">
<img src="https://source.unsplash.com/random">
</div>

The MDN docs have an example.
See here: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode#using_mix-blend-mode_with_svg

Related

I can't frame this image inside an SVG

I want to wrap this
inside
to achive a result similar to
(source: i.ibb.co)
it is to say, the t-shirt should be cropped inside the cloud, following its path.
I tried to use a CSS border mask, but I was not successful:
.wrapper {
background-image:url('https://svgshare.com/i/T9J.svg');
background-repeat:no-repeat;
background-size:200px;
background-position:50% 50%;
width:200px;
}
.svg-border-mask {
-webkit-mask-box-image: url('https://svgshare.com/i/T9J.svg');
mask-border: url('https://svgshare.com/i/T9J.svg');
}
<div class="wrapper">
<img src="https://i.stack.imgur.com/2GKtb.png" alt="" class="svg-border-mask" />
</div>
How can I do it? I read about the clip-path way too, but I don't know how to draw this SVG path...
Use mask not mask-border and apply the same properties as the background to have a perfect matching:
.wrapper {
background-image:url('https://i.ibb.co/KjmqTs2/cloud.png');
background-repeat:no-repeat;
background-size:200px;
background-position:50% 50%;
-webkit-mask: url('https://i.ibb.co/KjmqTs2/cloud.png');
-webkit-mask-repeat:no-repeat;
-webkit-mask-size:200px;
-webkit-mask-position:50% 50%;
width:200px;
}
img {
max-width:100%;
}
<div class="wrapper">
<img src="https://i.stack.imgur.com/2GKtb.png" alt="" class="svg-border-mask" />
</div>
You can also simplify like below:
img {
--m:url('https://i.ibb.co/KjmqTs2/cloud.png') center/contain no-repeat;
background:var(--m);
-webkit-mask: var(--m);
width:200px;
padding:0 20px; /* some padding to control the shape */
}
<img src="https://i.stack.imgur.com/2GKtb.png" >
<img src="https://i.stack.imgur.com/2GKtb.png" style="width:100px;padding:0">
<img src="https://i.stack.imgur.com/2GKtb.png" style="width:100px;padding:0 30px">
A good reference is https://stackoverflow.com/questions/3796025/fill-svg-path-element-with-a-background-image but as I was new to this too I have seen how it works by taking the cloud SVG image given in the question and combining it with the given tshirt image.
Look at the code in this snippet which defines an img and uses it instead of the fill color on the first path in the given SVG. I've put it all inline so it's possible to see what is going on.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342.33 210.05">
<defs>
<style>.cls-1{fill:#00ffff;}.cls-2{fill:#d1d1d1;}</style>
<pattern id="img1" patternUnits="userSpaceOnUse" width="342.33" height="210.05">
<image href="https://cdn.shopify.com/s/files/1/0520/4063/0437/products/img9_be295193-87ac-4d81-a55d-2353cbf5621d_250x.png" x="0" y="0" width="342.33" height="210.05" />
</pattern></defs>
<g id="Capa_2" data-name="Capa 2">
<g id="Capa_1-2" data-name="Capa 1">
<g id="Fill_24" data-name="Fill 24">
<path d="M337.32,112.06A56.17,56.17,0,0,1,320.21,152a50.61,50.61,0,0,1-58.44,9l-3-1.52-.6,3.3c-4.05,22.46-22.82,38.38-44.58,37.92-16.41-.37-31.29-10.12-38.84-25.47l-2.86-5.81-1.79,6.23C165,193.48,146.93,206.38,129,204.93c-19.83-1.65-37.72-17.08-43.53-37.59l-1.39-4.5-3,3.67a42.48,42.48,0,0,1-23.59,14.76A41.38,41.38,0,0,1,25.05,175a45.35,45.35,0,0,1-19-28.71A46.93,46.93,0,0,1,11.89,112C21.13,96.84,38,88.9,54.89,91.73l4.63.78-1.94-4.28A40,40,0,0,1,59.7,51,35.88,35.88,0,0,1,82.8,34.33a34.66,34.66,0,0,1,27,5.27,37.65,37.65,0,0,1,13.26,15.85l3.18,7.14,1.55-7.66C133.35,27.57,157.66,6.12,184.33,5c30.07-1.19,59.39,18.76,71.34,48.54.78,1.82,1.43,3.65,2.16,5.84l.92,2.76,2.59-1.33a50.69,50.69,0,0,1,24.07-5.54C314.53,56,337.82,81.42,337.32,112.06Z" fill="url(#img1)" />
<path class="cls-2" d="M285.52,50.32a55.83,55.83,0,0,0-23.87,4.84c-.42-1.17-.87-2.35-1.36-3.5C247.58,20,216.27-1.21,184.13.05c-26.82,1.08-51.42,21.11-59.63,47.59a42.77,42.77,0,0,0-11.91-12.18,39.6,39.6,0,0,0-30.85-6,40.87,40.87,0,0,0-26.31,19,45.08,45.08,0,0,0-4,37.9C34,85,17.15,93.76,7.62,109.36a52,52,0,0,0-6.47,38,50.21,50.21,0,0,0,21.08,31.82,46.34,46.34,0,0,0,36.46,7A47.49,47.49,0,0,0,82.1,173c7.49,20.28,26.05,35.21,46.53,36.92,1.09.08,2.18.13,3.27.13,17.51,0,34-11.27,41.12-27.78a49.24,49.24,0,0,0,40.47,23.34c23.2.57,43.32-15.65,48.94-38.85a56.69,56.69,0,0,0,21.07,4.67,55.84,55.84,0,0,0,40.18-15.88,61.15,61.15,0,0,0,18.64-43.41c0-.35,0-.69,0-1C342.33,78.18,317.05,51,285.52,50.32Zm-1.9,116.11a51.31,51.31,0,0,1-21.85-5.51l-3-1.52-.6,3.3c-4.05,22.46-22.82,38.38-44.58,37.92-16.41-.37-31.29-10.12-38.84-25.47l-2.86-5.81-1.79,6.23C165,193.48,146.93,206.38,129,204.93c-19.83-1.65-37.72-17.08-43.53-37.59l-1.39-4.5-3,3.67a42.48,42.48,0,0,1-23.59,14.76A41.38,41.38,0,0,1,25.05,175a45.35,45.35,0,0,1-19-28.71A46.93,46.93,0,0,1,11.89,112C21.13,96.84,38,88.9,54.89,91.73l4.63.78-1.94-4.28A40,40,0,0,1,59.7,51,35.88,35.88,0,0,1,82.8,34.33a34.66,34.66,0,0,1,27,5.27,37.65,37.65,0,0,1,13.26,15.85l3.18,7.14,1.55-7.66C133.35,27.57,157.66,6.12,184.33,5c30.07-1.19,59.39,18.76,71.34,48.54.78,1.82,1.43,3.65,2.16,5.84l.92,2.76,2.59-1.33a50.69,50.69,0,0,1,24.07-5.54c29.12.65,52.41,26.11,51.91,56.75A56.17,56.17,0,0,1,320.21,152,51,51,0,0,1,283.62,166.43Z"/>
</g>
</g>
</g>
</svg>

SVG ClipPath: Why does applying the clip path to a DIV have different results to an IMAGE?

I need to create a set of 3 triangles that each have content in them (images, copy, etc).
I have setup this Pen to show roughly what I'm trying to achieve: https://codepen.io/andystent/pen/OJyNdmB
And here is an image for quick reference:
In this example the "Top" and "Left" triangles are IMAGES with the clip-path applied and displaying perfectly.
The "Right" triangle (with the red background) is a DIV with the clip-path applied but the proportions are wrong.
It should look like a mirrored version of the "Left" triangle.
When I apply it to an image it is perfect but when I apply to the div it is not. What is the best way to do this?
I am new to SVG so it is extremely likely that I am not doing this correctly. I have looked at numerous posts and the method I have tried is from a few of those but without success... so now I'm reaching out to you geniuses...
Here's the HTML and CSS for the red "Right" triangle with the clip applied to the DIV in the CSS:
#right-wrapper {
position: absolute;
width: 50%;
height: 100%;
right: 0;
padding: 40px 20px;
box-sizing: border-box;
}
#right-content-div {
background-color: red;
height: 100%;
width: 100%;
position: absolute;
top: 0;
right: 0;
clip-path: url(#clip-path-right);
-webkit-clip-path: url(#clip-path-right);
display: flex;
justify-content: center;
align-items: center;
}
<div id="right-wrapper">
<svg width="100%" height="100%" viewBox="0 0 1220 1214" preserveAspectRatio="none">
<defs>
<clipPath id="clip-path-right">
<path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" id="path-1">
</path>
</clipPath>
</defs>
<div id="right-content-div" preserveAspectRatio="none">
<h1>test heading</h1>
</div>
<!-- <image clip-path="url(#clip-path-right)" height="100%" width="100%" preserveAspectRatio="none" xlink:href="https://www.w3schools.com/css/klematis_big.jpg" /> -->
</svg>
</div>
----- UPDATE: -----
As suggested in the comments, I have created a simplified Pen that gets to the heart of what I'm trying to achieve and the embedded HTML and CSS is below.
Essentially I am trying to get the red <div> to be clipped exactly like the <image>.
https://codepen.io/andystent/pen/RwWRjLd
#right-content-div {
background-color: red;
height: 100%;
width: 100%;
position: absolute;
top: 0;
clip-path: url(#clip-path-right);
-webkit-clip-path: url(#clip-path-right);
}
<svg width="20%" height="20%" viewBox="0 0 1220 1214">
<defs>
<clipPath id="clip-path-right">
<path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" id="path-1">
</path>
</clipPath>
</defs>
<image clip-path="url(#clip-path-right)" height="100%" width="100%" preserveAspectRatio="none" xlink:href="https://www.w3schools.com/css/klematis_big.jpg" />
</svg>
<div id="right-content-div" preserveAspectRatio="none">
<h1>test heading</h1>
</div>
Here is an idea where I will be using mask instead of clip-path. The main trick to correctly set the viewBox (you already have it in your code) add preserveAspectRatio="none" then have a mask size of 100% 100%
.box {
width:200px;
height:200px;
display:inline-block;
background:red;
}
.mask {
-webkit-mask:url('data:image/svg+xml;utf8,<svg preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1220 1214"> <path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" /> </svg>') 0 0/100% 100%;
mask:url('data:image/svg+xml;utf8,<svg preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1220 1214"> <path d="M1232,1212.58943 L1232,4.82844551 C1232,3.17159126 1230.65685,1.82844551 1229,1.82844551 C1228.53907,1.82844551 1228.08435,1.93465364 1227.67111,2.13882722 L18.145562,599.743544 C13.1941115,602.189966 11.1633848,608.187127 13.6098071,613.138577 C14.582638,615.107544 16.1765951,616.701501 18.145562,617.674332 L1227.67111,1215.27905 C1229.15654,1216.01298 1230.95569,1215.40376 1231.68962,1213.91832 C1231.89379,1213.50508 1232,1213.05036 1232,1212.58943 Z" /> </svg>') 0 0/100% 100%;
}
<div class="box mask"></div>
<div class="box mask" style="width:300px;"></div>
<div class="box mask" style="height:300px;"></div>
<img src="https://i.picsum.photos/id/1074/200/200.jpg" class="mask">

Scale SVG clipPath and keep aspect ratio of Image

I have an image inside of an SVG element with a clipPath.
I want the clip path to behave like it is in my codePen https://codepen.io/celli/pen/rNBvmyx with preserveAspectRatio="none" so that I always get the same height for my clipPath which matches the parent and stretch from edge to edge of my browser.
The issue is that I want my image to preserve it's aspect-ratio and not appear squashed, while maintaining that the mask is the only element that is being squeezed and not preserving it's aspect ratio.
I tried adding css to the image to preserve the aspect ratio, but it seems to follow the SVGs preserveAspectRatio="none", but I only want that to apply to my clipPath part of the SVG.
<div id="containerId">
<svg class="svg-graphic" preserveAspectRatio="none" viewBox="0 0 1920 1080" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="auto">
<g>
<clipPath id="svgmask">
<polygon points="0,0 0,650 1920,1045 1920,394 "/>
</clipPath>
</g>
<image clip-path="url(#svgmask)" style="width:100%; height:auto; max-width:100%;" xlink:href="https://img-fotki.yandex.ru/get/5607/5091629.6b/0_612e6_b9039c0d_M.jpg" />
</a>
</svg>
</div>
A solution to your problem would be clipping a div with the image as a background. In this case you use a path instead of a polygon where the coords values are from 0 to 1 and clipPathUnits="objectBoundingBox". This won't work on IE and on Edge: https://caniuse.com/#feat=css-clip-path
*{margin:0;
padding:0;}
#containerId {
width: 100%;
height: 800px;
background-color: green;
}
#media (max-width: 800px) {
#containerId {
width: 100%;
height: 500px;
background: orange;
}
}
.img {
width: 100%;
height: 100%;
background-image: url("https://img-fotki.yandex.ru/get/5607/5091629.6b/0_612e6_b9039c0d_M.jpg");
background-size: cover;
-webkit-clip-path: url(#svgmask);
clip-path: url(#svgmask);
}
<svg height="0" width="0" style="position:absolute;">
<defs>
<clipPath id="svgmask" clipPathUnits="objectBoundingBox">
<path d="M0,0 L0,0.6 1,1 1,0.4"/>
</clipPath>
</defs>
</svg>
<div id="containerId">
<div class="img"></div>
</div>
I found an alternative way to do it that works in IE, without SVG, in-case anyone is interested: https://codepen.io/celli/pen/KKPReKE I wanted to use SVG, but this way seems to be the best solution by using a pseudo element and a rotated div.
<div id="head">
<div id="headAddBkgColor"></div>
</div>
<div id="slantElm"></div>

Can anyone explain why firefox crops this SVG image?

Can anyone explain why firefox crops this SVG image?
It's within a container and being scaled to fit by CSS.
I'm using <symbol> and <use>.
.container {
width: 1em;
height: 1em;
}
svg {
width: 100%;
height: 100%;
}
<svg style="display:none">
<symbol id="icon_triangleup" xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24">
<path d="M12.8,5.4c-0.377-0.504-1.223-0.504-1.6,0l-9,12c-0.228,0.303-0.264,0.708-0.095,1.047 C2.275,18.786,2.621,19,3,19h18c0.379,0,0.725-0.214,0.895-0.553c0.169-0.339,0.133-0.744-0.095-1.047L12.8,5.4z" />
</symbol>
</svg>
<div class="container">
<svg>
<use xlink:href="#icon_triangleup"></use>
</svg>
</div>
I can tell you why, as in, how to fix it. But not why Chrome seems to ignore what's causing the issue in Firefox.
Firefox is using the 24px width and height set on the <symbol> element, so remove those and the symbol will expand to fill the space of it's container.
You can always set the width and height on the <use> element if you want the individual instances of the symbol to be different sizes.
.container {
width: 1em;
height: 1em;
}
svg {
width: 100%;
height: 100%;
}
<svg style="display:none">
<symbol id="icon_triangleup" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12.8,5.4c-0.377-0.504-1.223-0.504-1.6,0l-9,12c-0.228,0.303-0.264,0.708-0.095,1.047 C2.275,18.786,2.621,19,3,19h18c0.379,0,0.725-0.214,0.895-0.553c0.169-0.339,0.133-0.744-0.095-1.047L12.8,5.4z" />
</symbol>
</svg>
<div class="container">
<svg>
<use xlink:href="#icon_triangleup"></use>
</svg>
</div>

image cropped as a triangle on webpage

This is a real css-challenge, I don't think this is possible:
I've made some white css triangles. and when you hover on a triangle, the white triangle should change in a photo also cropped like a triangle. I've made a jsfiddle for it:
fiddleLink
Any help appreciated
You can use svg to achieve this effect: http://jsfiddle.net/xTd6Y/4/
<div id="image-wrapper">
<svg id="svg-1" class="clip-svg">
<rect class='svg-background' width="300" height="300" fill="#ffffff" />
<image id="img-1" class='svg-image' width="300" height="300" xlink:href="http://lorempixel.com/300/300" />
</svg>
<svg id="svg-2" class="clip-svg">
<rect class='svg-background' width="300" height="300" fill="#ffffff" />
<image id="img-2" class='svg-image' width="300" height="300" xlink:href="http://lorempixel.com/300/301" />
</svg>
<svg id="svg-3" class="clip-svg">
<rect class='svg-background' width="300" height="300" fill="#ffffff" />
<image id="img-3" class='svg-image' width="300" height="300" xlink:href="http://lorempixel.com/300/302" />
</svg>
</div>
<svg id="svg-defs">
<defs>
<clipPath id="clip-triangle">
<polygon points="0, 200 100, 0 200, 200"/>
</clipPath>
</defs>
</svg>
css
body {
background-color: #e0e0e0;
}
#image-wrapper {
position: relative;
}
.svg-background, .svg-image {
clip-path: url(#clip-triangle);
}
.svg-image {
visibility: hidden;
}
.clip-svg .svg-image:hover {
visibility: inherit;
}
/* size and positioning */
svg.clip-svg {
position: absolute;
height: 250px;
width: 250px;
}
#svg-1 {
top: 110px;
left: 50px;
}
#svg-2 {
top: 40px;
left: 140px;
}
#svg-3 {
top: 160px;
left: 250px;
}
The clipping path is defined in svg#svg-defs, and can be set to whatever you like.
Image attributes are visible to / accessible by js and css.
You can apply the clipping path to any html element with css of
myElement {
clip-path: url(#clip-triangle);
}
but this is only reliable on firefox so far as I can tell.
Note: solution only tested on FF and chrome
note: small edit to move :hover from the svg to the embedded image, to correct problem with hover triggered outside clip area

Resources