htmlcssgridaspect-ratio

Weird unwanted overflow inside CSS grid


I am trying to make a grid which has two columns. The second column should contain an image input field which should be a square with a 1:1 aspect ratio. The square should be aligned with the bottom of the first column. Basically, the bottom of the image input should reach the bottom of the first column. I made a sketch of what I am trying to do in Figma (see the image).

Note: I cannot use the aspect-ratio property as it doesn't have great enough support yet for my needs. I also want to avoid magic numbers and JavaScript.

What I've tried: Currently, I am using the width: 0; + padding: 0 100%; trick to get a 1:1 aspect ratio. However, the image input is not pushing the other grid column back like I want and is instead overflowing. Additionally, the input doesn't seem to be getting a correct 1:1 aspect ratio either. Any help would be appreciated.

enter image description here

body {
  background: #eee;
}
section {
  margin: 2rem;
  padding: 2rem;
  background: white;
}
input {
  background: #eee;
  border: 0.05rem solid black;
  border-radius: 0.5rem;
  padding: 0.5rem;
}


.grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2rem;
}
.form-item {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.form-item ~ .form-item {
  margin-top: 2rem;
}


.image-input-container {
  position: relative;
  height: 100%;
  width: 0;
  padding: 0 100%;
}
.image-input {
  background: #eee;
  border: 0.05rem solid black;
  border-radius: 0.5rem;
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
<section>
  <div class="grid">
  
    <div>
      <div class="form-item">
        <label>Name</label>
        <input>
      </div>
      <div class="form-item">
        <label>Description</label>
        <input>
      </div>
    </div>
    
    <div class="form-item">
      <label>Image</label>
      <div class="image-input-container">
        <button class="image-input">+</button>
      </div>
    </div>
    
  </div>
</section>


Solution

  • The width: 0; padding: 0 100%; 'trick' does not work because padding is calculated relative to the containing block width.

    As you cannot use aspect-ratio, you could force the right hand column second item to be square for example by having an img element that is square and with the height of the left hand column. Then your div (into which I guess you will eventually place the image the user has chosen) can sit inside that cell taking its dimensions from it, but not affecting those dimensions as it is positioned absolute.

    <style>
      body {
        background: #eee;
      }
      
      section {
        margin: 2rem;
        padding: 2rem;
        background: white;
      }
      
      input {
        background: #eee;
        border: 0.05rem solid black;
        border-radius: 0.5rem;
        padding: 0.5rem;
      }
      
      .grid {
        display: grid;
        grid-template-columns: 1fr auto;
        gap: 2rem;
      }
      
      .form-item {
        display: flex;
        flex-direction: column;
        gap: 0.25rem;
      }
      
      .form-item~.form-item {
        margin-top: 2rem;
      }
      
      .image-input-container {
        position: relative;
        height: 100%;
        width: fit-content;
      }
      
      .image-input {
        background: #eee;
        border: 0.05rem solid black;
        border-radius: 0.5rem;
        position: absolute;
        inset: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
      }
      
      .dummy {
        height: 100%;
        width: auto;
      }
    </style>
    <section>
      <div class="grid">
    
        <div>
          <div class="form-item">
            <label>Name</label>
            <input>
          </div>
          <div class="form-item">
            <label>Description</label>
            <input>
          </div>
        </div>
    
        <div class="form-item">
          <label>Image</label>
          <div class="image-input-container">
            <img class="dummy" width="1" height="1">
            <button class="image-input">+</button>
          </div>
        </div>
    
      </div>
    </section>