Show hidden rect with text on hover of another poly - css

I need to use pure svg for a project. I know how to get this effect simply with divs but I dont know how to make it work with svg, I dont know what im doing wrong.
I want to show a hidden black rect with white text when you hover on another polygon (and the polygon is 0.1 of opacity normal and changes to 0.8 of opacity on the same hover) Something like a tooltip with opacity and with a nice smooth transition, but pure SVG.
.showme {
opacity: 0.3;
}
.showme:hover {
opacity: 0.8;
}
.desc {
visibility: hidden;
}
.showme:hover + .desc {
visibility: visible;
}
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" >
<rect x="1" y="1" width="998" height="298" fill="blue" class="showme"/>
</svg>
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" class="desc" >
<rect x="1" y="1" width="998" height="298" fill="black" />
<text x="250" y="150" font-family="Verdana" font-size="55" fill="white">Hello world!</text>
</svg>
Please help :/
Thanks.

Keeping your svg, you can do with like this, but you'll need some slight changes:
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" >
<rect onmouseover='document.getElementById("desc").style.visibility = "visible"' onmouseout='document.getElementById("desc").style.visibility = "hidden"' x="1" y="1" width="998" height="298" fill="blue" class="showme"/>
</svg>
<svg width="200" height="200" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1" id="desc" >
<rect x="1" y="1" width="998" height="298" fill="black" />
<text x="250" y="150" font-family="Verdana" font-size="55" fill="white">Hello world!</text>
</svg>
https://jsfiddle.net/q6kkhvz7/2/

Related

How to use SVG clipPath with Pattern via CSS clip-path property?

The initial SVG figure with pattern:
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%">
<circle cx="2" cy="2" fill="white" r="0.8"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="100" height="100" fill="url(#img-dotted-dots)"></rect>
</mask>
</defs>
<path d="M0 0 H 100 V 100 H 0 Z" mask="url(#img-dotted-mask)" fill="#1063B1"></path>
</svg>
Need to achieve:
One instance of the SVG figure with pattern for refferencing with CSS as clip-path.
I have tried to create SVG clipPath element and bind to CSS clip-path by this way
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<pattern
patternUnits="objectBoundingBox"
patternContentUnits="objectBoundingBox"
x="0" y="0" height="0.1" width="0.1">
<circle cx="0" cy="0" fill="white" r="0.5"></circle>
</pattern>
</clipPath>
</defs>
</svg>
Nothing happens.
Expected result - the same as the previous snippet.
For comparing:
If I use SVG rect - CSS clip-path works.
If pattern - doesn't
.figure {
width: 300px;
height: 300px;
clip-path: url(#img-dotted-clip-path);
background-color: #1063B1;
}
<div class="figure"></div>
<svg width="0" height="0" viewBox="0 0 100 100">
<defs>
<clipPath
clipPathUnits="objectBoundingBox"
id="img-dotted-clip-path">
<rect width="1" height="1"></rect>
</clipPath>
</defs>
</svg>
The only things that are valid inside a clip path are:
Shape elements (‘circle’, ‘ellipse’, ‘line’, ‘path’, ‘polygon’, ‘polyline’, ‘rect’)
‘text’
‘use’
Plus you can use animation elements etc to animate the clip path. However, only the shapes of those elements are used. Effects such as patterns, filters, etc are ignored.
The only way you could get the effect you want to work as a clipping path would be to add numerous <circle> elements to your <clipPath>.
<clipPath>
<circle>
<circle>
<circle>
<circle>
... etc ...
</clipPath>
But you could use a mask instead. Masks allow patterns.
.figure {
width: 300px;
height: 300px;
-webkit-mask: url(#img-dotted-mask);
mask: url(#img-dotted-mask);
background-color: #1063B1;
}
<p>This only works in Firefox</p>
<div class="figure"></div>
<svg width="0" height="0">
<defs>
<pattern id="img-dotted-pattern"
viewBox="0 0 1 1"
patternUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
<rect width="1" height="1" fill="black"/>
<circle cx="0.5" cy="0.5" fill="white" r="0.15"></circle>
</pattern>
<mask id="img-dotted-mask">
<rect width="2000" height="2000" fill="url(#img-dotted-pattern)"/>
</mask>
</defs>
</svg>
However inline SVG masks applied to HTML elements, like my example above, only work in Firefox. To get an SVG mask to work in Chrome, you would need to use mask or mask-image with an external or Data URL (as Temani has done in their answer).
You can recreate the same thing using mask combined with radial-gradient
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
/*radius here size here*/
-webkit-mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
mask:radial-gradient(3px, #fff 97%,transparent 100%) 0 0/20px 20px;
}
body {
background:#f2f2f2;
}
<div class="figure"></div>
Or consider the SVG inside the mask property. Make sure to escape the # and correctly set the viewbox and width/height to have a perfect repeat
.figure {
width: 300px;
height: 300px;
background:linear-gradient(to right,red,#1063B1);
-webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="192" viewBox="0 0 100 90"><defs><pattern id="img-dotted-dots" x="0" y="0" height=".08" width="7.69%"><circle cx="2" cy="2" fill="white" r="0.8"></circle></pattern><mask id="img-dotted-mask"><rect width="100" height="100" fill="url(%23img-dotted-dots)"></rect></mask></defs><path d="M0 0 H 100 V 100 H 0 Z" mask="url(%23img-dotted-mask)" fill="%231063B1"></path></svg>');
}
body {
background:#f2f2f2;
}
<div class="figure"></div>

How to make SVG “fill” act in a similar way to CSS “background-position:right top”

I have the following SVG image:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66.667 108">
<pattern id="i" width="100%" height="100%">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/38/Bangalore_Panorama_edit1.jpg" width="45" height="49" preserveAspectRatio="xMinYMin slice"/>
</pattern>
<rect x="21.667" y="0" width="45" height="49" fill="url(#i)"/>
</svg>
I need the rectangle to fill with an image equivalent to the following CSS syntax:
background-size:cover;
background-image:url("image.jpg");
background-repeat:no-repeat;
background-position:right top;
Thanks to this post, I got them all except background-position:right top. Is this possible in an SVG image? If so, how can I achieve this?
To mimic the behavior, so that the top right corner of the picture is located at the top right corner of the rect, you just need to change the preserveAspectRatio="xMinYMin slice" of the image to preserveAspectRatio="xMaxYMin slice":
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 66.667 108">
<pattern id="i" width="100%" height="100%">
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/3/38/Bangalore_Panorama_edit1.jpg" width="45" height="49" preserveAspectRatio="xMaxYMin slice"/>
</pattern>
<rect x="21.667" y="0" width="45" height="49" fill="url(#i)"/>
</svg>

How do I get filters to work on nested SVGs?

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>

How does SVG image pattern work with preserving aspect ratio?

I have the following svg:
<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="none" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" width="100%" height="100%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="-20" width="100" height="100"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" style="stroke-width:0" fill="url(#img1)"/>
</svg>
It's not working as expected because it enlarge te face of the people on the image as follows:
But it should look like this:
Does having a triangular polygon affects the image? How can I solve it, I need 4 triangle figures with images inside to be clickables.
Well this is working as intended. You specify a pattern whose unit should fill the bounding box of the container, and then specify a 2:1 container - so it stretches the image. There are lots of permutations that preserve the aspect ratio of the image - it depends on exactly what behavior you want.
This is one version that preserves the aspect ratio of the SVG itself even when it's asked to fill a larger space.
<svg height="100%" width="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" width="100%" height="100%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="-20" width="100" height="100"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" fill="url(#img1)" />
</svg>
Or if you want to adjust the pattern itself, you can double the height of the pattern and offset it in Y to adjust for the 2:1 ratio of your container:
<svg height="100%" width="100%" viewBox="0 0 100 100" style="display: block; position: absolute; top: 0;">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" y="-100%" width="100%" height="200%">
<image xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="0" width="100" height="100" preserveAspectRatio="xMidYMax meet"/>
</pattern>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" fill="url(#img1)" />
</svg>
This is another version that uses a filter to fill in the image.
<svg height="100%" width="100%" viewBox="0 0 100 100" style="display: block; position: absolute; top: 0; background:grey">
<defs>
<filter id="img1" x="0%" y="0%" width="100%" height="100%" >
<feImage xlink:href="https://media.npr.org/assets/img/2016/06/22/gettyimages-467390112_custom-e8fa0c9a7224b7172555577fde25a08949bde2d2-s900-c85.jpg" x="0" y="0" width="100" height="100" preserveAspectRatio="xMidYMax meet"/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<polygon points="0 100, 50,50 100,100" id="abajo" filter="url(#img1)" />
</svg>

Fill SVG path with colour but on hover fade-in pattern

I am trying to add an SVG image (in this case a flag of Belgium) as the fill of an SVG path (actually an ellipse). On hover, the ellipse's fill has to transition into red. In other words, the fill SVG has to 'fade out'. I tried it in a way I'd do it with CSS, but neither the SVG pattern nor the transition seem to work. I tried on Chrome and Firefox.
svg ellipse {
fill: url(#img1);
transition: fill 400ms;
}
svg:hover ellipse {
fill: red;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" height="480" width="640" viewBox="0 0 640 480">
<defs>
<pattern x="0" y="0" id="img1" height="480" width="640" viewBox="0 0 640 480">
<g fill-rule="evenodd" stroke-width="1pt">
<path d="M0 0h213.335v479.997H0z" />
<path fill="#ffd90c" d="M213.335 0H426.67v479.997H213.335z" />
<path fill="#f31830" d="M426.67 0h213.335v479.997H426.67z" />
</g>
</pattern>
</defs>
<rect fill="none" stroke="blue" x="1" y="1" width="640" height="480"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" />
</svg>
You can't transition fill like that because the two fills are not something that can be interpolated smoothly between.
What you need to do is have two versions of the ellipse, one on top of the other. Then either fade in or out the top one.
.visible-on-hover {
transition: opacity 400ms;
opacity: 0;
}
.visible-on-hover:hover {
opacity: 1;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" height="480" width="640" viewBox="0 0 640 480">
<defs>
<pattern x="0" y="0" id="img1" height="1" width="1"
viewBox="0 0 640 480" preserveAspectRatio="xMidYMid slice">
<g fill-rule="evenodd" stroke-width="1pt">
<path d="M0 0h213.335v479.997H0z" />
<path fill="#ffd90c" d="M213.335 0H426.67v479.997H213.335z" />
<path fill="#f31830" d="M426.67 0h213.335v479.997H426.67z" />
</g>
</pattern>
</defs>
<rect fill="none" stroke="blue" x="1" y="1" width="640" height="480"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" fill="url(#img1)"/>
<ellipse stroke="black" stroke-width="5" cx="400" cy="200" rx="350" ry="150" fill="red" class="visible-on-hover"/>
</svg>

Resources