Rotate svg in a div container - html

I created an svg. Since I need to rotate it by 45degree, I wrapped it in a div that I transform with a rotation.
It works but the svg overflows the window.
Here the code:
.container {
background-color: tomato;
transform: rotate(45deg);
width: max-content;
}
<div class="container">
<svg width="200" height="200" x="0" y="0">
<rect x="0" y="0" width="100" height="100" fill="pink" stroke="black" />
<rect x="100" y="0" width="100" height="100" fill="white" stroke="black" />
<rect x="0" y="100" width="100" height="100" fill="white" stroke="black" />
<rect x="100" y="100" width="100" height="100" fill="white" stroke="black" />
</svg>
</div>
This is what I would like to obtain:

I would rotate just svg, because you don't need to rotate whole container. You still need add some padding because, when you rotate square it is longer left to right than before.
.container {
width: max-content;
padding: 50px;
}
svg {
transform: rotate(45deg);
}
<div class="container">
<svg width="200" height="200" x="0" y="0">
<rect x="0" y="0" width="100" height="100" fill="pink" stroke="black" />
<rect x="100" y="0" width="100" height="100" fill="white" stroke="black" />
<rect x="0" y="100" width="100" height="100" fill="white" stroke="black" />
<rect x="100" y="100" width="100" height="100" fill="white" stroke="black" />
</svg>
</div>

Related

SVG file mask not being loaded with <use>

Let's say I have an SVG file test.svg
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="testsvg">
<mask id="mask3" x="0" y="0" width="100" height="100" >
<rect x="0" y="0" width="100" height="50"
style="stroke:none; fill: #ffffff"/>
<rect x="0" y="50" width="100" height="50"
style="stroke:none; fill: #666666"/>
</mask>
<rect x="1" y="1" width="100" height="100"
style="stroke: none; fill: #0000ff; mask: url(#mask3)"/>
</symbol>
</defs>
</svg>
If i try to use it like this in test.html
<svg>
<use href="test.svg#testsvg"/>
</svg>
The mask is not working I get a blue rectangle only. Doing an inspect element in firefox shows that the mask element is missing inside the shadow root. (Why ?)
The same thing as a direct inline SVG works just fine as expected, (I get two rectangles of different colors)
test2.html
<svg xmlns="http://www.w3.org/2000/svg">
<mask id="mask3" x="0" y="0" width="100" height="100" >
<rect x="0" y="0" width="100" height="50"
style="stroke:none; fill: #ffffff"/>
<rect x="0" y="50" width="100" height="50"
style="stroke:none; fill: #666666"/>
</mask>
<rect x="1" y="1" width="100" height="100"
style="stroke: none; fill: #0000ff; mask: url(#mask3)"/>
</svg>
Why is this happening?
Note To reproduce the above behavior security.fileuri.strict_origin_policy should be set to false in about:config in Firefox so that local files may be loaded

SVG: how to round stroke and rectangle corners?

Is it possible to round a rectangle in SVG while ensuring the stroke obeys the roundedness of corners? The code below isn't working.
No Stroke:
stroke-width="0px"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="0px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
With Stroke:
stroke-width="10px"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
The stroke seems to follow the original sharp corners instead of the rounded corners.
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
A wide string extends beyond the svg border of the canvas SVG. Therefore, the string is partially cropped.
You must reduce the size of the rectangle so that the line is visible and shift the upper left corner of the rectangle right and down x="5" and y="5"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="5" y="5" width="90" height="90" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
Update
ViewBox added. The coordinates of the rectangle x andy of the are increased, SVG wrapped in a container and can be embedded in an HTML page as a separate block. Adaptive application
.container {
width:30%;
height:30%
}
<div class="container">
<svg viewBox="0 0 110 110" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="90" height="90" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
</div>
As you can see from the picture, a square with a wide stroke is completely inside the SVG canvas
The first trivial solution is to make the overflow visible and add some margin to rectify this
svg {
overflow:visible;
margin:5px; /*half the stroke*/
}
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="150" height="80" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="100" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
Or you use calc() like below:
svg rect{
height:calc(100% - 10px);
width:calc(100% - 10px);
x:5px;
y:5px;
}
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="150" height="80" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="100" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
That can be used as background too:
.box {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" stroke="red" stroke-width="10" rx="10" ry="10" stroke-linejoin="round" /></svg>');
color: #fff;
padding:25px;
display:inline-block;
margin: 75px 0;
}
<div class="box"> Some text here</div>
<div class="box"> text very loooooooooooong here</div>
<div class="box"> a text <br> two line here</div>
<svg width="400" height="180">
<rect x="50" y="20" rx="20" ry="20" width="150" height="150"
style="fill:red;stroke:black;stroke-width:5;opacity:0.5" />
</svg>

How to embed svg into svg?

I have to perform this task in which i have to embed one svg into another svg.
As I am new to SVG, I have done the polygon and rectangle part but while combining these two I am facing issues. I am attaching my work up to which I have completed.
Don't have a bunch of SVGs. Instead you should just put all your shapes into one big SVG.
Below is a quick example. But remember, you might find it easier to just use one of the many available vector drawing apps to create your SVG.
<!DOCTYPE html>
<html>
<body>
<svg width="550" height="400">
<g>
<rect width="300" height="30" style="fill:rgb(255,0,0);" />
<text x="10" y="20" fill="white">Fatality</text>
</g>
<g transform="translate(0,40)">
<rect width="300" height="30" style="fill:rgb(255,0,0);" />
<text x="10" y="20" fill="white">Lost Time Incidents</text>
</g>
<g transform="translate(0,80)">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="10" y="20" fill="white">Restricted Work Cases</text>
</g>
<g transform="translate(0,120)">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="10" y="20" fill="white">Medical Treatment Cases</text>
</g>
<g transform="translate(0,160)">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="10" y="20" fill="white">First Aid Cases</text>
</g>
<g transform="translate(0,200)">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="10" y="20" fill="white">RTA Incident</text>
</g>
<g transform="translate(0,240)">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="10" y="20" fill="white">Environment Incident</text>
</g>
<g transform="translate(0,280)">
<rect width="300" height="30" style="fill:rgb(102,204,0);" />
<text x="10" y="20" fill="white">Near Miss</text>
</g>
<g transform="translate(0,320)">
<rect width="300" height="30" style="fill:rgb(102,204,0);" />
<text x="10" y="20" fill="white">Unsafe Acts & Conditions</text>
</g>
<g transform="translate(0,360)">
<rect width="300" height="30" style="fill:rgb(102,178,255);" />
<text x="10" y="20" fill="white">Man Hours</text>
</g>
<polygon points="350,0, 550,400, 150,400" style="fill:white;stroke:black;stroke-width:1" />
</svg>
In order to embed one svg into another svg you have to use it the same way you would use a <symbol> element.
const SVG_NS = 'http://www.w3.org/2000/svg';
let colors = [
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(255,128,0)",
"rgb(102,204,0)",
"rgb(102,204,0)",
"rgb(102,178,255)"
];
let angle = Math.atan2(215,430);
let n = 0;
let offset = 10;// distance between the border of the triangle and the start of the rectangle
for(let y = 40; y < 430; y+= 40){
let halfW = Math.tan(angle)*y - offset;
let o = {
x:430/2 - halfW,
y: y,
width: 2*halfW,
height: 30,
fill:colors[n]
}
drawRect(o, polys);
n++;
}
function drawRect(o, parent) {
let rect = document.createElementNS(SVG_NS, 'rect');
for (var name in o) {
if (o.hasOwnProperty(name)) {
rect.setAttributeNS(null, name, o[name]);
}
}
parent.appendChild(rect);
return rect;
}
svg{max-width:100vh}
<svg viewBox="0 0 600 600" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="400" height="30" y="40">
<rect width="300" height="30" style="fill:rgb(255,0,0);" />
<text x="0" y="15" fill="white">Fatality</text>
</svg>
<svg width="400" height="30" y="80">
<rect width="300" height="30" style="fill:rgb(255,0,0);" />
<text x="0" y="15" fill="white">Lost Time Incidents</text>
</svg>
<svg width="400" height="30" y="120">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="0" y="15" fill="white">Restricted Work Cases</text>
</svg>
<svg width="400" height="30" y="160">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="0" y="15" fill="white">Medical Treatment Cases</text>
</svg>
<svg width="400" height="30" y="200">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="0" y="15" fill="white">First Aid Cases</text>
</svg>
<svg width="400" height="30" y="240">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="0" y="15" fill="white">RTA Incident</text>
</svg>
<svg width="400" height="30" y="280">
<rect width="300" height="30" style="fill:rgb(255,128,0);" />
<text x="0" y="15" fill="white">Environment Incident</text>
</svg>
<svg width="400" height="30" y="320">
<rect width="300" height="30" style="fill:rgb(102,204,0);" />
<text x="0" y="15" fill="white">Near Miss</text>
</svg>
<svg width="400" height="30" y="360">
<rect width="300" height="30" style="fill:rgb(102,204,0);" />
<text x="0" y="15" fill="white">Unsafe Acts & Conditions</text>
</svg>
<svg width="400" height="30" y="400">
<rect width="300" height="30" style="fill:rgb(102,178,255);" />
<text x="0" y="15" fill="white">Man Hours</text>
</svg>
<svg id="polys" height="430" width="430" viewBox="0 0 430 430" x="160" >
<polygon points="215,0, 0,430 430,430 215,0" style="fill:white;stroke:red;stroke-width:1" />
</svg>
</svg>

How do maskUnits & maskContentUnits attributes affect mask positioning?

I've read a bit of the spec for the SVG mask element but the sections on maskUnits and maskContentUnits aren't clear to me, and also how they affect each other isn't clear to me.
From the spec:
maskUnits = 'userSpaceOnUse': x, y, width and height represent values in the current user coordinate system in place at the time when the mask element is referenced.
maskUnits = 'boundingBox': x, y, width and height represent fractions or percentages of the object bounding box of the element to which the mask is applied.
maskContentUnits = 'userSpaceOnUse': The user coordinate system for the contents of the mask element is the current user coordinate system in place at the time when the mask element is referenced.
maskContentUnits = 'boundingBox': The coordinate system has its origin at the top left corner of the bounding box of the element to which the clipping path applies to and the same width and height of this bounding box.
I've tried editing the maskUnits example and maskContentUnits example on MDN but whenever I change anything something unexpected happens, like the whole element disappears or the mask doesn't seem to be applied.
The snippet below is a sandbox with a few examples of the confusing behavior. I'd expect all of the squares to look different but there are 2 pairs each that are identical, and one of the pairs look like no mask was applied at all:
* {
margin: 0;
padding: 0;
}
body {
padding: 20px 0 0 20px;
}
.hidden {
width: 0;
height: 0;
margin: 0;
}
svg {
width: 100px;
height: 100px;
margin: 0 20px 20px 0;
display: block;
}
p {
margin-bottom: 10px;
font-family: monospace;
}
<!-- mask definitions -->
<svg viewBox="0 0 100 100" class="hidden">
<mask
id="usou-usou"
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="usou-obb"
maskUnits="userSpaceOnUse"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="obb-usou"
maskUnits="objectBoundingBox"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="obb-obb"
maskUnits="objectBoundingBox"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-usou)"
/>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-obb)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-usou)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-obb)"
/>
</svg>
We know what units are in ordinary life, there are inches, miles, kilometers etc.
One inch is not the same as one kilometre. If you draw a tiny picture, one inch across and you put a frame round it 2 inches across, the picture itself won't change if we make the frame 2 kilometres across. Equally, changing the picture size doesn't change how much is visible inside the picture frame unless the frame is too small for the picture.
maskUnits affect the units of the picture (mask) frame, maskContentUnits affect the units of the picture (mask).
objectBoundingBox units are defined such that 0 is the left side of the masked shape and 1 is the right side.
userSpaceOnUse units use the same co-ordinate system as the masked shape itself. If you mask a rect which extends from 50-100 then your mask ought to cover that area too if you want to mask the entire rect.
If you draw a circle with a radius of 100 kilometres centred 100 kilometres from the origin in both directions, then look at a square 1 millimetre across that starts at the origin, that square will have nothing drawn on it as everything is drawn outside that area.
We're masking
<rect x="0" y="0" width="100" height="100"/>
So our mask's x, y, width and height i.e.
<mask maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"/>
need to cover the same area (or more) if we want to mask that shape and they do.
If we had maskUnits="objectBoundingBox" we'd need
<mask maskUnits="objectBoundingBox" x="0" y="0" width="1" height="1"/>
Using 100 for the width and height would make the mask 100 times the size it needs to be but other than wasting lots of memory, it has no visible effect.
maskContentUnits work the same for the mask's content i.e.
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
Either they need to be 0..1 for objectBoundingBox or 0..100 for the shape. Since they are far too big for objectBoundingBox the mask is all one colour as the shapes are outside the area you can see i.e. the area over the shape.
<!-- mask definitions -->
<svg viewBox="0 0 100 100" class="hidden">
<mask
id="usou-usou"
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="usou-obb"
maskUnits="userSpaceOnUse"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="1" height="1" fill="white" />
<!-- if we wanted the same mask as above it would be r="0.25" -->
<circle cx=".5" cy=".5" r=".1" fill="black" />
</mask>
<!-- have the mask cover only the top left quarter of the shape -->
<mask
id="obb-usou"
maskUnits="objectBoundingBox"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="0.5"
height="0.5"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<!-- have the mask cover only the top left quarter of the shape -->
<mask
id="obb-obb"
maskUnits="objectBoundingBox"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="0.5"
height="0.5"
>
<rect x="0" y="0" width="1" height="1" fill="white" />
<!-- if we wanted the same mask as above it would be r="0.25" -->
<circle cx=".5" cy=".5" r=".1" fill="black" />
</mask>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-usou)"
/>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-obb)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-usou)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-obb)"
/>
</svg>

Keep <text> element scaled inside <svg> with viewBox

I'm trying to put some text as labels inside some scaled elements, and the text is too big to fit in the container. What can I do here?
<div class="t_container">
<div class="t_x" style="position: relative;">
<svg position="absolute" viewBox="0 0 6 1" preserveAspectRatio="none">
<g>
<rect x="0" y="0" width="1" height="0.4"><title>Nov-21</title></rect>
<text x="0.5" y="0.5" fill="red">A<text>
</g>
<rect x="1" y="0" width="1" height="1"><title>Nov-22</title></rect>
<rect x="2" y="0" width="1" height="1"><title>Nov-23</title></rect>
<rect x="3" y="0" width="1" height="1"><title>Nov-24</title></rect>
<rect x="4" y="0" width="1" height="1"><title>Nov-25</title></rect>
<rect x="5" y="0" width="1" height="1"><title>Nov-26</title></rect></svg>
</div>
Here is a codepen with the result.
You have a very small custom viewport="0 0 6 1" size. 6px - width, 1px - height, so the font can not be displayed with such parameters.
I increased the size of the viewBox 100 times viewBox="0 0 600 100"
Squares for clarity painted in different colors. You can change their coloring according to your choice.
The text is placed inside the squares. I hope that's exactly what you wanted when you used the command
<title> Nov-24 </ title> inside the squares.
But the command <title> in SVG is a system tooltip, the information from which appears when you hover the cursor.
The size of the tooltip and its font can not be changed, so I added in the squares more tags <text> ... </ text>, the parameters of which you can change.
<div class="t_container">
<div class="t_x" style="position: relative;">
<svg position="absolute" viewBox="0 0 600 100" >
<g>
<rect x="0" y="0" width="100" height="40"><title>Nov-21</title></rect>
<text x="35" y="75" font-size="36" fill="red">A</text>
</g>
<rect x="100" y="0" width="100" height="100" fill="orange">
<title>Nov-22</title></rect>
<text x="125" y="55" font-size="18" fill="white">Nov-22</text>
<rect x="200" y="0" width="100" height="100" fill="orangered">
<title>Nov-23</title></rect>
<text x="225" y="55" font-size="18" fill="white">Nov-23</text>
<rect x="300" y="0" width="100" height="100" fill="green">
<title>Nov-24</title></rect>
<text x="325" y="55" font-size="18" fill="white">Nov-24</text>
<rect x="400" y="0" width="100" height="100" fill="dodgerblue">
<title>Nov-25</title></rect>
<text x="425" y="55" font-size="18" fill="white">Nov-25</text>
<rect x="500" y="0" width="100" height="100" fill="yellowgreen">
<title>Nov-26</title></rect>
<text x="525" y="55" font-size="18" fill="white">Nov-26</text>
</svg>
</div>