Calculator keypad layout with flexbox

Wrap the uneven keys in their own flex containers and go from there…

* { box-sizing: border-box; }                                      /* 1 */

.flexBoxContainer {
    display: flex;
    justify-content: space-around;
    align-items: center;
    width: 100%;
}

.calculator {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: center;
    width: 100%;
}

.calculator .keys {
    border: red 1px solid;
    height: 50px;
    width: 25%;
    break-inside: avoid;
}

.calculator input {
    height: 100px;
    width: 100%;
    direction: rtl;
}

#anomaly-keys-wrapper {                                            /* 2 */
    display: flex;
    width: 100%; 
}

#anomaly-keys-wrapper > section:first-child {                      /* 3 */
    display: flex;
    flex-wrap: wrap;
    width: 75%;
}

#anomaly-keys-wrapper > section:first-child > div {                /* 4 */
    flex: 1 0 33.33%;
}

#anomaly-keys-wrapper > section:first-child > div:nth-child(4) {   /* 5 */
    flex-basis: 66.67%;
}

#anomaly-keys-wrapper > section:last-child {                       /* 6 */
    width: 25%;
    display: flex;
    flex-direction: column;
}

#anomaly-keys-wrapper .tall {                                      /* 7 */
    width: 100%;
    flex: 1;
}

@media (min-width: 321px) {
    .calculator {
        width: 320px;
    }
}
<div class="flexBoxContainer">
    <div class="calculator">
        <input />
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <div class="keys"></div>
        <section id="anomaly-keys-wrapper">
            <section>
                <div class="keys"></div>
                <div class="keys"></div>
                <div class="keys"></div>
                <div class="keys long"></div>
                <div class="keys"></div>
            </section>
            <section>
                <div class="keys tall"></div>
            </section>
        </section>
    </div>
</div>

Revised Codepen (with compiled CSS)

Notes:

  1. Include padding and borders in width / height calculations.
  2. Wrap uneven keys in a separate flex container (with defaults flex-direction: row and flex-wrap: nowrap)
  3. Wrap long key in a separate flex container with wrapping enabled (and take enough siblings to create equal height with tall key).
  4. Force three keys per row max.
  5. Make long key twice the width of siblings. (Didn’t use simpler long class selector due to weaker specificity.)
  6. Wrap tall key in a separate flex container with vertical orientation.
  7. Make tall key consume all available width and height of container.

UPDATE

From the comments:

Hi, 1. Can you explain me how flex basis works? and why did you use it instead of giving width to long button. 2. Why is it necessary to give flex: 1; to tall button, as i have read it is the default value.

Question #1:

The keys in the first sub-section container (containing .long) are sized with flex: 1 0 33.33%.

This is shorthand for flex-grow: 1, flex-shrink: 0, and flex-basis: 33.33%.

For the .long key we are simply overriding the flex-basis component with 66.67%. (there’s no need to re-declare the other two components).

Also, there’s really no difference in this case between width and flex-basis, but since we’re overriding flex-basis, I used flex-basis.

Using width would leave the original flex-basis: 33.33% intact, creating two width rules which may, therefore, fail to expand the .long key, depending on which rule prevails in the cascade.

For a complete explanation of flex-basis vs. width, see What are the differences between flex-basis and width?

Question #2:

Because the initial value of the flex-grow component is 0 (source).

Leave a Comment