I have three SVGs nested inside another SVG. The first one is supposed to be fluid and stretched out so preserveAspectRatio is none. The other two are set to 10% and 90% for the x value. But if you resize the page you'll see they have different distance from the left and right side. Why?
I'm expecting to see the left one having the same distance from left as the right one having the distance from right.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" viewBox="0 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="90%" viewBox="0 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>
Because you're starting to draw the second blue box at 90%, when you really want to end the draw at 90%. Fix this by setting the viewBox of the second blue box to:
viewBox="20 0 20 20"
Here's another solution.
The two blue SVGs are identical apart from their preserveAspectRatio attributes.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" width="80%" height="100%" viewBox="0 0 10 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="10%" width="80%" height="100%" viewBox="0 0 10 20" preserveAspectRatio="xMaxYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>
For anyone as confused as me, here is the problem:
If I set the viewBox x value to half of the width 10 / 2 = 5, then I technically panned the origin to the width's center.
.box {
width: 60vw;
border: 1px dashed lightgray;
}
svg {
overflow: visible;
}
<div class="box">
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="50">
<svg viewBox="0 0 2 2" preserveAspectRatio="none">
<rect x="0" width="2" height="1" fill="#DDDDDD" />
</svg>
<svg x="10%" viewBox="5 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
<svg x="90%" viewBox="5 0 20 20" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="10" height="10" fill="#7FDBFF" />
</svg>
</svg>
</div>
Related
This question already has answers here:
How to resize a svg
(2 answers)
Closed 17 hours ago.
I have the below SVG which I am using as a mask to overlay on an image, I am trying to make the circle responsive, so it shrinks on mobile devices but haven't had any luck using view box etc as it removes the mask, I am also trying to position the shadow to the bottom right of the circle, but again I am having trouble making it responsive.
Any help would be greatly appreciated.
svg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2000 1000" preserveAspectRatio="xMidYMin slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="250" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<path id="Shadow" d="M462.231,0c19.593,38.355,29.045,88.448,36.926,138.3,9.125,75.59-104.323,237.333-194.755,250.24C246.323,389.921,51.569,371.964,0,313.148c46.559,91.147,141.283,153.59,250.655,153.59,155.395,0,281.365-125.97,281.365-281.365A280.22,280.22,0,0,0,462.231,0" opacity="0.2" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</svg>
Putting the path inside a g container allowed me to scale the shadow relative to the mask, hope this helps someone in the future.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="16.5%" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<g>
<path id="Shadow" d="m 462.231 0 c 19.593 38.355 29.045 88.448 36.926 138.3 c 9.125 75.59 -104.323 237.333 -194.755 250.24 c -58.079 1.381 -252.833 -16.576 -304.402 -75.392 c 46.559 91.147 141.283 153.59 250.655 153.59 c 155.395 0 281.365 -125.97 281.365 -281.365 a 280.22 280.22 0 0 0 -69.789 -185.373" opacity="0.2" style="transform: scale(0.3) translate(579px, 650px);" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</g>
</svg>
I'm trying to achieve the following graph using SVG patterns:
The only one I could do is the first one:
.patterns { display: flex;}
<div style="position: absolute; width: 0; height: 0;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id="pattern1" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" style="stroke:#04A484; stroke-width:1" />
</pattern>
<pattern id="pattern2" patternUnits="userSpaceOnUse">
</pattern>
<pattern id="pattern3" patternUnits="userSpaceOnUse">
</pattern>
</defs>
</svg>
</div>
<div class="patterns">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect width="25px" height="100px" fill="url(#pattern1)"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect width="25px" height="100px" fill="url(#pattern2)"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect width="25px" height="100px" fill="url(#pattern3)"/>
</svg>
</div>
Borders are not an issue, since I'm using a charts library that only needs the SVG pattern.
How can I achieve the other two patterns ?
Thanks in advance.
There's a slight problem with your diagonal shading. Since the line is dawn from (0,0) to (0,10), it lies on the edge of the SVG rendering area, so half of it will be hidden. That's why your lines look rather thin. You can fix that by offsetting the line slightly so that you keep everything visible.
The other patterns aren't hard to make. There's no need to apply any sort of rotation; just find a unit pattern that repeats the way you want. For the second of the three patterns, one of the horizontal lines has to travel across the edge of the pattern unit. To fix this, I broke this line into two parts; one aligned with the left edge of the pattern block, and one aligned with the right edge; i.e. M15 4 20 4M0 4 5 4 instead of M15 4 25 4, which would end up 5 pixels past the right edge of the 20×32 pattern block.
(Note: I'm using <path> elements to draw the lines, because they're a bit easier to type in. <path d="M1 2 3 4M5 6 7 8"/> is equivalent to <line x1="1" y1="2" x2="3" y2="4"/><line x1="5" y1="6" x2="7" y2="8"/>.)
.patterns { display: flex;}
<div style="position: absolute; width: 0; height: 0;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<pattern id="pattern1" width="8" height="8" patternTransform="rotate(45)" patternUnits="userSpaceOnUse">
<path d="M3 0 3 8" style="stroke:#25a08b; stroke-width:2" />
</pattern>
<pattern id="pattern2" width="20" height="32" patternUnits="userSpaceOnUse">
<path d="M0 28 10 28M5 20 15 20M10 12 20 12M15 4 20 4M0 4 5 4" style="stroke:#b2b6c1; stroke-width:2" />
</pattern>
<pattern id="pattern3" width="20" height="32" patternUnits="userSpaceOnUse">
<path d="M1 8 9 8M5 4 5 12M11 24 19 24M15 20 15 28" style="stroke:#0c2160; stroke-width:2" />
</pattern>
</defs>
</svg>
</div>
<div class="patterns">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect x="1" y="1" width="28" height="98" fill="url(#pattern1)" stroke="#25a08b" stroke-width="2"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect x="1" y="1" width="28" height="98" fill="url(#pattern2)" stroke="#b2b6c1" stroke-width="2"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%">
<rect x="1" y="1" width="28" height="98" fill="url(#pattern3)" stroke="#0c2160" stroke-width="2"/>
</svg>
</div>
I have a nested SVG with 3 elements. 2 triangles that are positioned at the right-left sides and one line in the middle. I would like to obtain a responsive line (line should only have the width available between the triangles), both when resizing horizontally and vertically. I have tried setting the width in percentage but in only works when resizing horizontally. When I am resizing vertically it doesn't work because the width of the triangles changes. Here is a codepen link: https://codepen.io/roppazvan/pen/dyyPKKL?editors=1100
<svg
class='input-source'
stroke='black'
stroke-width='0'
fill="black">
<rect x="20" y="20%" width="100%" height="60%"
stroke='black'
stroke-width='0'
>
</rect>
<!-- The right head -->
<svg class='head input-source' id='right'
height="100%"
width='100%'
viewBox="0 0 20 40"
preserveAspectRatio="xMaxYMid"
>
<rect width="100%" height="100%"/>
</svg>
<!-- The left head -->
<svg class='head input-source' id='left'
height="100%"
width='100%'
viewBox="0 0 15 30"
preserveAspectRatio="xMinYMid"
>
<rect width="100%" height="100%"/>
</svg>
</svg>
</svg>
<svg width="110px" height="40px" version="1.0" state='normal'>
<svg
class='input-source'
stroke='black'
stroke-width='0'
fill="black">
<rect x="20" y="20%" width="100%" height="60%"
stroke='black'
stroke-width='0'
>
</rect>
<!-- The right head -->
<svg class='head input-source' id='right'
height="100%"
width='100%'
viewBox="0 0 20 40"
preserveAspectRatio="xMaxYMid"
>
<rect width="100%" height="100%"/>
</svg>
<!-- The left head -->
<svg class='head input-source' id='left'
height="100%"
width='100%'
viewBox="0 0 15 30"
preserveAspectRatio="xMinYMid"
>
<rect width="100%" height="100%"/>
</svg>
</svg>
</svg>
The simplest and easiest approach to implement and understand, is probably to just use flex-box.
#svg-container {
margin-top: 100px;
width: 100%;
border: 1px solid #bada55;
display: flex;
flex-direction: row;
}
svg {
height: 10vh;
}
/* stretch the middle box */
svg:nth-child(2) {
flex: 1;
}
<div id="svg-container">
<!-- left head -->
<svg viewBox="0 0 14 14" preserveAspectRatio="xMinYMid" opacity="0.5">
<polygon points="0,7 14,0 14,14 " />
</svg>
<!-- line -->
<svg viewBox="0 0 14 14" preserveAspectRatio="none">
<rect y="30%" width="100%" height="40%" />
</svg>
<!-- right head -->
<svg viewBox="0 0 14 14" preserveAspectRatio="xMaxYMid" opacity="0.5">
<polygon points="14,7 0,0 0,14 "/>
</svg>
</div>
I have a svg-pattern applied to a polygon. It's working fine.
When I set another size on the svg-polygon, I don't want to scale the pattern.
I've tried all combinations I can think of with viewBox, patternUnits and patternContentUnits. The goal is to make the polygon work responsibly e.g. scale with it's parent element. Can anyone point me in the right direction?
<svg width="1000" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
<svg width="500" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
full example: https://codepen.io/anderssonola/pen/QqxKjJ
I solved temporarily by applying the pattern to a <rect>and then use css clip-pathto create the polygon and the pattern does not scale. I still would prefer to solve it with pure svg, since IE does not support the css clip-path.
.clip {
background: gray;
clip-path: polygon(0 0, 100% 0, 100% 30%, 0% 100%);
margin-bottom: 1em;
}
.clip.half {
width: 50%;
}
svg {
display: block;
height: 50px;
width: 100%
}
<div >
<svg>
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" >
<!-- pattern code -->
</svg>
</pattern>
<rect width="100%" height="50" fill="url(#pattern)" id="pattern-md"/>
</defs>
</svg>
</div>
<div class="clip">
<svg>
<use href="#pattern-md"/>
</svg>
</div>
<div class="clip half" >
<svg>
<use href="#pattern-md" />
</svg>
</div>
Working example: https://codepen.io/anderssonola/pen/oGyBMj/
You could always scale the pattern and size the polygon appropriately e.g.
<polygon transform="scale(2)" points="0,0 720,0 720,10 0,30" stroke="#bbb" fill="url(#pattern)" />
I am creating an HTML5 grid for a website. The grid looks the way I would like it to, however in each "big" square, there are 10 smaller squares. I need there to be only 5 squares in each "big" square. I am not proficient in HTML5 and am not sure how to even word the question, hopefully someone understands what I am trying to do here.
HERE is the site: http://www.webexplosive.com/sms_test/piermap.html
and HERE is my grid code:
<div style="width: 902px; height: 602px; position: absolute; left: 0px; top: 86px;">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="minorGrid" width="10" height="10" patternUnits="userSpaceOnUse">
<path d="M 10 0 L 0 0 0 10" fill="none" stroke="#FF4444" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="100" height="100" patternUnits="userSpaceOnUse">
<rect width="100" height="100" fill="url(#minorGrid)"/>
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="red" stroke-width="4"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
</div>
Look at this:
http://jsfiddle.net/cBXER/
<div style="width: 902px; height: 602px; position: absolute; left: 0px; top: 86px;">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="minorGrid" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#FF4444" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="100" height="100" patternUnits="userSpaceOnUse">
<rect width="100" height="100" fill="url(#minorGrid)"/>
<path d="M 100 0 L 0 0 0 100" fill="none" stroke="red" stroke-width="4"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
</div>
You need to change your minor grid width, height and path d values to 20 because 20 is one-fifth of 100.