Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 826
M-N Avatar asked Oct 18 '18 06:10

M-N


People also ask

Can you style SVG with CSS?

Not only does it mean that SVG properties can be styled using CSS as presentation attributes or in style sheets, but this also can be applied to CSS pseudo-classes such as :hover or :active . SVG 2 also introduces more presentation attributes that can be used as styling properties.

Can you nest grids in CSS?

You can "nest" grids by making a grid item a grid container. These grids however are independent of the parent grid and of each other, meaning that they do not take their track sizing from the parent grid. This makes it difficult to line nested grid items up with the main grid.


1 Answers

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>
like image 168
M-N Avatar answered Sep 19 '22 07:09

M-N