I’m using flex
in a number input component to render custom “+” and “-” buttons next to the input itself. The buttons use aspect-ratio: 1/1;
to ensure they are always square, but I can’t seem to get the buttons’ container to honor that. Instead, the buttons are overflowing the container, almost as if the container is measuring their size without the aspect-ratio
property. When I remove that property the container renders at the appropriate size.
Some example code:
.input-interior {
box-shadow: 0 1px 0 blue;
box-sizing: border-box;
display: flex;
flex-grow: 1;
position: relative;
width: 600px;
}
.input-container {
flex-grow: 1;
min-width: 0;
}
input {
appearance: textfield;
background-color: transparent;
border: none;
box-shadow: none;
box-sizing: border-box;
color: rgb(15 15 15);
height: 80px;
margin: 0;
outline: none;
padding-left: 8px;
padding-right: 8px;
padding-top: 5px;
padding: 0;
width: 100%;
}
.input-actions {
box-shadow: 0 0 0 1px green;
box-sizing: border-box;
column-gap: 8px;
display: flex;
flex-shrink: 0;
padding: 8px;
}
button {
border: none;
margin: 0;
padding: 0;
aspect-ratio: 1 / 1;
min-height: 44px;
align-items: center;
display: flex;
justify-content: center;
min-width: auto;
width: auto;
}
<div class="input-interior">
<div class="input-container">
<input min="0" step="1" type="number" value="0" />
</div>
<div class="input-actions">
<button type="button">-</button>
<button type="button">+</button>
</div>
</div>
How do I get the .input-actions
container to honor the dynamic size of its children?
Short answer: the min-height
should be equal to a whole available height.
button {
min-height: 64px;
}
.input-interior {
box-shadow: 0 1px 0 blue;
box-sizing: border-box;
display: flex;
flex-grow: 1;
position: relative;
width: 600px;
}
.input-container {
flex-grow: 1;
min-width: 0;
}
input {
appearance: textfield;
background-color: transparent;
border: none;
box-shadow: none;
box-sizing: border-box;
color: rgb(15 15 15);
height: 80px;
margin: 0;
outline: none;
padding-left: 8px;
padding-right: 8px;
padding-top: 5px;
padding: 0;
width: 100%;
}
.input-actions {
box-shadow: 0 0 0 1px green;
box-sizing: border-box;
column-gap: 8px;
display: flex;
flex-shrink: 0;
padding: 8px;
}
button {
border: none;
margin: 0;
padding: 0;
aspect-ratio: 1 / 1;
min-height: 64px;
align-items: center;
display: flex;
justify-content: center;
min-width: auto;
width: auto;
}
<div class="input-interior">
<div class="input-container">
<input min="0" step="1" type="number" value="0" />
</div>
<div class="input-actions">
<button type="button">-</button>
<button type="button">+</button>
</div>
</div>
Details
When there is only min-height
the .input-actions
container uses it also as a width of the buttons (since aspect-ratio: 1/1
) and bases its own width on that:
112px = (2 * button min-height 44px) + (2 * container padding 8px) + (column-gap 8px)
Seems reasonable to set min-height: 100%
, but in that case container will become even smaller than 40px (depending on a font metrics) because it needs an absolute units, not relative.
A CSS variable and calc()
can be used to make the height settable in one place:
.input-interior {
--input-height: 80px;
box-shadow: 0 1px 0 blue;
box-sizing: border-box;
display: flex;
flex-grow: 1;
position: relative;
width: 600px;
}
.input-container {
flex-grow: 1;
min-width: 0;
}
input {
appearance: textfield;
background-color: transparent;
border: none;
box-shadow: none;
box-sizing: border-box;
color: rgb(15 15 15);
height: var(--input-height);
margin: 0;
outline: none;
padding-left: 8px;
padding-right: 8px;
padding-top: 5px;
padding: 0;
width: 100%;
}
.input-actions {
box-shadow: 0 0 0 1px green;
box-sizing: border-box;
column-gap: 8px;
display: flex;
flex-shrink: 0;
padding: 8px;
}
button {
border: none;
margin: 0;
padding: 0;
aspect-ratio: 1 / 1;
min-height: calc(var(--input-height) - 8px * 2);
align-items: center;
display: flex;
justify-content: center;
min-width: auto;
width: auto;
}
<div class="input-interior">
<div class="input-container">
<input min="0" step="1" type="number" value="0" />
</div>
<div class="input-actions">
<button type="button">-</button>
<button type="button">+</button>
</div>
</div>