I'm trying to apply mask to transformed svg element (it's simplified, I'm trying to do it with path, but structure is same). If mask is applied to element outside of transformed group, it works as expected. If I try to do the same inside , element just disappears.
HTML:
<svg width="350pt" height="100pt" >
<defs>
<pattern id="circleFill" patternUnits="userSpaceOnUse" width="5" height="5" >
<circle cx="2" cy="2" r="2" fill="red"></circle>
</pattern>
<mask id="circleMask">
<rect x="0" y="0" width="100%" height="100%" fill="url(#circleFill)" />
</mask>
</defs>
<g transform="translate(0,150) scale(.1,-.1)">
<rect class="holder" x="300" y="300" height="1000" width="1000"/>
<rect class="main t" x="350" y="350" height="400" width="400" />
</g>
<rect x="300" y="50" height="50" width="50" class="main masked o" />
</svg>
CSS:
.holder {
fill: darkgray;
stroke: black;
stroke-width: 2px;
}
.o{ fill: red; }
.t{ fill: purple; }
.masked{ mask: url(#circleMask); }
If I add "masked" class to second rect (with classes "main t"), it just disappears.
The following structure works:
<g class="masked">
<g transform="...">
<rect ... />
</g>
</g>
I can't use it because I have more than 50 elements in image that should have the same transform and only some of them should be masked (and there are 5 different masks).
Here's the fiddle: Fiddle
What I'm doing wrong? Is it possible to mask element inside transformed group?
I have looked at several other answers on Stack:
Responsive SVG Clip Path or Mask Image
Responsive SVG image mask
But none seem to work for me. I have an SVG mask based on a path. I want it to expand to fill all available space (or contract) whilst keeping the aspect ratio of the path.
svg {
width: 100%;
height: 100%;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 237.859 264.582" preserveAspectRatio="xMinYMin meet">
<defs>
<pattern id="triangle-image" patternUnits="userSpaceOnUse" width="3918" height="3918">
<image xlink:href="images/aspirational-photos/christian-buehner-JQFHdpOKz2k-unsplash.jpg" x="0" y="0" width="100%" height="100%" />
</pattern>
<pattern id="triangle-pattern" width="100%" height="100%" patternUnits="userSpaceOnUse">
<path id="triangle-path" d="M237.844,32.946c-0.001-9.981-4.42-19.279-12.121-25.512c-7.82-6.331-17.85-8.78-27.518-6.721
c-3.373,0.717-6.639,1.979-9.707,3.751l-129.11,74.56l-42.942,24.8C6.147,109.771-0.001,120.42,0,132.312
c0,11.892,6.149,22.541,16.449,28.487l84.623,48.833l87.457,50.486c7.179,4.143,15.193,5.435,23.174,3.736
c15.41-3.279,26.166-16.532,26.156-32.222L237.844,32.946z"
fill="#fff" fill-rule="evenodd" width="100%" height="100%" />
</pattern>
<mask id="triangle-mask" width="100%">
<rect x="0" y="0" width="100%" height="100%" fill="url(#triangle-pattern)" />
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#triangle-image)" mask="url(#triangle-mask)"/>
</svg>
The SVG seems to obey the path values no matter what I do. Is there a way to make it expand or contract like an image would?
I've simplified your code in the sense that I'm applying the mask to the image instead of using patterns. Also the mask is the path. I'm not using width="100%" since the width af an svg element will take all the space available i.e 100%.
I would like to understand why you need it height="100%"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 240 265">
<defs>
<mask id="triangle-mask">
<path d="M237.844,32.946c-0.001-9.981-4.42-19.279-12.121-25.512c-7.82-6.331-17.85-8.78-27.518-6.721
c-3.373,0.717-6.639,1.979-9.707,3.751l-129.11,74.56l-42.942,24.8C6.147,109.771-0.001,120.42,0,132.312
c0,11.892,6.149,22.541,16.449,28.487l84.623,48.833l87.457,50.486c7.179,4.143,15.193,5.435,23.174,3.736
c15.41-3.279,26.166-16.532,26.156-32.222L237.844,32.946z"
fill="#fff" />
</mask>
</defs>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" mask="url(#triangle-mask)"/>
</svg>
Alternatively if you need all those patterns please remove width="100%"for the mask in your code.
I'm trying to get a hover effect for some svgs. The code I'm working on is basically icons contained in an svg so they're all positioned on top of a background (it looks like a map - I want individual icons on the map to highlight on hover).
The problem is filters don't seem to have any effect on nested svg elements. I've tried putting the filter directly in the nested element and it doesn't change anything.
Here's a simple example of the code that I would like to work.
.icon:hover{
filter: sepia(100%);
}
<html>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg x="10" class="icon">
<rect x="10" y="10" height="100" width="100" style="fill: #0000ff"/>
</svg>
<svg x="200">
<rect x="10" y="10" height="100" width="100" style="fill: #0000ff"/>
</svg>
</svg>
</body>
</html>
You can use svg filters. The sepiatone filter is from https://gist.github.com/jorgeatgu/5b338cc1a4e0df901348
svg{border:1px solid}
.icon:hover{
filter: url(#sepiatone);
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="sepiatone">
<feColorMatrix type="matrix" values=".343 .669 .119 0 0 .249 .626 .130 0 0 .172 .334 .111 0 0 .000 .000 .000 1 0"/>
</filter>
</defs>
<svg x="10" class="icon">
<rect x="10" y="10" height="100" width="100" style="fill: #0000ff"/>
</svg>
<svg x="200">
<rect x="10" y="10" height="100" width="100" style="fill: #0000ff"/>
</svg>
</svg>
I'm trying to work out a simple svg example - creating bar graph.
However, I don't have clear grasp of how it works. I rotated an existing graph
upside down but seems like there is a small offset. Corresponding jsfiddle here - http://jsfiddle.net/rhvP8/2/
<div style="width:300px;height:300px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="width:100%;height:100%" viewBox="0 0 300 300">
<g>
<rect width="14.55" height="40%" x="0" y="0" fill="black"></rect>
<rect width="14.55" height="20%" x="50" y="0" fill="green"></rect>
<rect width="14.55" height="80%" x="100" y="0" fill="red"></rect>
<rect width="14.55" height="90%" x="150" y="0" fill="yellow"></rect>
<rect width="14.55" height="10%" x="200" y="0" fill="pink"></rect>
<rect width="14.55" height="60%" x="250" y="0" fill="orange"></rect>
</g>
</svg>
</div>
<div style="width:300px;height:300px;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="width:100%;height:100%" viewBox="0 0 300 300">
<g transform="rotate(180)">
<rect width="14.55" height="40" x="-50" y="-300" fill="black"></rect>
<rect width="14.55" height="20" x="-100" y="-300" fill="green"></rect>
<rect width="14.55" height="35" x="-150" y="-300" fill="red"></rect>
<rect width="14.55" height="90" x="-200" y="-300" fill="yellow"></rect>
<rect width="14.55" height="10" x="-250" y="-300" fill="pink"></rect>
<rect width="14.55" height="60" x="-300" y="-300" fill="orange"></rect>
</g>
</svg>
</div>
The thing you need to remember is that the rotate() transform will rotate an object about the coordinates (0,0), which in this case is the top left corner of the graph. Since the graph is 300p wide and 300px tall, rotating through 180° causes the graph to spin off beyond the top left corner. A translate transform can be used to readjust the coordinates so that the drawing appears within the viewbox again. Hopefully this illustration will explain:
Here's an updated JSfiddle with a few other fixes: http://jsfiddle.net/rhvP8/4/
An alternative to squeamish's solution is just to use the version of rotate that takes the rotation origin as well: rotate(angle x y).
Since you know your graph is 300x300, using rotate(180 150 150) works fine.
Demo here
Easy way: the scaleY() CSS function, defines a transformation that resizes an element along the y-axis (vertically).
svg {
transform: scaleY(-1);
}
View browser compatibility here: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/scaleY()#browser_compatibility
I have an SVG image that I would like to keep as a separate file to my main html file. I am trying to make it work as an embed tag but have problems with different view box behaviour.
Below is the code that works as I would like. The viewbox takes up as much space as possible without overflowing the window
<!DOCTYPE html>
<body style="overflow:hidden; margin:0" bgcolor="#E6E6FA">
<div>
<!-- <embed src="example.svg" type="image/svg+xml" /> -->
<svg
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
viewBox="0 0 400 600">
<g stroke-width="2">
<rect height="600" width="400" stroke="#FF0" y="0" x="0" fill="#808080"/>
<rect height="80" width="100" stroke="#808080" y="80" x="40" fill="#F60"/>
<rect height="120" width="160" stroke="#808080" y="250" x="160" fill="#FC0" onclick="alert('one')"/>
</g>
</svg>
</div>
</body>
When I replace this with the embed tag that references this exact same text. The viewbox fills the width so that overflows the vertical dimension of the window.
I have worked out the answer. By moving from a width attribute to setting the width in the style attribute the problem is resolved.
html file contains a div and embed with style set widths.
<body style="overflow:none; margin:0" bgcolor="#E6E6FA">
<div style="height:100%">
<embed src="example.svg" type="image/svg+xml" style="height:100%;width:100%"/>
</div>
</body>
And the SVG file contains the view box
<svg
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
viewBox="0 0 400 600">
<g stroke-width="2">
<rect height="600" width="400" stroke="#FF0" y="0" x="0" fill="#808080"/>
<rect height="80" width="100" stroke="#808080" y="80" x="40" fill="#F60"/>
<rect height="120" width="160" stroke="#808080" y="250" x="160" fill="#FC0" onclick="alert('one')"/>
</g>
There are still some odd behaviours when shrinking the window (it only resizes properly when the width is changed with the height) so if anyone has a better answer I would be keen to hear it