skip to Main Content

I am trying to dynamically create an SVG image within JS in a static HTML document. I created an empty iframe element on my page. Please note that I am using this as a learning exercise so it’s built with static elements. I am not referencing any external sites (thus no bootstrap or other packages).

The iframe code I am currently using (on the .html page) is below.

In my JS code I want to adjust the height and width to create a box surrounding my SVG image. The SVG header I generated is:
The challenge I can’t overcome is that when the width and height dimensions from the svg header are assigned to the iframe height and width, I get a vertical scroll bar on the right side. If I add 16 units to the iframe height the scroll bar goes away but now there’s a blank area at the bottom of the image. When I examine it in the browser (Chrome) developer tools I can’t get a fix on what that area is a part of. I’ve played with padding, margins, and anything else I can find that makes sense. I may resort to having no border around my iframe (which is ok) but I’d like to learn from this what can be done.

As a side note, I have seen advice on the web about using a div element inside my iframe and that’s ok too. I’m not sure it’s significant but the svg image I am generating will be downloaded and used as a standalone image, hence my use of an iframe in the first place.

Thank you for your patience in this long winded question.

On my html page:

    <iframe
      id="ifBarcodeImage"
      name="ifBarcodeImage"
      style="border:1px solid red; padding:0px; margin:0px; display:auto"
      height="200px"
      width="200px"
      srcdoc=""
    />

And generated in my js code:

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 324 120" enable-background="new 0 0 324 120" xml:space="preserve">
.
.
.
</svg>

Finally, this is a screen clipping of the resulting image. Ideally I would like the blue rectangle to display inside the red rectangle with no border/padding around it. Alternately, I would be alright with the whole svg image centered in the iframe. The blue rectangle is my attempt to see the outer limits of the view box and will not be part of my finished project.

enter image description here

2

Answers


  1. You just need to add the attribute scrolling=“no” to your iframe. Technically it was deprecated years ago when HTML5 was first released, however, every browser fully supports this and that is unlikely to ever change, as it would break too many existing websites. Currently this still cannot be achieved with CSS.

    Login or Signup to reply.
  2. For an SVG to fit in its container you need to set preserveAspactRatio="none" on the SVG

    No need for an IFRAME when you

    • create a native Web Component <fit-svg src="your.svg">,
      with shadowDOM so you don’t have to worry about CSS or duplicate IDs in your SVG
    • that fetches the external SVG defined in the src attribute
    • sets all required <style>
    • injects the fetched SVG
    • sets preserveAspactRatio="none" on the SVG
    • since everyone complains about shadowDOM being difficult to style,
      I wacked in an extra ...this.children to move all lightDOM to shadowDOM
    <script>
      // define <fit-svg> anytime you like. There is no ONLOAD/PARSED dependency
      customElements.define("fit-svg", class extends HTMLElement {
        async connectedCallback() {
          this.attachShadow({mode:"open"}).innerHTML = "";
          this.shadowRoot.append(
              Object.assign(document.createElement("style"), {
                  innerHTML: ":host{ display:inline-block   }" +
                             "div  { width:100%;height:100% }" +
                             "svg  { height:100%;width:100% }"
              }),
              Object.assign(document.createElement("div"), {
                  innerHTML: await (await fetch(this.getAttribute("src"))).text()
              }),
              ...this.children
          )
          this.shadowRoot.querySelector("svg")
                         .setAttribute('preserveAspectRatio', 'none');
        }
      })
    </script>
    <style>
      #SVG1 { width:100px;height:150px;background:pink }
      #SVG2 { width:300px;height:180px;background:pink }
    </style>
    <!-- NOW ALL HTML REQUIRED IS: -->
    <fit-svg id=SVG1 src="//svg-cdn.github.io/heart.svg">
         <style> path:nth-child(2n+2) { fill: GREEN } </style>
    </fit-svg>
    <fit-svg id=SVG2 src="//svg-cdn.github.io/heart.svg">
         <style> path:nth-child(2n+2) { fill: RED } </style>
    </fit-svg>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search