Adding clip-path to svg image element that has extra vertical space - html

I'm having trouble controlling the clip-path coordinates on an image element in a responsive inline svg. Here is my code example (jsfiddle: http://jsfiddle.net/tbbtester/4XP4w/):
CSS:
ul{margin:0;padding:0;list-style:none;height:510px;position: relative;width:1140px;}
li{margin:0;padding:0;position:absolute;background:blue;width:40.1754386%;height:52.15686275%;overflow:hidden;top:0;left:0;}
svg{height: 100%;display:block;width: 100%;position: absolute;top:0;left:0;}
image{clip-path: url(#promo5-1-image);}
HTML:
<ul>
<li>
<svg viewBox='0 0 100 87.59398496' preserveAspectRatio="xMidYMid slice" xml:space="preserve">
<defs>
<clipPath id="promo5-1-image">
<polygon points="0,0 100,0 100,70 0,87.59398496" />
</clipPath>
</defs>
<image preserveAspectRatio="xMinYMid meet" x="0" y="0" width="100" height="87.59398496" xlink:href="http://svgtest.tbb.dev.novicell.dk/test.jpg" src="http://svgtest.tbb.dev.novicell.dk/test.jpg" overflow="visible" />
</svg>
</li>
</ul>
The entire image is visible, nothing has been cut off. But the image element is actually larger than the displayed area - it seems that unnecessary space is added above and below the image, and it causes problems when I want to add a clip-path to it since the point 0,0 starts outside the visible area. (You can see the extra space if you click the image element in the dom in the browsers developer tools)

Ok, I found the solution. The problem was mainly that I used a wrong way of calculating the coordinates of the svg and its elements. Solution fiddle: http://jsfiddle.net/tbbtester/4XP4w/1/
CSS:
ul{margin:0;padding:0;list-style:none;width:100%;height:510px;position: relative;width:1140px;}
li{margin:0;padding:0;position:absolute;background:blue;width:40.1754386%;height:52.15686275%;overflow:hidden;top:0;left:0;}
svg{height: 100%;display:block;width: 100%;position: absolute;top:0;left:0;overflow:hidden;}
image{clip-path: url(#promo5-1-image);}
HTML:
<ul>
<li>
<svg viewBox='0 0 100 58.07860262' preserveAspectRatio="none">
<defs>
<clipPath id="promo5-1-image">
<polygon points="0,0 100,0 100,50.87336245 0,58.07860262" />
</clipPath>
</defs>
<image x="0" y="0" width="100" height="58.07860262" xlink:href="http://svgtest.tbb.dev.novicell.dk/test.jpg" src="http://svgtest.tbb.dev.novicell.dk/test.jpg" />
</svg>
</li>
</ul>

Related

Svg image mask cut top and bottom

I need to create images with this shape:
http://imgh.us/image-mask_1.svg
First i try with css mask but the problem was support of browsers. So i jump over to svg image with mask inside.
I have a problem with SVG image where top and bottom part of the mask is cut off.
I have created a codepen to show you the problem:
<svg width="551" height="397" viewBox="0 0 551 397">
<defs>
<mask id="section_mask">
<image x="0.5" y="0.5" width="551" height="397" xlink:href="http://imgh.us/image-mask.svg" />
</mask>
</defs>
<image mask="url(#section_mask)" width="551" height="397" xlink:href="http://imgh.us/kh110512-22049-1-1024x682.jpg" />
</svg>
http://codepen.io/lasse_head/pen/ObJLKN
Thanks Lasse
It happens because the masked image has wrong width/height ratio.
The original image is 1024 x 682. The ration is 1.71788413. So, if you want to have height 397px, the width should be 397 x 1.71788413 = 596px . However, you set it to 551px.That was the reason for cutting.
<svg width="551" height="397" viewBox="0 0 551 397">
<defs>
<mask id="section_mask">
<image x="0.5" y="0.5" width="551" height="397" xlink:href="http://imgh.us/image-mask.svg" />
</mask>
</defs>
<image mask="url(#section_mask)" width="551" height="397" xlink:href="http://imgh.us/kh110512-22049-1-1024x682.jpg" />
</svg>

How to crop a particular area of image with SVG clipping mask

I am doing a clipping mask through SVG clip path. I am using one SVG element with three clipping masking.
Problem is my svg is getting full window width and height, therefore images are also getting full width and height.
So what I want is to move the image inside the clipping path so that I can show the actual area of the image
Here is the Jsfiddle link.
I don't want to change the image's aspect ratio..
please let me know if there is any way for this .
Thanks
If you don't want your images to stretch and break their aspect ratio, then don't use preserveAspectRatio="none". You'll probably want to use one of the "xxx slice" variants. Below I have used different ones for each image in order to have them align to the left, centre and right repectively.
*{padding:0px; margin: 0px;}
html, body {width: 100%; height: 100%;}
<svg version="1.1" id="triagnleSvg" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
xml:space="preserve">
<clipPath id="last" clipPathUnits="objectBoundingBox">
<polygon points="1,0 .78,0 0.58,1 1,1"/>
</clipPath>
<clipPath id="first" clipPathUnits="objectBoundingBox">
<polygon points="0,0 0.4,0 0.218,1 0,1"/>
</clipPath>
<clipPath id="mid" clipPathUnits="objectBoundingBox">
<polygon points="0.4,0 0.78,0 0.58,1 0.218,1"/>
</clipPath>
<image class="topImage" clip-path="url(#mid)" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit3.jpg"/>
<!-- top -->
<image class="leftImage" clip-path="url(#first)" preserveAspectRatio="xMinYMid slice" width="100%" height="100%" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit2.jpg"/>
<!-- right -->
<image class="rightImage" clip-path="url(#last)" preserveAspectRatio="xMaxYMid slice" width="100%" height="100%" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit1.jpg"/>
</svg>
Update
[I am] still unable to get the exact view for the first image. I want to show the girl's face. but its not happening
One solution would be to change your images so that the area of interest is in the desired part of the image.
Otherwise you need to start working with viewBoxes. However, once a viewBox gets involved though, you can no longer stretch the parent SVG to fill the page width and height as per the original example. You'll have to be satisfied with a fixed aspect ratio for the image as a whole.
Here's one way to solve your problem:
*{padding:0px; margin: 0px;}
html, body {width: 100%; height: 100%;}
<svg version="1.1" id="triagnleSvg" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2 1">
<defs>
<clipPath id="mid" clipPathUnits="objectBoundingBox">
<polygon points="0.3,0 1,0 0.7,1 0,1"/>
</clipPath>
</defs>
<image class="leftImage" preserveAspectRatio="xMaxYMid slice" width="1" height="1"
xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit2.jpg"/>
<image class="rightImage" preserveAspectRatio="xMidYMid slice" x="1" width="1" height="1"
xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit1.jpg"/>
<image class="topImage" preserveAspectRatio="xMidYMid slice" x="0.5" width="1" height="1"
xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit3.jpg"
clip-path="url(#mid)"/>
</svg>
You might want to change the x (and maybe the y, too) for your images and apply the opposite translation to their corresponding clipping paths.
<!-- language: lang-html -->
<svg version="1.1" id="triagnleSvg" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" preserveAspectRatio="none"
xml:space="preserve">
<clipPath id="last" clipPathUnits="objectBoundingBox" transform="translate(-200,0)">
<polygon points="1,0 .78,0 0.58,1 1,1"/>
</clipPath>
<clipPath id="first" clipPathUnits="objectBoundingBox" transform="translate(450,0)">
<polygon points="0,0 0.4,0 0.218,1 0,1"/>
</clipPath>
<clipPath id="mid" clipPathUnits="objectBoundingBox">
<polygon points="0.4,0 0.78,0 0.58,1 0.218,1"/>
</clipPath>
<image class="topImage" clip-path="url(#mid)" width="100%" height="100%" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit3.jpg"/>
<!-- top -->
<image class="leftImage" clip-path="url(#first)" width="100%" height="100%" x="-450" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit2.jpg"/>
<!-- right -->
<image class="rightImage" clip-path="url(#last)" width="100%" height="100%" x="200" xlink:href="http://testyourprojects.net/matrix/project/stackoverflowissue/kit1.jpg"/>
</svg>
However, if you are not fixing the minimum and maxumum width and height of the svg or its container, you might show blank parts of the image outside its boundaries. You can set min-height, max-height, min-width, or max-widthon the css for the svg or its container.
Also, since showing the interesting area rather depends on the device/browser width, an extra enhancement would be to automatically compute the exact translations to center the region of interest with a script, depending on the user's width.

Why does svg <use xlink:href="#"/> referencing an element with clip-path not work?

When implementing an SVG sprite, an <svg> element is created and svg elements are referenced via the <use> element. The containing <svg> element is then hidden using style="display: none;"
The clip-Path attribute does not render, but the path does. This leaves my path looking different from how I want it to.
How do I use an svg <use xlink:href="#"/> referencing an element with clip-path?
I used grunt-svg-store to create my svg sprite, but have simplified this example for Q&A format https://css-tricks.com/svg-sprites-use-better-icon-fonts/
<svg id="svg-test" style="display: none;">
<clipPath id="my-clip-1">
<circle id="circle-1" cx="50" cy="50" r="50" />
</clipPath>
<path id="svg-test-reference" clip-path="url(#my-clip-1)" d="M10-39.288h80v80H10z" />
</svg>
<!-- Reference SVG <path> by ID with Use -->
<svg class="svg-item" viewBox="0 0 100 100">
<use xlink:href="#svg-test-reference" />
</svg>
Live example on Codepen.io
Use <svg style="width:0; height:0;"> instead of <svg style="display: none;"> to hide the sprite.
<!-- SVG element -->
<svg id="svg-test" style="width:0; height:0;">
<clipPath id="my-clip-1">
<circle id="circle-1" cx="50" cy="50" r="50" />
</clipPath>
<path id="svg-test-reference" clip-path="url(#my-clip-1)" d="M10-39.288h80v80H10z" />
</svg>
<!-- Reference SVG <path> by ID with Use -->
<svg class="svg-item" viewBox="0 0 100 100">
<use xlink:href="#svg-test-reference" />
</svg>
Live example on Codepen.io
In my case, using only "width" and "height" equals to zero, left a void area where should be the image. However, using display:content; instead display:none; works fine, no void area and no image.

Filling an SVG polygon with an image [duplicate]

Is it possible to set a background-image for an SVG <path> element?
For instance, if I set the element class="wall", the CSS style .wall {fill: red;} works, but .wall{background-image: url(wall.jpg)} does not, neither .wall {background-color: red;}.
You can do it by making the background into a pattern:
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100">
<image href="wall.jpg" x="0" y="0" width="100" height="100" />
</pattern>
</defs>
Adjust the width and height according to your image, then reference it from the path like this:
<path d="M5,50
l0,100 l100,0 l0,-100 l-100,0
M215,100
a50,50 0 1 1 -100,0 50,50 0 1 1 100,0
M265,50
l50,100 l-100,0 l50,-100
z"
fill="url(#img1)" />
Working example

Does element order matter for inline SVG?

In Google Chrome 24, if an element referenced by a <use> element is defined later in the document it isn't rendered. I didn't notice anything related to element order in the documentation for the use element.
Is this behavior undefined and shouldn't be expected to be consistent across browsers or just a bug in Chrome?
An example of this can be seen below (slightly modified from this question). Blue circle renders as expected, red, not so much. Firefox 17 and IE 9 render both circles as I would expect. When the same content is referenced as an external <img />, both circles render as well.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Chrome use-tag bug?</title>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="200px" height="200px" viewBox="0 0 200 200">
<defs>
<g id="test2">
<circle cx="50" cy="50" r="25" fill="blue"/>
</g>
</defs>
<g>
<rect x="0.5" y="0.5" width="199" height="199" stroke="black" fill="none"/>
<use xlink:href="#test1" x="0" y="0"/>
<use xlink:href="#test2" x="0" y="0"/>
</g>
<defs>
<g id="test1">
<circle cx="100" cy="100" r="25" fill="red"/>
</g>
</defs>
</svg>
</body>
</html>
UPDATE: Seems to be working in Chrome 39.
The Rendering Order depends on the element order, so it looks strong like a bug in chrome:
SVG Rendering Order 1.0, Part 2: Language