使用Flexbox布局的计算器按键布局

5
我正在使用 flexbox 构建计算器。我希望其中一个键的高度是另一个键的两倍,另一个键的宽度是另一个键的两倍。
我在谷歌上搜索了很多,但没有找到同时解决这两个问题的答案。
对于高度加倍的键,我只找到了将 flex-direction 设置为 column 的答案。但在这种情况下,我将无法制作宽度加倍的键。
这里是 我的代码(在 codepen.io 上)。请帮忙。

$(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">&divide</div>
    <div class="keys keysOp" tabindex="5">&times</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>

2个回答

4
将不均匀的键包装在它们自己的 flex 容器中,然后从那里开始...

* { 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>

修改后的 Codepen(包含编译后的 CSS)

注意事项:

  1. width / height 的计算中包括填充和边框。
  2. 将不均匀的键包装在单独的弹性容器中(默认为 flex-direction: rowflex-wrap: nowrap)。
  3. 键包装在启用换行的单独的弹性容器中(并且带有足够多的同级元素以创建与 键相等的高度)。
  4. 强制每行最多三个键。
  5. 使 键的宽度是同级元素的两倍。(由于特异性较弱,未使用更简单的 .long 类选择器。)
  6. 键包装在具有垂直方向的单独的弹性容器中。
  7. 使 键占用容器的所有可用宽度和高度。

更新

来自评论:

你好,1. 你能解释一下弹性基础是如何工作的吗?为什么你使用它而不是给长按钮设置宽度。2. 给高按钮添加 flex: 1; 是必要的吗,因为我读到它是默认值。

问题 #1:

第一个子部分容器中的键(包含 .long)使用 flex: 1 0 33.33% 进行大小调整。

这是 flex-grow: 1flex-shrink: 0flex-basis: 33.33% 的简写。

对于 .long 键,我们只是将 flex-basis 组件覆盖为 66.67%。(没有必要重新声明其他两个组件。)

此外,在这种情况下,widthflex-basis 实际上没有区别,但由于我们正在覆盖 flex-basis,所以我使用了 flex-basis

使用 width 将保留原始的 flex-basis: 33.33%,创建两个 width 规则,这可能会导致无法扩展 .long 键,具体取决于哪个规则在级联中占优。

有关 flex-basiswidth 的完整说明,请参阅 flex-basis 与 width 之间的区别是什么?

问题 #2:

由于 flex-grow 组件的初始值为 0来源),因此需要手动设置该属性以使其生效。


1
你好,
  1. 你能解释一下 flex basis 是如何工作的吗?为什么你使用它而不是给长按钮设置宽度?
  2. 给高按钮设置 flex: 1; 是必要的吗?我读过它是默认值。
- Suyash Gulati
1
我已经更新了我的答案,并回答了你的问题。 - Michael Benjamin

2
我无法给出通用的答案,但这是我能得到的最接近的答案。
我已经修改了你的代码,使用浮动布局模型而不是弹性盒子布局模型。这种方法不太现代化,但似乎是解决特定问题的可行方法,几乎没有负面影响。
请注意,我还修改了按钮的宽度,使其实际上占据了所有可能的空间,并将它们的box-sizing设置为border-box,更多信息可以在这里找到。

https://codepen.io/anon/pen/VjOKGX

.calculator {
    // Required to keep the buttons inside
    overflow: hidden;
    width: 100%;
    @media #{$gtphone} {
        width: 320px;
    }
    .keys {
        // Changes the box model so that width includes the borders too
        box-sizing: border-box;
        border: red 1px solid;
        height: 50px;
        // The width is modified to take up all the space
        width: 25%;
        // Floating is defined
        float: left;
        break-inside: avoid;
    }
    .long {
        // This one needs float to be set to right,
        // so that other elements may be on its left in multiple rows
        float: right;
        height: 100px !important;
    }
    .big {
        // Again, width is modified
        width: 50% !important;
    }
    input {
        height: 100px;
        width: 100%;
        direction: rtl;
    }
}

你好,感谢您的及时回复,但我只想寻找一个使用flexbox的解决方案,因为我现在处于学习模式。 也许将来我会使用您的方法,因为它更简单且代码更少。 - Suyash Gulati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接