How to scale SVG path with fixed height/stroke-width? - html

It is possible to scale an SVG while keeping its height and/or stroke-width to a fixed value? I am looking for a way to keep the nice linecap rounded and scaled to the defined height (10px, or stroke-width: 10px)
Sandbox of what I'm trying to do:
https://codesandbox.io/s/scale-svg-with-fixed-stroke-width-snrh6r
But unsure how to get that to work or if is even possible...

Linecaps will expand the width of your <path>.
Try this:
set width:100% and height:10px for svg
preserveAspectRatio="none" will squeeze the svg/path to the total width of the parent div
vector-effect: non-scaling-stroke ensures line caps won't be distorted
the <path> is drawn across the entire width
overflow:visible prevents the line caps from being cut off
padding:0 5px 0 5px adjusts the svg viewport by a left and right 5px offset on both sides
.App {
font-family: sans-serif;
text-align: center;
resize: horizontal;
overflow: auto;
width: 352px;
padding: 0.3em;
border: 1px solid #ccc;
}
.stackbar-svg {
overflow: visible;
box-sizing: border-box;
padding: 0 5px 0 5px;
}
path {
stroke: red;
fill: red;
stroke-width: 10px;
stroke-linecap: round;
vector-effect: non-scaling-stroke;
}
<div class="App" style="width: 238px;">
<svg class="stackbar-svg" width="100%" height="10" viewBox="0 0 100 10" preserveAspectRatio="none">
<path id="stackbar-path-0" class="svgstackbar-color-0" d="M 0 5 L 100 5" />
</svg>
<p>As you resize the div, the stroke-width shrink<br>How to keep it at a fixed 10px?</p>
</div>
You could make the <path> element a 100% width and control

Related

textPath renders as skewed / path starting point and width aren't as assigned

I've been trying to add textpath on my page, but it keeps showing up as slanted/skewed and I cannot figure out why.
I need the path to have dynamic width and fixed height. That seems to mess with the text, tho.
preserveAspectRatio makes the width and height of the path as desired, but the text gets skewed. Removing it keeps the text intact, but the path's dimensions then are width: 376 and height: 376. It also then doesn't start at the assigned starting point (0,0).
Has anyone had this or something similar happen to them?
Here's my HTML:
<svg width="100%" height="376" viewBox="0 0 100 100" preserveAspectRatio="none">
<path d="M0 0 L100 100" id="line-2"/>
<text>
<textPath xlink:href="#line-2" id="line-2-text" startOffset="60%">Hello</textPath>
</text>
</svg>
And in SCSS I have:
svg {
fill: $primary-color;
margin: 0;
padding: 0;
position: absolute;
left: 0;
top: 100vh;
width: 100%;
#line-2-text {
fill: black;
font: {
family: $main-font;
size: 12px;
weight: bold;
}
text-transform: uppercase;
}
}

HTML arc sector with inline style

I would like to use HTML + CSS to draw a arc sector with fixed radix and length (e.g. 30px radius and 70% length).
I found so far most of the solution is to combined two pictures with position:absoulte. Unfortunately, my html codes will be embedded as an email template to send out, and I found that Gmail does not support absolute position. And that is also the reason why I would like to use inline style rather than header css.
Related question here:
HTML5 / CSS3 Circle with Partial Border
The similar output I am looking for.
http://dabblet.com/gist/3949571
Any help for it?
I'd use an SVG.
svg {
width: 150px;
height: 150px;
}
circle.inner {
stroke: rebeccapurple;
stroke-width: 3;
stroke-dasharray: 39% 139%;
stroke-dashoffset: 78%;
fill: pink;
}
<svg viewbox="0 0 100 100">
<circle class="inner" cx="40" cy="40" r="25" />
</svg>
you can use transparent borders and inset shadow to draw bg color :
/*demo*/
div {
display:flex;
align-items:center;
justify-content:center;/* center content not text */
text-align:center;
}
<div style="
box-sizing:border-box;
padding:1px;
margin:5px;
height:200px;
width:200px;
border:solid 20px transparent;
border-top-color:blue;
box-shadow:inset 0 0 0 100px lightblue;
border-radius:100%;"
>Some text <br/> too?</div>

Creating a skewed triangle shape

Is it possible to create the shape produced by this Fiddle. But then with no JavaScript but CSS3 (with <div>) ?
Basically this:
for(var i = 0; i < coords.length; i += 1) {
if(coords[(i + 1)] != undefined) {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[(i + 1)].x, coords[(i + 1)].y);
ctx.stroke();
} else {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[0].x, coords[0].y);
ctx.stroke();
}
}
So you have points that needs to connect to each other?
Use svg, if you don't want to use canvas.
<svg width="100" height="100">
<path d="M0 0 l100 10 l-40 90z" fill="none" stroke="black" stroke-width="2" />
</svg>
Path command for 8,8,10,10,30,30,49,10 would be M8 8 L10 10 L30 40 L49 10z.
<svg width="49" height="40" viewBox="0 0 50 41">
<path d="M8 8 L10 10 L30 40 L49 10z" fill="none" stroke="black" stroke-width="2" />
</svg>
To apply a click event to the shape, you could use pointer-events: all on #test.
#test {
pointer-events: all;
}
<svg width="49" height="40" viewBox="0 0 50 41">
<path id="test" d="M8 8 L10 10 L30 40 L49 10z" fill="none" onclick="alert('Works')" stroke="black" stroke-width="2" />
</svg>
Note: Posting this answer just because you asked with CSS3, but the complexity and possible calculation overhead involved in this approach is proof enough why CSS shouldn't be used for this. Please do not use this approach.
A bit of explanation on how this was achieved:
A div is created with top and right border (1px black) and the other two borders are set to none.
This div is then skewed a bit to make it appear as though the edge on the right side is a bit slanted.
Inside the shape, a pseudo-element with only a right border is created and it is also skewed to produce the diagonal line from the right-bottom to the left-top. Transform origin is set as right-bottom to avoid positioning overhead.
An anchor tag is added within the parent div and the overflow is set to hidden so that only the portion within the shape is clickable.
The user select on the anchor tag are disabled to prevent a double click from selecting a blank space within the div.
Finally the whole container div is rotated a bit to make it look as though the triangle is not parallel to x-axis.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 50px;
width: 45px;
border: 1px solid black;
border-left: none;
border-bottom: none;
-webkit-transform: skew(-10deg) rotate(5deg);
-moz-transform: skew(-10deg) rotate(5deg);
transform: skew(-10deg) rotate(5deg);
overflow: hidden;
}
a {
display: block;
content: '';
margin-left: 0px;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
height: 100%;
width: 100%;
}
div:after {
position: absolute;
top: 0px;
left: 0px;
content: '';
height: 50px;
width: 45px;
-webkit-transform: skew(42deg);
-webkit-transform-origin: left bottom;
-moz-transform: skew(42deg);
-moz-transform-origin: left bottom;
transform: skew(42deg);
transform-origin: left bottom;
border-right: 1px solid black;
}
<div>
</div>
Another option to create a skewed triangle shape would be to use clip-path like in below snippet. The shape is created by applying the same clip-path on the main container element and a pseudo-element which is smaller than the container.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 150px;
width: 150px;
background: black;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
div:after{
position: absolute;
content: '';
height: calc(100% - 5px);
width: calc(100% - 5px);
top: 2px;
left: 3px;
background: white;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 250px;
}
<div id="clickme"></div>
You can do it by embeding SVG as CSS. Quote from:
http://css-tricks.com/using-svg/
"Another way to use SVG's is to convert them into Data URI's. Data URI's might not save you actual file size, but can be more efficient because the data is right there. It doesn't require an additional HTTPRequest.
Mobilefish.com has an online conversion tool for that (http://www.mobilefish.com/services/base64/base64.php). Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back.
...
You can use that anywhere we've talked about so far (except inline because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.
As CSS
.logo {
background: url(data:image/svg+xml;base64,[data]);
}
"

SVG coordinates shifted

I'm trying to fit an svg into a div. The svg contains of a single path. I've set up viewBox and preserveAspectRatio correctly, I think, but a part of the path (which is supposed to fit entirely in the svg) is drawn outside the viewBox. Here's the fiddle, and here's the code:
html:
<div class='sparkline' class="ng-isolate-scope">
<svg viewBox="1 1 10 10" preserveAspectRatio="none">
<path d="M0,10L5,5L10,0"></path>
</svg>
</div>
css:
path {
stroke: blue;
stroke-width: 0.2;
fill: none;
}
.sparkline{
width: 200px;
height: 200px;
position:absolute;
top:0px;
left:0px;
border: 1px solid black;
margin: 20px;
}
svg{
width:100%;
height:100%;
display: block;
position: absolute;
top: 0px;
left: 0px;
}
I see no reason for the line to be shifted to the left, how can I overcome this?
Your code works as expected, but it possibly contains a typo. Provided that the viewBox is defined between 1 and 10, the line with 0 in X or/and Y should look shifted off the box.
Use viewBox="0 0 10 10" to fit the line into diagonal of the box.

How to make arc shapes with CSS3?

I'm trying to achieve following look, with pure css:
Where each white arc is a different element, say span. I know we can make round shapes with css, but how can it be turned into arc sort of shape?
With the following HTML:
<div id="arcs">
<div>
<div>
<div>
<div></div>
</div>
</div>
</div>
</div>
And the CSS:
#arcs div {
border: 2px solid #000; /* the 'strokes' of the arc */
display: inline-block;
min-width: 4em; /* the width of the innermost element */
min-height: 4em; /* the height of the innermost element */
padding: 0.5em; /* the spacing between each arc */
border-radius: 50%; /* for making the elements 'round' */
border-top-color: transparent; /* hiding the top border */
border-bottom-color: transparent;
}
#arcs div {
border: 2px solid #000;
/* the 'strokes' of the arc */
display: inline-block;
min-width: 4em;
/* the width of the innermost element */
min-height: 4em;
/* the height of the innermost element */
padding: 0.5em;
/* the spacing between each arc */
border-radius: 50%;
/* for making the elements 'round' */
border-top-color: transparent;
/* hiding the top border */
border-bottom-color: transparent;
}
<div id="arcs">
<div>
<div>
<div>
<div></div>
</div>
</div>
</div>
</div>
JS Fiddle demo.
SVG Approach:
I would recommend you to use SVG to draw such shapes:
In the example below I've used SVG's path element to draw an arc. This element takes single attribute d to describe the shape structure. d attributes takes a few commands and corresponding necessary parameters.
I've used only 2 path commands:
M command is used to move the pen to a specific point. This command takes 2 parameters x and y and usually our path begins with this command. It basically defines starting point of our drawing.
A command which is used to draw curves and arcs. This commands takes 7 parameters to draw an arc / curve. A detailed explanation of this command is Here.
Screenshot:
Useful Resources:
Specification
MDN
Working Example:
svg {
width: 33%;
height: auto;
}
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="arcs" fill="none" stroke="#fcfcfc">
<path d="M80,80 A100,100,0, 0,0 80,220" stroke-width="4" />
<path d="M90,90 A85,85,0, 0,0 90,210" stroke-width="3.5" />
<path d="M100,100 A70,70,0, 0,0 100,200" stroke-width="3" />
<path d="M110,110 A55,55,0, 0,0 110,190" stroke-width="2.5" />
</g>
</defs>
<rect x="0" y="0" width="300" height="300" fill="#373737" />
<use xlink:href="#arcs" />
<use xlink:href="#arcs" transform="translate(300,300) rotate(180)" />
</svg>