Different Viewbox behaviour for inline vs embedded svg - css

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

Related

Responsive SVG Mask

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.

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>

I need to create 2 color Curve Responsive background with SVG

I need to create curve Responsive SVG background, with two color.
i Tried this below code:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 100% 100%" class="hidden-xs hidden-sm">
<defs>
<clipPath id="clip-Nye">
<rect width="100%" height="100%"/>
</clipPath>
</defs>
<g id="Nye" data-name="Nye" clip-path="url(#clip-Nye)">
<rect width="100%" height="100%" fill="#fff"/>
<path id="Rectangle" d="M0,453.226,817.641,0s696,663.078,406.715,730.84q-335.194,78.515-815.961,459.149C142.369,1400.607,0,453.226,0,453.226Z" transform="matrix(-0.485, 0.875, -0.875, -0.485, 1914.704, 197.622)" fill="#01b0f0"/>
</g>
</svg>
The Issue is that, when i minimize page with CTRL + -, SVG not show properly and side show blank.
what i do wrong? any idea?
You can try the use of radial-gradient:
body {
margin:0;
height:100vh;
background:radial-gradient(100% 200% at left,white 50%,#01b0f0 50.1%);
}

SVG change cursor from `cursor:wait` into e.g. `cursor:help` after hovering n seconds (loading time for tooltip) without scripting?

There has been a question about changing the cursor using before on this site, but it asked for a solution using Javascript, and it wasn't specific about when to trigger the action to change the cursor.
My question is about SVG and CSS/SMIL without the use of other scripting languages such as Javascript.
When hovering over a certain object, how to change the cursor from cursor:wait into e.g. cursor:help? The change should be triggered after an exact amount of seconds of being hovered over the object.
The use-case is clearly presented in a minimal snippet below.
MWE SNIPPET
#MOUSE_OVER_THESE{
cursor:wait;
}
<svg id="SVG"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="250"
height="175"
viewBox="0 0 250 175">
<text font-size="10" x="10" y="20">
<tspan
x="10" dy="0">Hover over the objects below. Can the cursor</tspan><tspan
x="10" dy="12">change from "cursor:wait" into e.g. "cursor:help"</tspan><tspan
x="10" dy="12.5">after about 1 second, (which will be right</tspan><tspan
x="10" dy="12.5">about when the tooltip appears on certain</tspan><tspan
x="10" dy="12.5">browsers) without using any scripting language?</tspan></text>
<g id="MOUSE_OVER_THESE">
<rect x="50" y="100" width="60" height="50" fill="red">
<title>This is a tooltip.</title>
</rect>
<rect x="150" y="100" width="60" height="50" fill="blue">
<title>This is another tooltip.</title>
</rect>
</g>
</svg>
I can not afford to use scripting languages such as Javascript, so I am wondering if there is a more native SVG with CSS/SMIL approach.
Here is a trick using transition and a hidden element.
UPDATE
The mouse need to be moved slightly in order to see the cursor change
.hide {
transition:1s visibility 1s;
cursor:wait;
}
.hide:hover {
visibility:hidden;
}
#MOUSE_OVER_THESE {
cursor:help;
}
#MOUSE_OVER_THESE:hover + .hide {
display:none;
}
<svg id="SVG"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="250"
height="175"
viewBox="0 0 250 175">
<text font-size="10" x="10" y="20">
<tspan
x="10" dy="0">Hover over the objects below. Can the cursor</tspan><tspan
x="10" dy="12">change from "cursor:wait" into e.g. "cursor:help"</tspan><tspan
x="10" dy="12.5">after about 1 second, (which will be right</tspan><tspan
x="10" dy="12.5">about when the tooltip appears on certain</tspan><tspan
x="10" dy="12.5">browsers) without using any scripting language?</tspan></text>
<g id="MOUSE_OVER_THESE">
<rect x="50" y="100" width="60" height="50" fill="red">
<title>This is a tooltip.</title>
</rect>
<rect x="150" y="100" width="60" height="50" fill="blue">
<title>This is another tooltip.</title>
</rect>
</g>
<rect class="hide" x="50" y="100" width="160" height="50" fill="transparent"></rect>
</svg>

SVG graph with variable width

I am trying to create an SVG graph with a fixed width to the left for the x axis labels and then a variable width to fill the remaining space for the actual graph results. The image below shows what I am trying to achieve. Thus far I have been unable to work out how to create the fixed width and variable width area.
Any help with this would be much appreciated!
Many thanks.
I would nest a couple of SVG elements inside your main like so:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500px" height="500px" >
<svg width="100">
<rect x="0" y="0" width="100%" height="100%" fill="red" />
</svg>
<svg x="100" >
<rect x="0" y="0" width="100%" height="100%" fill="blue" opacity="0.5"/>
</svg>
</svg>
NOTE I made the blue SVG element translucent so you can see that none of the red SVG was behind it.
I would also recommend using viewBox to give you more control over your drawing...
EDIT:
OK then I need to ask you a question about aspect ratios. If you take a square (width = height) and chop off a fixed portion from ONE side you no longer have a square and you have to think about what that means to your graph.
I believe this SVG will demonstrate more or less what you want:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="600px" height="500px" viewBox="0 0 1200 1000">
<svg width="200">
<rect x="0" y="0" width="100%" height="100%" fill="red" opacity="0.5"/>
</svg>
<svg x="200" width="1000" height="1000" viewBox="0 0 100 100">
<rect x="0" y="0" width="100%" height="100%" fill="blue" opacity="0.5"/>
<rect x="80%" y="10%" width="10%" height="50%" fill="green"/>
<rect x="10" y="10" width="70" height="40" fill="gray"/>
</svg>
NOTE the aspect ratio (AR) of the outermost SVG's dimensions MUST match the outermost viewBox's AR but can have different values. Likewise for the second inner SVG, but now you are dealing with a slice of the total that is a true square and not a rectangle. You can vary the width and height of the outer most SVG and so long as you maintain the same AR all the code on the inside will not have to change - it will all scale automajically :)
Also note the different scales in use and the different value types I used for co-ordinates. Because my second inner SVG's viewBox set the user co-ordinates to 100 X 100, 10% and 10 amount to the same thing...
You could also set the preserveAspectRatio="none" or some other value to achieve different effects but for a graph I kinda think lining things up is important so I wouldn't.
One final note - you could (and in your case should) omit the viewBox on the inner SVG. That way the scale is consistent on all parts of your graph. I was just showing off the power of viewBox :)
It just occurred to me that you may prefer a rectangle to a square so here is a code sample for that:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="400px" viewBox="0 0 1600 800" >
<svg width="200">
<rect x="0" y="0" width="100%" height="100%" fill="red" opacity="0.5"/>
</svg>
<svg x="200" width="1400" height="800" viewBox="0 0 175 100" >
<rect x="0" y="0" width="100%" height="100%" fill="blue" opacity="0.5"/>
<rect x="80%" y="10%" width="10%" height="50%" fill="green"/>
<rect x="10" y="10" width="70" height="40" fill="gray"/>
</svg>
NOTE the width of the inner SVG is set to 175 so that the aspect ratio of 1400/800 is maintained.

Resources