I'm trying to make a SVG pattern seamless but with no luck
https://codepen.io/unlocomqx/pen/LYzbbNp
Code
<svg viewBox="0 0 100 100" width="300" height="300">
<defs>
<pattern id="grid2" width="10pt" height="10pt" patternUnits="userSpaceOnUse">
<path d="M 0 0 L 0 10 10 10 10 0 0 0" fill="#f7f6f4" stroke="#DDD" stroke-width="0.5"/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#grid2)"></rect>
</svg>
When I change the size to 5pt instead of 10pt, it works well
<svg viewBox="0 0 100 100" width="300" height="300">
<defs>
<pattern id="grid1" width="5pt" height="5pt" patternUnits="userSpaceOnUse">
<path d="M 0 0 L 0 10 10 10 10 0 0 0" fill="#f7f6f4" stroke="#DDD" stroke-width="0.5"/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#grid1)"></rect>
</svg>
How to fix it for the 10pt case?
You're running into the problem here that you can still only use SVG's built-in userSpaceOnUse or objectBoundingBox units for paths, so you'll have to use a rect, which does support more unit types (like pts).
Not seamless
<svg viewBox="0 0 100 100" width="300" height="300">
<defs>
<pattern id="grid2" width="10pt" height="10pt" patternUnits="userSpaceOnUse">
<rect x="0pt" y="0pt" width="10pt" height="10pt" fill="#f7f6f4" stroke="#DDD" stroke-width="0.5"/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#grid2)"></rect>
</svg>
Seamless
<svg viewBox="0 0 100 100" width="300" height="300">
<defs>
<pattern id="grid1" width="5pt" height="5pt" patternUnits="userSpaceOnUse">
<path d="M 0 0 L 0 10 10 10 10 0 0 0" fill="#f7f6f4" stroke="#DDD" stroke-width="0.5"/>
</pattern>
</defs>
<rect x="0" y="0" width="100" height="100" fill="url(#grid1)"></rect>
</svg>
I have a simple SVG with two rectangles. I want the "inner" rectangle to be exactly in the middle of the SVG. By setting x and y attributes to 50% the upper left corner is centred. Instead, I want to center the middle of the rectangle. I've tried setting transform-origin to center but it doesn't work.
<svg width="100" height="100">
<rect width="100%" height="100%" fill="gold" />
<rect width="30" height="30" x="50%" y="50%" fill="green" />
</svg>
How to achieve such functionality without manually specifying x and y attributes?
The explanation of the code:
The x and y coordinates of a rectangle represent the position of the upper left corner. So if you give your rectangle x="50" y="50" this will put the upper left corner of the rectangle in the middle of the SVG canvas. To center the rectangle you need to offset it with half width or height: 50 - (30/2) = 35. The solution is <rect width="30" height="30" x="35" y="35" fill="green" />
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<rect width="30" height="30" x="35" y="35" fill="green" />
</svg>
update:
The op is commenting:
I would actually prefer to set 50% for x and y instead of doing some math
In this case you may need to translate your rect, but you still need some math in order to know how much to translate:
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<rect width="30" height="30" x="50%" y="50%" transform="translate(-15,-15)" fill="green" />
</svg>
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<rect width="30" height="30" x="-15" y="-15" transform="translate(50,50)" fill="green" />
</svg>
Yet an other solution would be using a polygon or a path with the center in the origin:
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<polygon points="-15,-15 15,-15 15,15 -15,15" transform="translate(50,50)" fill="green" />
</svg>
Here is an alternative that may work in some cases:
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<rect width="100%" height="100%" transform-origin="50% 50%" transform="scale(0.3)" fill="green" />
</svg>
You can also do the calculation without the transform attribute.
<svg width="100" height="100" viewBox="0 0 100 100">
<rect width="100%" height="100%" fill="gold" />
<rect width="30" height="30" x="calc(50% - 15)" y="calc(50% - 15)" fill="green" />
</svg>
I have two pairs of SVG patterns and symbols. The symbol holds and the SVG and the pattern shapes it. I use each pattern as a fill for a Circle.
This approach works fine in chrome but in edge only some svgs render in the circle. Below is an example, on chrome you should see both a shoe and a diamond. On Edge only the diamond renders even thou the approach is the same as the shoe.
CodePen Example
<svg width="660" height="600">
<defs>
<symbol xmlns="http://www.w3.org/2000/svg" id="symbol-shoe" viewBox="0 0 45 45">
</svg>
....SVG code
</svg>
<symbol xmlns="http://www.w3.org/2000/svg" id="symbol-diamond" viewBox="0 0 45 45">
<svg>
....SVG code
</svg>
</symbol>
<pattern id="pattern-diamond" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
<use xmlns="http://www.w3.org/2000/svg" x="6.59" y="6.59" width="31.819" height="31.819" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#symbol-diamond" />
<pattern id="pattern-shoe" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
<use xmlns="http://www.w3.org/2000/svg" x="6.59" y="6.59" width="31.819" height="31.819" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#symbol-shoe" />
</pattern>
</defs>
<circle fill="url(#pattern-shoe)" cx="150" cy="150" r="60" />
<circle fill="url(#pattern-diamond)" cx="150" cy="400" r="60" />
I'm trying to create an SVG that has an element in each corner. I want the svg to be scaleable, whilst the corner elements retain their size and aspect ratio... whilst sticking to the corners.
I feel like with a lot of javascript fiddling, this could be done. But I really feel this could be done with some clever css and a good understanding of how SVG's actually work.
This is an example of how I'd expect it to work: Demo Fiddle. This is just html and css.
div { width:40px; height:40px; position:absolute;
&:nth-of-type(1) { top:0; left:0; background-color:red;}
&:nth-of-type(2) { top:0; right:0; background-color:blue;}
&:nth-of-type(3) { bottom:0; left:0; background-color:green;}
&:nth-of-type(4) { bottom:0; right:0; background-color:yellow;}
}
This is where I got to before finally coming here: Fiddle
<svg version="1.1" id="circle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100%" height="100%" viewBox="0 0 100 100" xml:space="preserve" preserveAspectRatio="none">
<svg id="top-left" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMinYMin meet">
<rect width="20" height="20" fill="red" style="y:0; x:0"/>
</svg>
<svg id="top-right" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMin meet">
<rect width="20" height="20" fill="blue" style="y:0; x:calc(100% - 20px)"/>
</svg>
<svg id="bottom-left" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMaxYMax meet">
<rect width="20" height="20" fill="green" style="y:calc(100% - 20px); x:0"/>
</svg>
<svg id="bottom-right" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMinYMax meet">
<rect width="20" height="20" fill="yellow" style="y:calc(100% - 20px); x:calc(100% - 20px)"/>
</svg>
</svg>
Any insight would be greatly appriciated.
Cheers,
Mark
If the corner elements are symmetrical (left-to-right and top-to-bottom) then you could use a little trick of placing the right (or bottom) elements at x=-100% (or y=-100%) and applying a scale transform with sx=-1 (or sy=-1).
<svg x="0%" y="0%" width="100%" height="100%" style="border: 1px solid black;">
<rect id="top-left" x="0%" y="0%" width="20" height="20" fill="red"/>
<rect id="top-right" x="-100%" y="0%" width="20" height="20" fill="green" transform="scale(-1,1)"/>
<rect id="bottom-left" x="0%" y="-100%" width="20" height="20" fill="blue" transform="scale(1,-1)"/>
<rect id="bottom-right" x="-100%" y="-100%" width="20" height="20" fill="yellow" transform="scale(-1,-1)"/>
</svg>
Note that this trick only works for the special case when the corner elements are symmetrical.
If you know you are only going to need to scale in one direction. In other words the SVG is fixed in either with or height. Then you can do something like the following, which is designed for a fixed height of 100px.
<svg width="100%" height="100" preserveAspectRatio="none">
<svg id="top-left" width="100%" height="100%" viewBox="0 0 20 100" preserveAspectRatio="xMinYMin meet">
<rect width="20" height="20" fill="red"/>
</svg>
<svg id="top-right" width="100%" height="100%" viewBox="0 0 20 100" preserveAspectRatio="xMaxYMin meet">
<rect width="20" height="20" fill="blue"/>
</svg>
<svg id="bottom-right" width="100%" height="100%" viewBox="0 0 20 100" preserveAspectRatio="xMaxYMax meet">
<rect y="80" width="20" height="20" fill="green"/>
</svg>
<svg id="bottom-left" width="100%" height="100%" viewBox="0 0 20 100" preserveAspectRatio="xMinYMax meet">
<rect y="80" width="20" height="20" fill="yellow"/>
</svg>
</svg>
I am trying to create an SVG sprite.
I have set the SVG image to be 100px wide, 50px height, then offset the second by 50.
How can I set the size of the actual icon? Currently, the icon is huge and not 50px.
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100px"
height="50px">
<defs>
<g id="arrow">
<path d="M378.135,227.256L206.224,55.354c-12.354-12.359-12.354-32.394,0-44.748c12.354-12.359,32.388-12.359,44.747,0
L445.258,204.89c6.177,6.18,9.262,14.271,9.262,22.366c0,8.098-3.091,16.195-9.262,22.372L250.971,443.91
c-12.359,12.365-32.394,12.365-44.747,0c-12.354-12.354-12.354-32.391,0-44.744L378.135,227.256z M9.265,399.166
c-12.354,12.354-12.354,32.391,0,44.744c12.354,12.365,32.382,12.365,44.748,0l194.287-194.281
c6.177-6.177,9.257-14.274,9.257-22.372c0-8.095-3.086-16.192-9.257-22.366L54.013,10.606c-12.365-12.359-32.394-12.359-44.748,0
c-12.354,12.354-12.354,32.388,0,44.748L181.18,227.256L9.265,399.166z"/>
</g>
</defs>
<use x="0" y="0" style="fill: #333" xlink:href="#arrow" />
<use x="50" y="0" style="fill: #999" xlink:href="#arrow" />
</svg>
This is what I see:
DO NOT USE TRANSFORM FOR SCALING
What you are missing is a defined viewBox.
If you do not define a viewBox the viewBox is the same size as the height and width that you defined.
So when you draw a path and some of its point are above 370 then they will be outside its container. Since your defined size is 100 width by 50 height. Any point with values higher then the size will not be drawn.
when you define a viewBox you can change the size without affecting what is drawn or not.
This is the article i allways use when i forget how to properly scale svgs: https://css-tricks.com/scale-svg/
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100px"
height="50px"
viewBox="0 0 500 500">
<defs>
<g id="arrow">
<path d="M378.135,227.256L206.224,55.354c-12.354-12.359-12.354-32.394,0-44.748c12.354-12.359,32.388-12.359,44.747,0
L445.258,204.89c6.177,6.18,9.262,14.271,9.262,22.366c0,8.098-3.091,16.195-9.262,22.372L250.971,443.91
c-12.359,12.365-32.394,12.365-44.747,0c-12.354-12.354-12.354-32.391,0-44.744L378.135,227.256z M9.265,399.166
c-12.354,12.354-12.354,32.391,0,44.744c12.354,12.365,32.382,12.365,44.748,0l194.287-194.281
c6.177-6.177,9.257-14.274,9.257-22.372c0-8.095-3.086-16.192-9.257-22.366L54.013,10.606c-12.365-12.359-32.394-12.359-44.748,0
c-12.354,12.354-12.354,32.388,0,44.748L181.18,227.256L9.265,399.166z"/>
</g>
</defs>
<use x="0" y="0" style="fill: #333" xlink:href="#arrow" />
<use x="50" y="0" style="fill: #999" xlink:href="#arrow" />
</svg>
Like this? I just added transform="scale(0.1)" attribute to the g tag to make it 10x smaller
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100px"
height="50px">
<defs>
<g id="arrow" transform="scale(0.1)">
<path d="M378.135,227.256L206.224,55.354c-12.354-12.359-12.354-32.394,0-44.748c12.354-12.359,32.388-12.359,44.747,0
L445.258,204.89c6.177,6.18,9.262,14.271,9.262,22.366c0,8.098-3.091,16.195-9.262,22.372L250.971,443.91
c-12.359,12.365-32.394,12.365-44.747,0c-12.354-12.354-12.354-32.391,0-44.744L378.135,227.256z M9.265,399.166
c-12.354,12.354-12.354,32.391,0,44.744c12.354,12.365,32.382,12.365,44.748,0l194.287-194.281
c6.177-6.177,9.257-14.274,9.257-22.372c0-8.095-3.086-16.192-9.257-22.366L54.013,10.606c-12.365-12.359-32.394-12.359-44.748,0
c-12.354,12.354-12.354,32.388,0,44.748L181.18,227.256L9.265,399.166z"/>
</g>
</defs>
<use x="0" y="0" style="fill: #333" xlink:href="#arrow" />
<use x="50" y="0" style="fill: #999" xlink:href="#arrow" />
</svg>