SVG coordinates shifted - html

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.

Related

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

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

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>

How to draw a curve by using div?

I need to draw two curves, using CSS.
I have tried to assemble some divs, using CSS border-radius to draw the curved panel. But the result is bad. Any better arithmetic?
As I had mentioned in comments earlier, please do not use CSS for achieving complex curves and shapes. While it is still possible to use CSS to achieve them (using transform + pseudo-elements like shown in this thread or using box-shadows in this thread), the process is very complex and you can't get much control over the shape, its curvature etc also. SVG on the other hand is designed for such graphics and it can also be scaled without any issues.
Below is a sample snippet on how to create the shape using a couple of cubic bezier curve (c) commands. The cubic bezier curve command takes 3 sets of parameters in total where the first two sets represent the coordinates of the control points for the initial and end points of the curve and the last set represents the coordinates of the actual end point of the curve.
You can control the curvature by modifying the control points.
.container {
position: relative;
width: 300px;
}
.container > div {
display: inline-block;
box-sizing: border-box;
}
.items {
width: 100%;
height: 250px;
border-radius: 10px;
border: 1px solid #BBB;
overflow: hidden;
}
.shape {
position: absolute;
top: 50%;
right: 0%;
height: 100px;
width: 40px;
transform: translateX(100%) translateY(-50%);
}
path {
stroke: #AAA;
fill: #DDD;
}
line {
stroke: #444;
}
<div class="container">
<div class="items">
</div>
<div class="shape">
<svg viewBox='0 0 50 100' preserveAspectRatio='none'>
<path d='M0,0
c10,15 40,15 48,35
v30
c-8,20 -38,20 -48,35'></path>
<line x1='15' y1='45' x2='30' y2='45' />
<line x1='15' y1='50' x2='30' y2='50' />
<line x1='15' y1='55' x2='30' y2='55' />
</svg>
</div>
</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]);
}
"

using svg line to imitate border of div

The end goal of this
use svg line to underscore border of div that contains it
webkit animation effects dash forwards to imitate border effects
If possible, the line to "be" the top border of the div
The problem is the extra padding below the top of the containing div. I do not know the source of the padding. Any tries at top: 0; or margin: 0; are unsuccessful.
Actual Results
The line is affected by unknown padding and pushed down a bit
I have an svg line with a div that contains it. This all happens in the ...
HTML
<div style = "display: inline;" id="divDisplay">
<svg height="1" width="1500">
<line id="top" x1="0" y1="0" x2="1500" y2="0" />
</svg>
</div>
CSS
#divDisplay {
background:linear-gradient(to bottom, #8dd2d9 , #58c0c7);
border: 2px solid #dadada;
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #111;
height: 100px;
}
#top {
top: 0;
position: fixed;
margin:0;
stroke: rgb(112,111,111);
stroke-width: 5;
stroke-dasharray:1300;
stroke-dashoffset:1300;
-webkit-animation: dash-top 3.00s forwards;
}
#-webkit-keyframes dash-top {
to { stroke-dashoffset: 0; }
}
This is because the <svg> element is inline by default, so vertical-align applies and defaults to baseline.
A quick fix is to change the vertical-align value: updated fiddle
svg {
vertical-align: top;
}
Not sure about the root cause, but adding the following css solved it.
#divDisplay svg
{
position:absolute;
top:1;
}
http://jsfiddle.net/wmeLa8tc/