3

Got a bit of a problem with my form layout if anyone can spare a bit of help: My understanding was that if I had a fixed width container, using fr instead of a percentage width for grid-template-columns would take into account only the free space available, and so grid-gap would not cause the grid to overflow its container, as described in this answer:

As a solution, instead of percentage units, try using fr units, which apply only to free space. This means that fr lengths are calculated after any grid-gap lengths are applied.

and also here:

The fr unit works only with the free space in the container.

But my code still seems to cause the grid to overflow (horizontally is all I care about):

https://codepen.io/nwoodward/pen/bGLpBbP

* {
  margin: 0;
}

.container {
  display: flex;
  justify-content: center;
  width: 100%;
  height: 100vh;
  background-color: firebrick;
}

.form {
  display: flex;
  flex-direction: column;
  padding: 2rem;
  margin: 2rem;
  width: 25rem;
  background-color: white;
}
.content {
  border: 1px solid red;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 4rem;
  width: 100%;
}
<div class="container">
  <form class="form">
    <div class="content">
      <div class="field">
        <label for="title" class="label">Title</label>
        <input type="text" placeholder="Job Title" id="title" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail">
        </i>
        <small class="error-msg"></small>
      </div>
      <div class="field">
        <label for="company" class="label">Company</label>
        <select name="company" id="company" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="location" class="label">Location</label>
        <select name="location" id="location" class="input">
            <!-- options added in js -->
        </select>                        
        <i class="icon"></i>
        <i class="icon"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="wage" class="label">Wage</label>
        <input type="text" placeholder="Wage" id="wage" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="type" class="new-job__label">Type</label>
        <select name="type" id="type" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="position" class="label">Position</label>
        <select name="position" id="position" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="pqe" class="label">PQE</label>
        <select name="pqe" id="pqe" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="featured" class="label">Featured</label>
        <select name="featured" id="featured" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>
    </div>
    <button class="new-job__submit">Submit</button>

  </form>
</div>

I guess that part of the issue is that the input elements have a fixed minimum width of some sort, but even if that is true, fixing the width of either the .field or the inputs to a smaller value that does fit isn't really what I'm after at all.


*EDIT: Overflowing with inputs overflow

**EDIT: Not overflowing with divs not overflowing

NickW
  • 1,207
  • 1
  • 12
  • 52
  • Why do you use `grid-gap: 4rem`? It is much and causes an overflow. – Arman Ebrahimi May 09 '22 at 18:18
  • 1
    @ArmanEbrahimi even a smaller gap might cause an overflow. The gap is not responsible for the overflow. It is an coneptional issue that is caused by giving a parent a `fixed/max-height` and not addintg a proper overflow rule as fall back. Either the parten with the `fixed` or `max-height` simply needs `overflow: auto` as overflow rule or need to change the property to `min-height` – tacoshy May 09 '22 at 19:01
  • Hi @ArmanEbrahimi - I've used that large gap to emphasise the problem :) I could make the inputs and fields narrower so they fit, but then I'd be manually calculating how wide the column should be minus the gutters - which surely defeats the point – NickW May 09 '22 at 19:13
  • @tacoshy - unfortunately I don't think so, I've changed the OP to make it more clear :) – NickW May 09 '22 at 19:14
  • like I said, it is conceptional. For your horizontal overflow there isnt much you can do then checking where your breakpoint is and adding a `media query` to coutner it by changing your layout to a single column as example. – tacoshy May 09 '22 at 19:14
  • Respectfully I don't think that's true at all. I've not set the width of anything within the column - it's not like selects can't be smaller than that - so what is it that's preventing it from shrinking? Replace the inputs with divs and it behaves as it should: https://codepen.io/nwoodward/pen/bGLpBbP – NickW May 09 '22 at 19:24
  • Have added an image to the OP to show what I mean too! – NickW May 09 '22 at 19:30

2 Answers2

0

The issue is caused because you gave a parent a fixed height:
.container { height: 100vh; }

To solve it just change the property from height to min-height. The container will grow then instead of letting the cotent overflow:

* {
  margin: 0;
}

.container {
  display: flex;
  justify-content: center;
  width: 100%;
  min-height: 100vh;
  background-color: firebrick;
}

.form {
  display: flex;
  flex-direction: column;
  padding: 2rem;
  margin: 2rem;
  width: 25rem;
  background-color: white;
}
.content {
  border: 1px solid red;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 4rem;
  width: 100%;
}
<div class="container">
  <form class="form">
    <div class="content">
      <div class="field">
        <label for="title" class="label">Title</label>
        <input type="text" placeholder="Job Title" id="title" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail">
        </i>
        <small class="error-msg"></small>
      </div>
      <div class="field">
        <label for="company" class="label">Company</label>
        <select name="company" id="company" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="location" class="label">Location</label>
        <select name="location" id="location" class="input">
            <!-- options added in js -->
        </select>                        
        <i class="icon"></i>
        <i class="icon"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="wage" class="label">Wage</label>
        <input type="text" placeholder="Wage" id="wage" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="type" class="new-job__label">Type</label>
        <select name="type" id="type" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="position" class="label">Position</label>
        <select name="position" id="position" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="pqe" class="label">PQE</label>
        <select name="pqe" id="pqe" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="featured" class="label">Featured</label>
        <select name="featured" id="featured" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>
    </div>
    <button class="new-job__submit">Submit</button>

  </form>
</div>
tacoshy
  • 10,642
  • 5
  • 17
  • 34
  • Hi @tacoshy, thanks for the reply, but unfortunately I'm not sure that solves my problem - it's the horizontal overflow I'm concerned about rather than the vertical one. I've added an image to the OP to show the overflow I'm talking about (which happens in your snippet too). Thanks again though – NickW May 09 '22 at 19:10
  • @NickW you can do the same with the x-axis. Also you should consider to add `media-queries` to your breakpoint to change the layout to a single column grid. – tacoshy May 09 '22 at 19:13
  • I'd like the content to scale to the size of the column - which there's plenty of space to do. `repeat(2, 1fr)` should achieve that, but isn't – NickW May 09 '22 at 19:16
  • because if the screen gets to small at some point it will always break (breakpoint). Same for pretty much every single website. Thats why I said it is conceptional and why you should consider `media queries`. if it is just that single input field then you can also give the input a width of 100% to only allow it to use the coulmn width. – tacoshy May 09 '22 at 19:20
  • Replace the inputs with divs: https://codepen.io/nwoodward/pen/bGLpBbP Unless you're telling me that it's the minimum size of the selects causing the problem I'm not sure what you're saying is true - it scales correctly. – NickW May 09 '22 at 19:26
0

Update the code like below (related question to understand the first code adjustment: Why does minmax(0, 1fr) work for long elements while 1fr doesn't?)

* {
  margin: 0;
}

.container {
  display: flex;
  justify-content: center;
  background-color: firebrick;
}

.form {
  display: flex;
  flex-direction: column;
  padding: 2rem;
  margin: 2rem;
  width: 25rem;
  background-color: white;
}
.content {
  border: 1px solid red;
  display: grid;
  grid-template-columns: repeat(2, minmax(0,1fr)); /* here */
  grid-gap: 4rem;
}

/* here */
input {
  max-width: 100%;
  box-sizing: border-box;
}
<div class="container">
  <form class="form">
    <div class="content">
      <div class="field">
        <label for="title" class="label">Title</label>
        <input type="text" placeholder="Job Title" id="title" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail">
        </i>
        <small class="error-msg"></small>
      </div>
      <div class="field">
        <label for="company" class="label">Company</label>
        <select name="company" id="company" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="location" class="label">Location</label>
        <select name="location" id="location" class="input">
            <!-- options added in js -->
        </select>                        
        <i class="icon"></i>
        <i class="icon"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="wage" class="label">Wage</label>
        <input type="text" placeholder="Wage" id="wage" class="input">
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="type" class="new-job__label">Type</label>
        <select name="type" id="type" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="position" class="label">Position</label>
        <select name="position" id="position" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="pqe" class="label">PQE</label>
        <select name="pqe" id="pqe" class="input">
            <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>

      <div class="field">
        <label for="featured" class="label">Featured</label>
        <select name="featured" id="featured" class="input">
          <!-- options added in js -->
        </select>
        <i class="icon icon--success"></i>
        <i class="icon icon--fail"></i>
        <small class="error-msg"></small>
      </div>
    </div>
    <button class="new-job__submit">Submit</button>

  </form>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415