Calculator keypad layout with flexbox
css, flexbox, html
Solution
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:
- Include padding and borders in `width` / `height` calculations.
- Wrap uneven keys in a separate flex container (with defaults `flex-direction: row` and `flex-wrap: nowrap`)
- Wrap long key in a separate flex container with wrapping enabled (and take enough siblings to create equal height with tall key).
- Force three keys per row max.
- Make long key twice the width of siblings. (Didn't use simpler `long` class selector due to weaker specificity.)
- Wrap tall key in a separate flex container with vertical orientation.
- 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).
Problem
I am building a calculator with flexbox. I want one of its keys twice the height and another key twice the width. I googled much about it but couldn't find both cases together. For twice height key, only answers I found was to make `flex-direction` as `column`. But in that case I will not be able to make double width key. Here is my code (on codepen.io). Please help. ``` $(function() { var curr = "", prev = ""; var updateView = function() { $('#curr').html(curr); $('#prev').html(prev); }; $('.keysNum').on('click', function(e) { curr += $(this).html(); console.log(this); updateView(); }); $('.keysOp').on('click', function(e) { }); }); ``` ``` .flexBoxContainer { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; display: flex; justify-content: space-around; align-items: center; width: 100%; min-height: 100vh; } .calculator { display: flex; flex-wrap: wrap; justify-content: center; align-content: center; width: 100%; min-height: 100vh; } @media (min-width: 321px) { .calculator { width: 320px; } } .calculator .keys { border: #d3d2cb 0.5px solid; background: #fefdff; color: #33393d; height: 50px; height: 14.2857142857vh; width: 25%; line-height: 14.2857142857vh; text-align: center; font-size: 1.4rem; font-weight: bold; transition: background 0.2s linear; } .calculator .keysOp { background: #f1f1ef; } .calculator .keysC { color: #f94913; } .calculator .keys:hover { background: #d3d2cb; transition: background 0s linear; } .calculator .keys:focus { outline: none; } .calculator .keys:active { background: #93938E; } .calculator .screen { background: #e9e8e5; height: 14.2857142857vh; width: 100%; line-height: 14.2857142857vh; direction: rtl; } .calculator .screen:last-child { font-size: 4rem; } .calculator #anomaly-keys-wrapper { display: flex; width: 100%; } .calculator #anomaly-keys-wrapper>section:first-child { display: flex; flex-wrap: wrap; width: 75%; } .calculator #anomaly-keys-wrapper>section:first-child>div.keys { flex: 1 0 33.33%; } .calculator #anomaly-keys-wrapper>section:first-child>div.long { flex-basis: 66.67%; } .calculator #anomaly-keys-wrapper>section:last-child { width: 25%; display: flex; flex-direction: column; } .calculator #anomaly-keys-wrapper>section:last-child>.tall { background: #f94913; color: #fefdff; width: 100%; line-height: 28.5714285714vh; flex: 1; } .calculator #anomaly-keys-wrapper>section:last-child>.tall:hover { background: #c73a0f; } .calculator #anomaly-keys-wrapper>section:last-child>.tall:focus { outline: none; } .calculator #anomaly-keys-wrapper>section:last-child>.tall:active { background: #8b280a; } ``` ``` <link href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" /> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="flexBoxContainer"> <div class="calculator"> <div class="screen" id="prev"></div> <div class="screen" id="curr"></div> <!-- <div class="keys keysC keysOp" tabindex="2">C</div> --> <div class="keys keysC keysOp" tabindex="2">C</div> <div class="keys keysOp" tabindex="3"><i class="icon ion-backspace-outline"></i></div> <div class="keys keysOp" tabindex="4">÷</div> <div class="keys keysOp" tabindex="5">×</div> <div class="keys keysNum" tabindex="6">7</div> <div class="keys keysNum" tabindex="7">8</div> <div class="keys keysNum" tabindex="8">9</div> <div class="keys keysOp" tabindex="9">-</div> <div class="keys keysNum" tabindex="10">4</div> <div class="keys keysNum" tabindex="11">5</div> <div class="keys keysNum" tabindex="12">6</div> <div class="keys keysOp" tabindex="13">+</div> <section id="anomaly-keys-wrapper"> <section> <div class="keys keysNum" tabindex="14">1</div> <div class="keys keysNum" tabindex="15">2</div> <div class="keys keysNum" tabindex="16">3</div> <div class="keys long keysNum" tabindex="17">0</div> <div class="keys" tabindex="18">.</div> </section> <section> <div class="keys tall" tabindex="19">=</div> </section> </section> </div> </div> ```