1

I'm trying to place bunch of divs side by side, left to right. So I'm using a flexbox with direction set to row.

I want each of those divs to derive their height and width from the content inside, hence I have left their height and width to default.

Lastly, I want to use an svg as the background. For that, I'm using a grid container and placing both the svg and the div in the same column and row as suggested in this stackoverflow post. Im setting the height and width of the svg to 100% to ensure it fills the whole background.

When I combine everything together, though, the width is of the divs are not being set properly. The height of the div seems to be set by the content inside, but the width seems to always default to 300px. For the life of me, I cant figure out how this width is being calculated. If the content is wider than 300px, then everything works as expected. But the container never shrinks to fit if the content is smaller than 300px.

How can I makes sure the divs are always shrunk to fit? See the code sample below:

.top {
  padding: 20px;
  display: flex;
  flex-direction: row;
}

.grid-container {
  background-color: red;
  display: grid;
}

.svg {
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  height: 100%;
}

.content {
  grid-column: 1;
  grid-row: 1;
  font-size: 100px;
}
This div has calculated width 300px for some reason
<div class="top">
  <div class="grid-container" key="1">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none">
      <polygon strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      ab
    </div>
  </div>
  <!-- more grid-containers -->
</div>

This works as expected
<div class="top">
  <div class="grid-container">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none">
      <polygon strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      abcdefghijkl
    </div>
  </div>
  <!-- more grid-containers -->
</div>
Cnoor0171
  • 368
  • 3
  • 12

3 Answers3

3

I was able to solve this by adding position: relative; to the .grid-container and position: absolute; to the svg and then giving the .content a z-index:1;

See here:

.top {
  padding: 20px;
  display: flex;
  flex-direction: row;
}

.grid-container {
  background-color: red;
  display: grid;
  width: auto;
  position: relative;
}

.svg {
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  height: 100%;
  position: absolute;
}

.content {
  grid-column: 1;
  grid-row: 1;
  font-size: 100px;
  z-index:1;
}
This div has calculated width 300px for some reason
<div class="top">
  <div class="grid-container" key="1">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none">
      <polygon id="diamond" strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      ab
    </div>
  </div>
  <!-- more grid-containers -->
</div>

This works as expected
<div class="top">
  <div class="grid-container">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none">
      <polygon strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      abcdefghijkl
    </div>
  </div>
  <!-- more grid-containers -->
</div>
John
  • 5,132
  • 1
  • 6
  • 17
2

You can try to use SVG as background image for the .grid-container (inline or linked), so you won't need to insert it into each single div. Importantly, the SVG must have preserveAspectRatio = 'none':

.top {
  padding: 20px;
  display: flex;
  flex-direction: row;
}

.grid-container {
  background-color: red;
  display: grid;
  background-image: 
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='-10 -10 20 20' preserveAspectRatio='none'> <polygon strokeWidth='0' fill='yellow' points='0,-10 10,0 0,10 -10,0'/> </svg>");
  background-repeat: no-repeat;
  background-size: cover;
}

.content {
  grid-column: 1;
  grid-row: 1;
  font-size: 100px;
}
<div class="top">
  <div class="grid-container" key="1">
    <div class="content">
      ab
    </div>
  </div>
  <!-- more grid-containers -->
</div>

<div class="top">
  <div class="grid-container">
    <div class="content">
      abcdefghijkl
    </div>
  </div>
  <!-- more grid-containers -->
</div>
1

There is a default width/height applied to SVG element creating this output. To avoid the issue make sure you set the attribute width/height to 0

.top {
  padding: 20px;
  display: flex;
  flex-direction: row;
}

.grid-container {
  background-color: red;
  display: grid;
}

.svg {
  grid-column: 1;
  grid-row: 1;
  width: 100%;
  height: 100%;
}

.content {
  grid-column: 1;
  grid-row: 1;
  font-size: 100px;
}
This div has calculated width 300px for some reason
<div class="top">
  <div class="grid-container" key="1">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none" width="0" height="0">
      <polygon strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      ab
    </div>
  </div>
  <!-- more grid-containers -->
</div>

This works as expected
<div class="top">
  <div class="grid-container">
    <svg class="svg" viewBox="-10 -10 20 20" preserveAspectRatio="none" width="0" height="0">
      <polygon strokeWidth="0" fill="yellow" points="0,-10 10,0 0,10 -10,0" />
    </svg>
    <div class="content">
      abcdefghijkl
    </div>
  </div>
  <!-- more grid-containers -->
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Thanks. I found in this [doc](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/width) that the svg width is supposed to be set to `300px` only if both `viewBox` and `width` attributes are unset, but that doesn't seem to be the case. The width gets set to `300px` even when `viewBox` is set. – Cnoor0171 Jun 14 '20 at 21:14
  • @Cnoor0171 you are correct. My answer wasn't very accurate but I was refering to intrinsic dimension created by the viewBox. First, you will notice that Firefox gives a complete different output for your code than chrome and you will not see the 300px of width but something else. I don't know exactly what browser is doing wrong also Flexbox and CSS grid make the caclulation more complex ... but at the end I knew that setting width/height to 0 would fix the issue. I will probably update later if I find a better explanation. – Temani Afif Jun 14 '20 at 21:35