2

In my attempt to create a responsive grid area with an svg image inside I have run into odd behaviour such as arbitrary grid area widths, and inability to have the image grow or shrink to a certain point than stop. The closest I have gotten is the following:

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

header {
    display: grid;
    grid-template-columns: auto 1fr;
    background-color: green;
    padding: 1rem;
}

img {
    width: 100%;
    max-width: 25vw;
    min-width: 12rem;
    background-color: pink;
}

div {
    background-color: red;
    text-align: center;
}

nav {
    background-color: yellow;
    grid-column: span 2;
}
<header>
  <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 324 413.28'%3E%3Crect class='655de5e2-44d3-4b5a-ae63-e6e7ec799246' x='18' y='18.12' width='288' height='324' fill='blue'/%3E%3C/svg%3E">
  <div>
    <h1>Heading</h1>
    <p>Text Line 1</p>
    <p>Text Line 2</p>
    <p>Text Line 3</p>
  </div>
  <nav>
    <a href="#">Menu Item 1</a>
    <a href="#">Menu Item 2</a>
    <a href="#">Menu Item 3</a>
    <a href="#">Menu Item 4</a>
    <a href="#">Menu Item 5</a>
    <a href="#">Menu Item 6</a>
  </nav>
</header>

I've tried height, min-height, max-height, and even using clamp within width with little success. Maybe I simply lack an understanding as some of the existing responses suggest, but not sure how to solve.

2 Answers2

1

The width of the image column is not arbitrary.

The grid container is laying out the structure first. It is then laying out the items.

This means that the first column is sized when the image is at its natural width (100%).

When the item is then rendered at width: 50%, the browser doesn't go back and re-size the column.

So the column size isn't arbitrary; it's the natural width of the image.

(This is arguably a bug or a CSS limitation.)

Notice that this problem doesn't exist when the image is at full width:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

header {
  display: grid;
  grid-template-columns: auto 1fr;
  background-color: green;
  padding: 1rem;
}

img {
  width: 100%;
  background-color: pink;
}

div {
  background-color: red;
}

nav {
  background-color: yellow;
  grid-column: span 2;
}
<header>
  <div style="background-color: blue">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 324 413.28'%3E%3Crect class='655de5e2-44d3-4b5a-ae63-e6e7ec799246' x='18' y='18.12' width='288' height='324' fill='blue'/%3E%3C/svg%3E">
  </div>
  <div>
    <h1>Heading</h1>
    <p>Text Line 1</p>
    <p>Text Line 2</p>
    <p>Text Line 3</p>
  </div>
  <nav>
    <a href="#">Menu Item 1</a>
    <a href="#">Menu Item 2</a>
    <a href="#">Menu Item 3</a>
    <a href="#">Menu Item 4</a>
    <a href="#">Menu Item 5</a>
    <a href="#">Menu Item 6</a>
  </nav>
</header>

And it comes back when you try width: 150%:

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

header {
  display: grid;
  grid-template-columns: auto 1fr;
  background-color: green;
  padding: 1rem;
}

img {
  width: 150%;
  background-color: pink;
}

div {
  background-color: red;
}

nav {
  background-color: yellow;
  grid-column: span 2;
}
<header>
  <div style="background-color: blue">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 324 413.28'%3E%3Crect class='655de5e2-44d3-4b5a-ae63-e6e7ec799246' x='18' y='18.12' width='288' height='324' fill='blue'/%3E%3C/svg%3E">
  </div>
  <div>
    <h1>Heading</h1>
    <p>Text Line 1</p>
    <p>Text Line 2</p>
    <p>Text Line 3</p>
  </div>
  <nav>
    <a href="#">Menu Item 1</a>
    <a href="#">Menu Item 2</a>
    <a href="#">Menu Item 3</a>
    <a href="#">Menu Item 4</a>
    <a href="#">Menu Item 5</a>
    <a href="#">Menu Item 6</a>
  </nav>
</header>

Side Note

Generally speaking, when working with CSS Grid and Flexbox, it's not a good idea to make images the children of the container.

In other words, it's generally better to avoid images as grid or flex items.

There are just too many bugs and rendering variations among different browsers.

In many cases, simply putting the image in a div (making the div the grid item) solves the problem.

Avoid images as grid or flex items:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • For a moment I thought you had solved it, but I was wrong. If you give the div with the image in it a background colour you will see that the div is still an arbitrary size. – Snape Ninja Apr 08 '23 at 16:40
  • I refactored my question because I started to discover other issues. – Snape Ninja Apr 08 '23 at 21:36
0

If you wrap the image in a <div> and remove the width and height attributes from both <svg> and the <img> you let it up to the grid to control the sizing.

Now, you can set whatever fits in your grid template, like grid-template-columns: 20% auto;.

body {
  margin: 0;
}

header {
  display: grid;
  grid-template-columns: 20% auto;
  background-color: green;
  padding: 1rem;
}

header > div {
  background-color: pink;
  grid-column: 1;
  grid-row: 1;
}

header > section {
  background-color: red;
  grid-column: 2;
  grid-row: 1;
}

header > nav {
  background-color: yellow;
  grid-column: span 2;
  grid-row: 2;
}
<header>
  <div>
    <img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMjQgNDEzLjI4Ij48cmVjdCB4PSIxOCIgeT0iMTguMTIiIHdpZHRoPSIyODgiIGhlaWdodD0iMzI0IiBmaWxsPSJibHVlIi8+PC9zdmc+">
  </div>
  <section>
    <h1>Heading</h1>
    <p>Text Line 1</p>
    <p>Text Line 2</p>
    <p>Text Line 3</p>
  </section>
  <nav>
    <a href="#">Menu Item 1</a>
    <a href="#">Menu Item 2</a>
    <a href="#">Menu Item 3</a>
    <a href="#">Menu Item 4</a>
    <a href="#">Menu Item 5</a>
    <a href="#">Menu Item 6</a>
  </nav>
</header>
chrwahl
  • 8,675
  • 2
  • 20
  • 30
  • I have added to my post the result and it is not as you describe. Now the image is larger than the grid column and its row is super tall. This is from running your code snippet. – Snape Ninja Apr 08 '23 at 14:15
  • 1
    @DarkxPunk OK, the SVG will just keep expanding because I removed the widht and height attributes of the SVG. I add a width for the `` and returned to the grid columns `auto 1fr`. Is it more like that? – chrwahl Apr 08 '23 at 14:45
  • So here it an oddity while experimenting further. This will work so long as I define the width with a fixed pixel value or a vw value, but not a %. I am going to mark this as solved since the main question is basically solved but I do have some other requirements that I think I am going to do another question for with you answer as the starting point. – Snape Ninja Apr 08 '23 at 16:46
  • 1
    This is not a good answer because changing the `display` value of grid (and flex) items does nothing. The `display` value of grid (and flex) items is controlled by the container and any attempts to define it are automatically overridden (sources: [grid](https://www.w3.org/TR/css3-grid-layout/#grid-item-display) | [flex](https://www.w3.org/TR/css-flexbox-1/#flex-items)). – Michael Benjamin Apr 08 '23 at 19:34