Draw a circle in svg with preserveAspectRatio="none" - css

I have an svg with viewBox="0 0 100 100" preserveAspectRatio="none" since I need to draw some elements with reference to percentages.
If I now draw a <circle cx="30" cy="50" r="0.5" stroke="white"/> though it becomes stretched/distorted as well.
Is there a way to tell the circle element to preserve its own aspect ratio?

If all you need is a circle you can use a very short, very wide line like in the following example.
This will work because
stroke-linecap="round" will give the illusion of a circle and because
strokes can take a vector-effect="non-scaling-stroke".
non-scaling-stroke
This value modifies the way an object is stroked. Normally stroking involves calculating stroke outline of the shape's path in current user coordinate system and filling that outline with the stroke paint (color or gradient). The resulting visual effect of this value is that the stroke width is not dependent on the transformations of the element (including non-uniform scaling and shear transformations) and zoom level.
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<!--<circle cx="30" cy="50" r="20"></circle>-->
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>
If you need a white stroke too you can add a white line behind the black one with a bigger stroke width
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="45" stroke="white" stroke-linecap="round" vector-effect="non-scaling-stroke" />
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>

Related

How to modify the size of a <g> (SVG element)?

I can not seem to succeed at modifying the size of my element that is rendered inside a recharts graph as X axis. I want it to be 20px height and width. I couldn't even succeed by making modifications in the console css to the element. Could anyone help me out?
Here's the element:
<svg
style={{ cursor: 'pointer', }} width="20px" height="20px"
>
<g transform={`translate(10,10)`} fill="green" stroke="green">
<path
fill="current"
fillRule="evenodd"
d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z"
transform="translate(.5)"
/>
</g>
</svg>
As #enxaneta recommended, a negative viewBox offset like viewBox="-0.5 -0.5 17 17" is a straight forward solution.
Alternatively, you could scale your <g> (or your path) like so:
.svg{
display:inline-block;
width:10em;
border: 1px solid #ccc
}
<svg class="svg" viewBox="0 0 16 16">
<g transform="scale(0.94117647)" transform-origin="8 8" stroke-width="1" fill="green" stroke="green">
<path d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z" ></path>
</g>
</svg>
Edit: correct scaling value
As #Carsten Massmann has pointed out it should be:
The scaling factor 0.94117647 is the result of
16/17 (original svg width / svg width + stroke-width)
transform-origin="8 8" ensures we're scaling from the center of our viewBox.
Another workaround might be to set overflow to visible to avoid any cropping:
.svg{
display:inline-block;
width:10em;
border: 1px solid #ccc
}
<svg overflow="visible" class="svg" viewBox="0 0 16 16">
<path stroke-width="1" fill="green" stroke="green" d="M8,0 C3.58862306,0 0,3.58862306 0,8 C0,12.4113769 3.58862306,16 8,16 C12.4113769,16 16,12.4113769 16,8 C16,3.58862306 12.4113769,0 8,0 Z M12.0546875,6.3046875 L7.72131347,10.6379394 C7.59130859,10.7679443 7.42065431,10.833374 7.25,10.833374 C7.07934569,10.833374 6.90869141,10.7679443 6.77868653,10.6379394 L4.61206056,8.47131347 C4.35131837,8.21069338 4.35131837,7.78930663 4.61206056,7.52868653 C4.87268066,7.26794434 5.29394531,7.26794434 5.5546875,7.52868653 L7.25,9.22399903 L11.1120606,5.36206056 C11.3726807,5.10131837 11.7939453,5.10131837 12.0546875,5.36206056 C12.3153076,5.62268066 12.3153076,6.04394531 12.0546875,6.3046875 Z" ></path>
</svg>
Caveats: your icon will be displayed larger than your original design and might cause layout inconsistencies when used with other elements that fit the 16x16 boundaries.
If it will be useful to you, I found svg similar to yours and I demonstrated how you can add styles
svg {
background: #479840;
border-radius: 50%;
}
path {
filter: invert(99%) sepia(99%) saturate(2%) hue-rotate( 205deg)
brightness(110%) contrast(100%);
}
<svg height="44" viewbox="0 0 24 24" width="44" xmlns="http://www.w3.org/2000/svg">
<path d="m10 15.586-3.293-3.293-1.414 1.414L10 18.414l9.707-9.707-1.414-1.414z"></path></svg>

How to change svg path width on hover

I have an issue I can't find an helpful answer. I have a svg arrow, the arrow has to grow when the user hovers over with the mouse. The problem is that only the line has to change size not the arrow head. I just want the line to grow horizontally.
This is the svg code
<svg width="51" height="8" viewBox="0 0 51 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.3536 4.35355C50.5488 4.15829 50.5488 3.84171 50.3536 3.64645L47.1716 0.464466C46.9763 0.269204 46.6597 0.269204 46.4645 0.464466C46.2692 0.659728 46.2692 0.976311 46.4645 1.17157L49.2929 4L46.4645 6.82843C46.2692 7.02369 46.2692 7.34027 46.4645 7.53553C46.6597 7.7308 46.9763 7.7308 47.1716 7.53553L50.3536 4.35355ZM0 4.5H50V3.5H0V4.5Z" fill="black"/>
</svg>
And this is the code the I have working right now
svg {
width: 50px;
overflow: visible;
transition: width 0.5s ease;
}
svg:hover {
width: 100px;
}
I also have a Codepen link
https://codepen.io/godhandkiller/pen/xxRZeYv
The problem here is that I'm manipulating the whole SVG but I only need to change the like size.
A possible solution: you can use a line path with a marker-end. The marker is the tip of the arrow. For the animation I'm using SMIL animations changing the d attribute of the path from M1,4L25,4 to M1,4L50,4. The animate element has a begin attribute making the animation to begin when you mouse over the overlaying rectangle: begin="theRect.mouseover". Another animate element animates the path on mouse out: begin="theRect.mouseout"
svg {
border: 1px solid red;
transition: width 0.5s ease;
}
<svg id="theSVG" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 8" stroke="#000" stroke-linecap="round">
<defs>
<marker id="m" overflow="visible" markerUnits="userSpaceOnUse">
<path d="M-3,-3L0,0 -3,3" />
</marker>
</defs>
<path d="M1,4L25,4" marker-end="url(#m)">
<animate attributeName="d" to="M1,4L50,4" dur="1s" begin="theRect.mouseover" repeatCount="1" fill="freeze" />
<animate attributeName="d" to="M1,4L25,4" dur="1s" begin="theRect.mouseout" repeatCount="1" fill="freeze" />
</path>
<rect width="100%" height="100%" stroke="none" pointer-events="all" id="theRect" />
</svg>

Svg responsive width with adjustable height

been having a hard time to come up with a good solution to have a responsive svg that will adopt the screen width plus an adjustable height. I tried setting width to 100% and height to something like 200px but no luck.
header.svg {
width: 100%;
max-height: 200px;
height: 200px;
}
<header>
<svg width="321px" height="141px" viewBox="0 0 321 141" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="header-copy-" fill="#262626">
<g id="header-copy-2">
<path d="M0,0.31823636 L321,0.31823636 L321,132.556396 C267.894961,138.185465 214.394961,141 160.5,141 C106.605039,141 53.1050387,138.185465 0,132.556396 L0,0.31823636 Z" id="Rectangle-Copy-12"></path>
</g>
</g>
</g>
</svg>
</header>
I also tried adding a 100% width to the header element.
Firstly, your selector is incorrect, it should be header svg not header.svg. The SVG is a child of the header...the header does not have the class of .svg.
Secondly, I'd recommend removing the height and width from the SVG. It's not needed since you have set an appropriate viewbox.
Now, it seems you want the width of the SVG to be 100% of the page but the height to be limited to a set value.
To do this you will have to set the preserveAspectRatio attribute of the SVG to none.
Viewbox & PreserveAspectRatio
header {
background: pink;
}
svg {
max-height: 100px;
width: 100%;
margin: auto;
display: block;
}
<header class="wide">
<svg viewBox="0 0 321 141" version="1.1" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="header-copy-" fill="#262626">
<g id="header-copy-2">
<path d="M0,0.31823636 L321,0.31823636 L321,132.556396 C267.894961,138.185465 214.394961,141 160.5,141 C106.605039,141 53.1050387,138.185465 0,132.556396 L0,0.31823636 Z" id="Rectangle-Copy-12"></path>
</g>
</g>
</g>
</svg>
</header>

Animated growing arrow link

Hi, I was wondering how one would go about animating an svg arrow like above (on hover).
I have tried playing around with CSS transforms, but they also scale the arrow-head which is no good. I assume the correct way to do this is using SVGs animations, but I don't know where to start.
For example I would the following arrow (line only) to grow and arrow head to move accordingly.
<svg width="600px" height="100px">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#f00" />
</marker>
</defs>
<line x1="50" y1="50" x2="100" y2="50" stroke="#000" stroke-width="5" marker-end="url(#arrow)" />
</svg>
Any help is very much appreciated!
You can create growing arrow by using "respoinsive" SVG like this.
svg{
width: 20px;
height: 20px;
transition:width 2s ease;
overflow: visible;
}
svg:hover{
width: 100px;
}
<svg>
<defs>
<marker id="m" markerWidth="4" markerHeight="8"
refX="0" refY="1" viewBox="0 0 1 2">
<polygon points="0,0 1,1 0,2" fill="black"/>
</marker>
</defs>
<line x1="0" y1="50%" x2="100%" y2="50%"
stroke-width="2" marker-end="url(#m)" stroke="black"/>
</svg>
There are some points to implement.
svg has no viewBox (so it is "responsive" SVG).
Line of arrow is defined by relative position of (root) svg size.
Arrow head is defined by marker element.
Growing animation is defined by CSS transition which animate width of svg. So, arrow grows with svg size.
In order to animate the individual SVG elements like HTML elements, you'll need to embed the SVG directly into the page like this:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
xml:space="preserve" class="logo">
<ellipse class="ground" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
C434.693,207.929,439.613,203.01,445.731,203.01z"/>
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="15" />
</filter>
</svg>
After doing this, you can use CSS animations on any of the individual SVG elements, just like HTML elements. For example, you could do the following:
svg ellipse { animate: grow 3s infinite; }
Without having the exact SVG code for your arrow, I can't give you more specific direction than that, but can point you in the direction of this article: https://css-tricks.com/using-svg/

Divide a circle into 24 segments using css

I have created a circle using css. Now I want to divide it into 24 segments. How can I perform this using css. Help me.
Here's my code for how I created circle:
<div class="circle"></div>
.circle{
width: 50px;
height: 50px;
border-radius: 50%;
background-color: blue
}
You can perform it more easily by using Scalable Vector Graphics.
code to draw circle:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="150" cy="100" r="50" stroke="blue" stroke-width="2" fill="white"/>
</svg>
You may draw different lines, so that you can divide the circle into segments.
Code for line:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2"/>
</svg>

Resources