Search code examples
htmlcsssvgimage-scalinginline-svg

*Inline* SVG image scales placed in *file* it does not


I have an SVG image that scales beautifully when it is inlined in my HTML, but if I move the very same SVG to a file and try to IMG or OBJECT tag that file in my HTML it simply won't scale.

(I know there are similar questions here but usually the other way around.)

I have read this great article, and others, and I have also read through StackOverflow but still no answers.

BTW I copied the potofgold.svg from Amazon and that behaves perfectly so I guess it must be my particular SVG.

The only thing different that I noticed is my SVG tag looks like: -

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewbox="0 0 250 182.6" style="enable-background:new 0 0 250 182.6;" xml:space="preserve">

And the pot of gold is: -

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 55" >

If I try to trim "redundant" and deprecated options from my SVG tag the browser refuses to display the image. Outdated SVG?

Anything I can do to get the image to scale when it's sourced from a file?

EDIT 1:

It's option C here if it helps. Western Australian State Coat of Arms. Is it because it doesn't have a "defs" section?

Further info for @patrick.

I had to un-optimize the SVG so that I could add variables to the colors and an external stylesheet that could be modified by Javascript (if need be): -

   <style>
    <![CDATA[<!--<!--
        .st1{fill:var(--coa-bg-color);}
        .st2{fill:var(--coa-bg-color);fill-rule:evenodd;clip-rule:evenodd}
        .st3{fill:none;stroke:var(--coa-bg-color);stroke-width:1.78}
        .st5{fill:none;stroke:var(--coa-bg-color);stroke-width:.45}
        .st6{fill:none;stroke:var(--coa-bg-color);stroke-width:.67}
        .st7{fill:none;stroke:var(--coa-bg-color);stroke-width:.45;stroke-miterlimit:5}
        ]]>
    </style>

But regarding height let me once again draw attention to the ridiculously important: -

        min-height: 0;

On the parent flex container!!!

Anyway here's the functionality Demo I'm working on: -

<!DOCTYPE html>
<html>
<head>
<script type="application/javascript">
    window.addEventListener("load", () =>
        {
            var imageDOM = document.getElementById("crest").contentDocument;
            var svgRoot = imageDOM.querySelector(':root');
            svgRoot.style.setProperty('--coa-bg-color', '#ffd700');
            
            var crest = imageDOM.getElementById("wa_state_crest");
        });
</script>
<style type="text/css">
:root {
  --main-bg-color: #002f5f;
}
    @-ms-viewport{
        width: device-width;
        height: auto;
    }   
    *, *:before, *:after{
        box-sizing: inherit;
        -webkit-touch-callout: none;
        -webkit-tap-highlight-color: rgba(0,0,0,0);
        -moz-user-select: none;
    }       
    ::-ms-clear{
        display: none;
    }       
    html, body{
        margin: 0px;
        box-sizing: border-box;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -ms-user-select: none;
        user-select: none;
        -ms-overflow-style: none;
        -ms-content-zooming: none;
        touch-action: manipulation;
    }
    body {
        background-image: radial-gradient(#fff, #1ecbe1, #ADD8E6);
        overscroll-behavior: none;
        pointer-events: auto;
        display: flex;
        font-size: 14px;
        flex-direction: column;
        height: 100vh;
        padding: 1em;
    }   
    
    .wholeScreen{
        display: flex;
        flex-direction: column;
        height: 100%;
        min-height: 0px;
    }   

    div#headerDiv{
        display: flex;
        order: 1;
        width: 100%;
        padding: 0.5em;
        align-items: center;
        flex-grow: 10;
        flex-shrink: 10;
        flex-basis: 10%'
    }

.field__items {
        display: flex;
        order: 2;
        align-items: center;
        flex-grow: 90;
        flex-shrink: 90;
        flex-basis: 90%;
        min-height: 0;
}
.field__item {
    display: flex;
    order: 3;
    justify-content: center;
    align-content: center;
    flex-basis: 100%;
    flex-grow: 1;
    flex-shrink: 1;
    max-height: 100%;
    padding: 3em;
}

#crest {
    animation-name: spin;
    animation-duration: 5000ms;
    animation-iteration-count: 3;
    animation-timing-function: linear;
}

@keyframes spin {
    from {
        transform: rotateY(0deg);
    }

    to {
        transform: rotateY(360deg);
    }
}

</style>
</head>
<body>
<div class="wholeScreen">
   <div id="headerDiv">
     <h1>Coat of Arms</h1>
   </div>
   <div class="field__items">
        <div class="field__item">
          <object id="crest" title="Government of Western Australia" alt="Western Australian Coat of Arms" data="coa.svg" type="image/svg+xml"></object>
        </div>
    </div>
</div>
</body>
</html>

Thanks again for the help.


Solution

  • Since your edit with the link to the concerned page, I had a look at the page and I notice that the table has different column widths, leading to different rendering widths of the SVG images. And effectively, Option C seems narrower and therefore the SVG images scales smaller.

    Just playing around with Chrome's inspector and adding these CSS rules, you'll notice a different rendering:

    /*
    My idea was: (4 x 22%) + (3 x 4%) = 100%
    
    But it's not correct due to padding and borders, so the browser
    will try to correct. So, instead, I'll set the seperating empty
    columns to a width of 0% as there's already some padding.
    
    Use !important to override the inline style attributes.
    */
    
    /* Columns containing text and images */
    #summary-state-coat-of-arms table td:nth-child(2n+1) {
      width: 22% !important;
    }
    
    /* Spacing columns (empty) */
    #summary-state-coat-of-arms table td:nth-child(2n) {
      width: 0% !important;
    }
    
    

    I didn't try replacing your inlined SVG images by external images. I just noticed that the problem may be due to the table structure and not the SVG resizing problem.

    Also, I notice that your "Option C" image in black has a viewBox height set to 240.85 and the same image in white (for the black background) has a viewBox height of 182.6, but both have the same width. I suggest you should reduce the height of the black one. This is probably the reason it doesn't center vertically even if you have preserveAspectRatio="xMidYMid meet", which is the default behavior.

    Edit, after some comments

    Just a question: Are the HTTP headers sending the correct MIME type for all the SVG images set in the src attribute of the <img> tags?

    It's just an idea, but perhaps this could make some browser have unwanted behaviours.

    Taking your SVG images as there are, formatting/optimizing them in SVG OMG and then setting them as data:image/svg+xml;base64,.... seems to work like expected on this Codepen proof of concept I made.