Search code examples
htmlcsssvggrid-layout

HTML grid layout disrupted by SVG child element


I'm trying to make a page with a simple 3x3 grid layout: header top, footer bottom, two sidebars, and the main display. Everything works fine until I add the SVG element that should fill the main-display div:

<div class="main">
  <svg viewBox="0 0 500 500"></svg>
</div>

The whole grid layout gets confused at this point, with the browser eliminating the header, extending the page below the height: 100% that I have declared, etc.

I can easily "fix" this by setting my SVG max-height and max-width arbitrarily small (below ~60% in Firefox 62.0.3; in Safari 12.0, <90%). But that isn't really a fix since it leaves a conspicuous gap (a huge one in Firefox). I much prefer to size my SVG 100% to fill its space in the grid. I must be missing something. What am I doing wrong?

Edit: Adding a screenshot of what I want and (one version of) what I have.

Here is what I have. Here is what I want.

The stylesheet for what you see is below. The only difference between the two images is the change in max-width and max-height from 10% to 100%.

    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      display: grid;
      border-style: solid; // to show that body renders improperly
      border-color: red;
      grid-template-columns: 3fr 9fr 2fr;
      grid-template-rows: 1fr 10fr 1fr;
      width: 100vw;
      height: 100vh;
    }

    div {
      border: solid black 1px; // to show div positions
    }

    .header {
      grid-column: 1 / 4;
      grid-row: 1;
    }

    .main {
      grid-column: 2;
      grid-row: 2;
    }

    .side1 {
      grid-column: 1;
      grid-row: 2;
    }

    .side2 {
      grid-column: 3;
      grid-row: 2;
    }

    .footer {
      grid-column: 1 / 4;
      grid-row: 3;
    }

    svg {
      max-height: 100%; 
      max-width: 100%;
    }
<body>
  <div class="header">Header</div>
  <div class="side1">Site 1</div>
  <div class="main">
    <svg viewBox="0 0 500 500"></svg>
  </div>
  <div class="side2">Site 2</div>
  <div class="footer">Footer</div>
</body>


Solution

  • It turns out that the problem is not with the svg element at all, but with its containing div (.main in the question's code snippet). Like flex items, grid items have a default min-width: auto and min-height: auto. By setting them to 0, the svg is able to size automatically, as it should.

    I still don't quite understand why the svg disrupted the layout, especially when it was set to 80% in Firefox, leaving conspicuous space around it, but the problem with the grid layout itself is clear enough.

        * {
          box-sizing: border-box;
          margin: 0;
          padding: 0;
        }
    
        body {
          display: grid;
          grid-template-columns: 3fr 9fr 2fr;
          grid-template-rows: 1fr 10fr 1fr;
          width: 100vw;
          height: 100vh;
        }
    
        div {
          border: solid black 1px; // to show div positions
        }
    
        .header {
          grid-column: 1 / 4;
          grid-row: 1;
        }
    
        .main {
          grid-column: 2;
          grid-row: 2;
          min-width: 0;
          min-height: 0;
        }
    
        .side1 {
          grid-column: 1;
          grid-row: 2;
        }
    
        .side2 {
          grid-column: 3;
          grid-row: 2;
        }
    
        .footer {
          grid-column: 1 / 4;
          grid-row: 3;
        }
    
        svg {
          max-height: 100%; 
          max-width: 100%;
        }
    <body>
      <div class="header">Header</div>
      <div class="side1">Site 1</div>
      <div class="main">
        <svg viewBox="0 0 500 500"></svg>
      </div>
      <div class="side2">Site 2</div>
      <div class="footer">Footer</div>
    </body>