Weird overflow inside foreignObject elements - svg

I get some weird overflow whenever I want to fit an object inside foreignObject tag.
Take the code below. Instead of expanding to 100x100, the box expands to 120px, which is double the border width. I've tried nearly everything in my mind to counteract this effect, but nothing seems to solve the issue.
<svg width="4in" height="3in" version="1.1"
xmlns = 'http://www.w3.org/2000/svg'>
<foreignObject width="100" height="100">
<div style="width:100%;height:100%;background-color: #fcefa1;border:10px solid #ff0000;"></div>
</foreignObject>
</svg>

It's double the border width because you have a border on both sides, ten plus ten is twenty. Try this:
<svg width="4in" height="3in" version="1.1"
xmlns = 'http://www.w3.org/2000/svg'>
<foreignObject width="100" height="100">
<div style="width:100%;height:100%;background-color: #fcefa1;border:10px solid #ff0000; -moz-box-sizing: border-box; box-sizing: border-box;"></div>
</foreignObject>
</svg>
The box-sizing CSS property lets you control what the width applies to.

Related

CSS transform-origin on <g> element for centered rotation?

I don't quite understand the transform-origin CSS rule.
If you have a plain <svg> with changing sizes (width, height) and some <rect> elements in it, how can you rotate a <g> element in it correctly?
It should be right next to the <rect>, so I am using transform: translate(x,y).
Then I'd like to rotate the group with rotate(45), but it ends up at strange places:
HTML
<div class="box">
<svg class="svg-main" width="600px" height="600px">
<rect x="0" y="50" width="90" height="40" fill="blue" stroke="blue"></rect>
<g transform="translate(100,50),rotate(7)"
transform-origin="center"
class="group">
<path d="M38.15,20.54,28.9,11.29a1.4,1.4,0,0,0-2.4,1v1.89a1.41,1.41,0,0,1-1.4,1.41H3.2A1.4,1.4,0,0,0,1.79,17v9.11a1.41,1.41,0,0,0,1.41,1.4H25.1a1.41,1.41,0,0,1,1.4,1.41v1.89a1.41,1.41,0,0,0,2.4,1l9.25-9.25A1.41,1.41,0,0,0,38.15,20.54Z" stroke="#000" strokeMiterlimit="10" strokeWidth="2"/>
</g>
</svg>
</div>
CSS
div.box {
padding: 30px;
background-color: #dfcfcf;
}
svg.svg-main {
background-color: white;
border: 2px solid #dedada;
}
svg.svg-main g.group path {
fill: rgba(215, 20, 45, 0.5);
}
JSFiddle
https://jsfiddle.net/bair_web/ajLgzoey/
Result for 17deg
Where is the origin?
Question
I would like to rotate the group with its <path> and using center for transform-origin.
MDN
How can I achieve a simple, centered rotation of a group in an SVG, which is also translated? It seems like transform-origin points to the parent element (the SVG)? So do I need to calculate the position of the<g> element relative to the <svg> elment and use it for transform-origin?
Because, when I just omit the origin, the rotated group also moves around and does not keep its center.

Half of line stroke is hidden on the SVG edge

If SVG line touches SVG edge, half of the line stroke will be outside of SVG and will be hidden (see example of line chart below, last tick at the right has half-width tickness).
What are the techincs to avoid it? Is there a way to scale out SVG a little bit, so the SVG image will be smaller and don't touch SVG borders? Something like adding padding?
I'm using non-fixed aspect ratio as height:1rem and width:100%, as it's supposed to take all the place available.
The viewbox scaling doesn't work
svg {
display: block;
}
.chart {
width: 300px;
border: 1px solid #ccc;
}
<div class="chart">
<svg height="1rem" width="100%" class="text-left" viewBox="-5% 0 105% 1rem">
<line x1="25%" y1="5%" x2="25%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<line x1="50%" y1="5%" x2="50%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<line x1="100%" y1="5%" x2="100%" y2="25%" stroke="#6B7280" stroke-width="2"></line>
<rect x="0%" y="25%" width="15.138888888888888%" height="50%" fill="#111827"></rect>
</svg>
</div>

How to dynamically size an SVG pattern to the size of it's children?

I'm trying to create a text based SVG fill pattern that is dynamic (any text could be used).
I want the text to repeat horizontally and vertically, without having to define width/height of the text object in the pattern definition. This Answer provided a lot of info regarding patternUnits, but it wasn't enough to answer my specific question. The pattern seems to require either absolute width/height (doesn't work with dynamic content) or relative % values that are based on the SVG canvas.
Is it possible for a pattern definition to be sized dynamically to fit its children's bounding box (supporting arbitrary text), while using userSpaceOnUse for the pattern's children to set pixel values?
The usecase is consuming user-provided text, so predefined widths/sizes do not work; the solution needs to be agnostic to the text content.
svg{width:100%;height:100%;}
body{height: 100vh;}
body, html{padding:0;margin:0;}
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="GPattern" x="0" y="0" width="100%" height="100%" patternUnits="userSpaceOnUse">
<text id="text" x="0" y="34" width="100%" height="100%"
style="font-family: Arial;
font-size : 34;
font-weight: 800;
stroke : #000000;
fill : #00ff00;
"
>This Text Should Be Dynamic</text>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#GPattern)"/>
</svg>
Goal Output:
Right now the solution I am considering would be to use JS to calculate an absolute width based on content string.length and manually edit the pattern's width attribute, but would prefer if SVG can calculate this automagically.
Leveraging the answer in https://stackoverflow.com/a/13873631/1577447, you can use Javascript to adjust the size of your pattern.
You can trigger adjustPatternSize() every time your code changes. I’ve baked in the default values in case you want to run this in a context where JS isn’t available.
svg{width:100%;height:100%;}
body{height: 100vh;}
body, html{padding:0;margin:0;}
input { position: absolute; left: 10%; bottom: 10%; }
<input id="textInput" type="text" value="This Text Is Dynamic">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="GPattern" x="-4" y="-1" width="483" height="46" patternUnits="userSpaceOnUse">
<text id="text" x="0" y="34" width="100%" height="100%"
style="font-family: Arial;
font-size : 34;
font-weight: 800;
stroke : #000000;
fill : #00ff00;
"
></text>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#GPattern)"/>
<script type="text/javascript">
const padding = 4
const text = document.getElementById("text");
const rect = document.getElementById("GPattern");
const input = document.getElementById("textInput");
input.oninput = handleInput;
function handleInput(e) {
adjustPatternSize(e.target.value)
}
function adjustPatternSize(string) {
text.textContent = string;
const bbox = text.getBBox();
rect.setAttribute("x",bbox.x - padding);
rect.setAttribute("y",bbox.y - padding );
rect.setAttribute("width",bbox.width + 2*padding);
rect.setAttribute("height",bbox.height + 2*padding);
}
adjustPatternSize("This Text Is Dynamic");
</script>
</svg>

Changing height and width of highchart svg

Does anyone know a method of changing the height and width of an svg image of a highchart. I'm getting the svg code using
var svg = chart1.getSVG();
The code itself then is :
<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="font-family:'lucida grande', 'lucida sans unicode', arial, helvetica, sans-serif;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="600" height="300"><desc>Created with Highstock 4.2.5</desc><defs><clipPath id="highcharts-11"><rect x="0" y="0" width="517" height="300"></rect></clipPath></defs><rect x="0" y="0" width="600" height="300" fill="#FFFFFF" class=" highcharts- ... etc
I've tried changing the height and width properties in this piece of code but it doesn't seem to work properly. I've also tried using the Viewbox method as well but that seems to make it too small. realistically I just need to change the height as the width seems to be okay, but if I could I would like to increase the width a small bit.I'm trying to print the svg in a pdf to show the charts but their not showing up true to their size (which is expected)
Any Ideas?
Thanks!

How to position an svg to vertically fill a variable height div?

I've created some svg graphics that I would like to set as backgrounds in some variable height divs. I'm trying to use them as a sprite, so one svg file has a few groups, each with its own id, and I'm using those ids to specify which background is rendered in each div.
Here's a link to a (non-working) JSFiddle.
HTML:
<svg width="0" height="0">
<defs>
<!-- BLUE GRAPHIC -->
<g id="blue_background">
<polygon fill="#C8D9E5" points="[...in the fiddle...]"/>
</g>
<!-- GREEN GRAPHIC -->
<g id="green_background">
<path fill="#49B974" d="[...in the fiddle...]"/>
</g>
</defs>
</svg>
<div class="box">
<h1>asdasdasd</h1>
<h1>asdasdasd</h1>
<h1>asdasdasd</h1>
<svg class="svg1" viewBox="0 0 600 200" >
<use xlink:href="#blue_background" width="100%" height="100%"></use>
</svg>
</div>
<div class="box">
<h1>asdasdasd</h1>
<h1>asdasdasd</h1>
<h1>asdasdasd</h1>
<svg class="svg2" viewBox="0 0 200 200">
<use xlink:href="#green_background" width="100%" height="100%"></use>
</svg>
</div>
Ideally the graphic would be aligned with the right side, and stretch to fill the div's height.
Thanks
Since you're describing your SVGs as "backgrounds", I assume you don't need them to push text out of the way.
In that case, I would recommend using absolute positioning for the SVGs (relative to the "box" containers). With absolute positioning, a height of 100% is valid even if the parent element doesn't have fixed height.
.box {
position: relative;
width: 400px;
border: 1px solid #ddd;
}
svg {
position:absolute;
height:100%;
top:0; right:0;
z-index:-1;
}
http://jsfiddle.net/svag2/1/

Resources