title: Is it possible to escape an SVG viewbox? (or how to position HTML DIV over scaled/transformed SVG?)
body: <p>In this document:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-css lang-css prettyprint-override"><code>html, body {
    height: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden
  }
  #content {
    width: 100%;
    height: 100%
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;div id="content"&gt;
    &lt;svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="90%" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid meet"&gt;
      &lt;rect style="fill:none;stroke:black" width="540" height="157" x="690" y="26"&gt;&lt;/rect&gt;
      &lt;text style="font-size:148px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="145"&gt;Test&lt;/text&gt;
      &lt;text style="font-size:112px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="340"&gt;Lorem ipsum etc etc&lt;/text&gt;
      &lt;foreignObject x="10" y="726" width="1901" height="347"&gt;
        &lt;div xmlns="http://www.w3.org/1999/xhtml" style="width:99.6%;height:97.7%;border:4px solid blue"&gt;
          &lt;p style="text-align:center"&gt;Hello World, from HTML inside SVG.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/foreignObject&gt;
    &lt;/svg&gt;
    &lt;div style="width:99%;border:4px solid blue"&gt;
      &lt;p style="text-align:center"&gt;Hello World, from HTML outside SVG.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>I want the location and size of the <code>foreignObject</code> 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?</p>
  
  <p>(The text at the top also rescales with the window, but this is desired in that case.)</p>
  
  <p>Note that I can't move or remove the viewBox.  I <em>can</em> 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.</p>
  
  <p>(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.)</p>
  
  <hr>
  
  <p><strong>Edit</strong> After <a href="https://stackoverflow.com/a/26126266/43534">AmeliaBR's answer</a>, this is the code I've come up with:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>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';
  }</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>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;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;body onload="adjustOverlay()" onresize="adjustOverlay()"&gt;
    &lt;div id="content"&gt;
      &lt;svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid meet"&gt;
        &lt;rect style="fill:none;stroke:black" width="540" height="157" x="690" y="26"&gt;&lt;/rect&gt;
        &lt;text style="font-size:148px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="145"&gt;Test&lt;/text&gt;
        &lt;text style="font-size:112px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="340"&gt;Lorem ipsum etc etc&lt;/text&gt;
        &lt;rect style="fill:yellow;stroke:black" width="1901" height="100" x="10" y="618" rx="20" ry="20"&gt;&lt;/rect&gt;
        &lt;text style="font-size:64px;text-align:center;text-anchor:middle;fill:black;stroke:none" x="960" y="685"&gt;Bottom banner text&lt;/text&gt;
        &lt;rect style="visibility:hidden" x="10" y="726" width="1901" height="347" id="placeholder"&gt;&lt;/rect&gt;
      &lt;/svg&gt;
    &lt;/div&gt;
    &lt;div id="overlay"&gt;
      &lt;p style="text-align:center"&gt;Hello World, from HTML outside SVG.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/body&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>It seems to behave as expected.  (And the reason for the less-than-100% widths was because I needed <code>box-sizing: border-box</code> -- which I had tried on the <code>html</code> element's style before asking the question, but it had no effect there; apparently it needs to be applied directly rather than inherited.)</p>