Gergő Horváth
Gergő Horváth

Reputation: 3705

Why does child padding expand parent width?

Consider the following example:

body {
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
  color:    #C0C0C0;
  background-color: #202020;
  display: flex;
  flex-direction: column;
  align-items: center;
}

* {
  box-sizing: border-box;
}
.col {
  display: flex;
  flex-direction: column;
}
.row {
  display: flex;
  flex-direction: row;
  background-color: gray
}
.wrap {
  flex-wrap: wrap;
}
.align-center {
  align-items: center;
}
.justify-center {
  justify-content: center;
}
.gap {
  gap: 20px;
}
input {
  background-color:#202020 ;
  border: 1px solid #C0C0C0 ;
  border-radius: 5px;
  padding: 12px 20px;
  margin: 8px 0;
  box-sizing: border-box;
}
.inputContainer {
  max-width: 300px;
  width: 100%;
}
.inputContainer > * {
  width: 100%;
}
<form class="col gap align-center" style="width: 90vw" action="">
  <div class="row wrap gap justify-center">
    <div class="col inputContainer">
      <label>expands:</label>
      <input />
    </div>
    <div class="col inputContainer">
      <label>parent:</label>
      <input />
    </div>
  </div>
  <div class="row wrap justify-center">
    <div class="col inputContainer">
      <label>even if:</label>
      <input />
    </div>
    <div class="col inputContainer">
      <label>no gap set:</label>
      <input />
    </div>
  </div>
  <div class="row wrap gap justify-center">
    <div class="col inputContainer">
      <label>alone works:</label>
      <input />
    </div>
  </div>
  <div class="row wrap gap justify-center">
    <div class="col inputContainer">
      <label>also with:</label>
      <input style='padding: 0' />
    </div>
    <div class="col inputContainer">
      <label>no padding:</label>
      <input style='padding: 0' />
    </div>
  </div>
</form>

The gray background demonstrates each row dimensions. If the inputs inside have padding on x axis, it expands the parent width, even though box sizing is border box. If there's only one child for the row, it works fine. If no padding set on children, it works fine. If there's padding set, it expands the parent width. Why?

Upvotes: 3

Views: 1691

Answers (1)

Temani Afif
Temani Afif

Reputation: 272648

A complex case of shrink-to-fit behavior. All your rows are flex items so their width depend on their content. Now the complex part is that you are making the child having width:100% which means 100% of the parent width so we have a cycle here.

In such case the browser will do the following:

  1. ignore the width:100% (consider it as auto)
  2. find the width of the child using other properties
  3. set the width of the parent based on (2)
  4. get back to the resolve width:100% based on the width found in (3)
  5. the width of child may change but not the one of the parent.

If one child is 100% then logically both cannot fit into one line and each one will be on its own line.

Here is a 2 steps illustration to understand what is happening:

body {
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
  color:    #C0C0C0;
  background-color: #202020;
  display: flex;
  flex-direction: column;
  align-items: center;
}

* {
  box-sizing: border-box;
}
.col {
  display: flex;
  flex-direction: column;
}
.row {
  display: flex;
  flex-direction: row;
  background-color: gray
}
.wrap {
  flex-wrap: wrap;
}
.align-center {
  align-items: center;
}
.justify-center {
  justify-content: center;
}
.gap {
  gap: 20px;
}
input {
  background-color:#202020 ;
  border: 1px solid #C0C0C0 ;
  border-radius: 5px;
  padding: 12px 20px;
  margin: 8px 0;
  box-sizing: border-box;
}
.inputContainer {
  max-width: 300px;
  width: 100%;
}
.inputContainer > * {
  width: 100%;
}
<form class="col gap align-center" style="width: 90vw" action="">
  <div class="row wrap gap justify-center">
    <div class="col inputContainer" style="width:auto">
      <label>expands:</label>
      <input />
    </div>
    <div class="col inputContainer" style="width:auto">
      <label>parent:</label>
      <input />
    </div>
  </div>
</form>
<hr>
<form class="col gap align-center" style="width: 90vw" action="">
  <div class="row wrap gap justify-center">
    <div class="col inputContainer" >
      <label>expands:</label>
      <input />
    </div>
    <div class="col inputContainer">
      <label>parent:</label>
      <input />
    </div>
  </div>
</form>

Notice how in both cases, the width of the parent is kept the same and it's the width based on the child having width:auto. Now you can easily understand all the other cases especially why adding padding will increase the width of the parent.

Upvotes: 2

Related Questions