In this document:
html, body {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden
}
#content {
width: 100%;
height: 100%
}
<div id="content">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="90%" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid meet">
<rect style="fill:none;stroke:black" width="540" height="157" x="690" y="26"></rect>
<text style="font-size:148px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="145">Test</text>
<text style="font-size:112px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="340">Lorem ipsum etc etc</text>
<foreignObject x="10" y="726" width="1901" height="347">
<div xmlns="http://www.w3.org/1999/xhtml" style="width:99.6%;height:97.7%;border:4px solid blue">
<p style="text-align:center">Hello World, from HTML inside SVG.</p>
</div>
</foreignObject>
</svg>
<div style="width:99%;border:4px solid blue">
<p style="text-align:center">Hello World, from HTML outside SVG.</p>
</div>
</div>
I'm using a viewBox to rescale an arbitrary-size SVG so that it fills the browser window (normally the 90% height on the svg is 100%; I've reduced it here for illustrative purposes). Within that SVG is a foreignObject containing some HTML to be rendered.
As it stands, the rendered HTML output is being rescaled to fit the viewBox coordinates as well; notice how the border width and text size for the inside-svg content is different from that outside, and that it changes when the window is resized.
I want the location and size of the foreignObject
to define the bounding box of the internal div, but I don't want it to actually rescale the contents, just to reflow them. Is there a way to do this?
(The text at the top also rescales with the window, but this is desired in that case.)
Note that I can't move or remove the viewBox. I can put the internal div outside of the svg and use JavaScript to size it, but I don't know how to set its bounding box (but not scale) to where it would be if it were inside.
(An unrelated thing that I don't understand is that I have to specify the width/height of the divs as less than 100% or it crops the border, both inside and outside. This might just be a Chrome thing though and isn't really important; I'm just curious.)
Edit After AmeliaBR's answer, this is the code I've come up with:
function svgTransform(x, y, matrix, svg) {
var p = svg.createSVGPoint();
p.x = x;
p.y = y;
return p.matrixTransform(matrix);
}
function svgScreenBounds(svgElement) {
var matrix = svgElement.getScreenCTM();
var r = svgElement.getBBox();
var leftTop = svgTransform(r.x, r.y, matrix, svgElement.ownerSVGElement);
var rightBottom = svgTransform(r.x + r.width, r.y + r.height, matrix, svgElement.ownerSVGElement);
return {
x: leftTop.x,
y: leftTop.y,
width: rightBottom.x - leftTop.x,
height: rightBottom.y - leftTop.y
};
}
function adjustOverlay() {
var placeholder = document.getElementById('placeholder');
var overlay = document.getElementById('overlay');
var bounds = svgScreenBounds(placeholder);
overlay.style.left = bounds.x + 'px';
overlay.style.top = bounds.y + 'px';
overlay.style.width = bounds.width + 'px';
overlay.style.height = bounds.height + 'px';
overlay.style.display = 'block';
}
html,body { height: 100%; margin: 0; padding: 0; overflow: hidden }
#content { width: 100%; height: 100% }
#overlay {
display: none;
position: absolute;
border:4px solid blue;
box-sizing: border-box;
}
<body onload="adjustOverlay()" onresize="adjustOverlay()">
<div id="content">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid meet">
<rect style="fill:none;stroke:black" width="540" height="157" x="690" y="26"></rect>
<text style="font-size:148px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="145">Test</text>
<text style="font-size:112px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="340">Lorem ipsum etc etc</text>
<rect style="fill:yellow;stroke:black" width="1901" height="100" x="10" y="618" rx="20" ry="20"></rect>
<text style="font-size:64px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="685">Bottom banner text</text>
<rect style="visibility:hidden" x="10" y="726" width="1901" height="347" id="placeholder"></rect>
</svg>
</div>
<div id="overlay">
<p style="text-align:center">Hello World, from HTML outside SVG.</p>
</div>
</body>
It seems to behave as expected. (And the reason for the less-than-100% widths was because I needed box-sizing: border-box
-- which I had tried on the html
element's style before asking the question, but it had no effect there; apparently it needs to be applied directly rather than inherited.)