[ 基础系列 ] - CSS 小测 07

392 阅读4分钟

系列文章

说在前面

本篇是张鑫旭老师的 CSS 基础测试8 的阅后笔记。

题目

先来看看题目。

请实现一个按钮相关的单行布局效果。

当只有一个按钮的时候,宽度 100%,效果如下:

img-00

左右安全距离为 1rem

当有两个以上按钮的时候,间隙 1rem,宽度等分,效果如下:

img-01

img-02

需求:

  • 尺寸间距符合题意
  • 按钮 UI 符合设计稿
  • 布局随着按钮个数自动适配
  • 整体宽度自适应
  • 代码友好
  • 按钮永远一行,不换行显示

思路

这道题没有什么难度,我们就横向分析一下。

首先简单把效果实现一下。题目要求的单行布局,自适应,通常有以下几种方案:

  • flex
  • grid
  • table

在不考虑兼容性(IE9+)的情况下,单行自适应布局,以 flex 为最优,这里先用 flex 来实现题中效果。

关键点只有一点:

  • flex: auto

代码如下:

<div class="btn-group">
  <button class="btn">按钮</button>
</div>
<div class="btn-group">
  <button class="btn">按钮</button>
  <button class="btn">按钮</button>
</div>
<div class="btn-group">
  <button class="btn">按钮</button>
  <button class="btn">按钮</button>
  <button class="btn">按钮</button>
</div>
.btn-group {
    margin: 1rem 0;
    display: flex;
    padding: 0 1rem;
}
.btn {
    margin-right: 1rem;
    flex: auto;
    height: 26px;
    color: #ef7077;
    border: 1px solid;
    border-radius: 13px;
    background: transparent;
}
.btn:not(:last-child) {
    margin-right: 1rem;
}

效果如下:

img-03

好的,今天的总结就......( ̄ε(# ̄)☆╰╮o( ̄皿 ̄///)

就上面的代码,我们聊一聊一些平时开发不容易注意到的细节吧。

首先,题目中有要求:

  • 按钮永远一行,不换行显示

那为什么代码没有设置 flex-wrap: nowrap 呢?

这是因为设置 display: flex 之后,默认就会设置 flex-wrap: nowrap

然后可能有同学注意到我在子项中使用的是 flex: auto,而不是 flex: 1。当然这里使用 flex: 1 也能实现同样的效果,甚至 flex: 2/3/4/5/n 都行,但语意并不贴切,这里更推荐使用 flex: auto

接下来是关于安全距离的问题,有的同学可能会这样实现:

.btn-group {
    padding: 0 0.5rem;
}

.btn{
    margin: 0 0.5rem;
}

看上去似乎代码更为简洁,但实际开发中并不推荐这样做。通过容器和元素共同实现安全距离的操作,逻辑不清,代码难以维护。

通常在布局的时候,边距尽量仅使用容器实现,不要影响子项。这里按钮与按钮之间的间距,通过 not 伪类实现是比较推荐的做法。

另外上面有提到,通过 gridtable 也能实现这个布局,下面分别来看看。

grid

事实上,grid 布局用在这里并不是很合适,grid 更适合的场景是更加偏向二纬的,比如经典的网格布局,这里就当作学习看看 grid 如何实现题目中的布局效果吧。

.btn-group {
    margin: 1rem 0;
    padding: 0 1rem;
    display: grid;
    grid-auto-flow: column;
    grid-gap: 1rem;
}

效果如下:

img-04

flex 相比,grid 的优势是可以控制单元格的间距。

table

table 布局并没有上面两者那么直观,优势在于兼容性更强,可以用于 IE8+。

由于 table 布局需要子项为块级元素,所以这里我们需要在 button 外包裹一个 div

<div class="btn-group" data-layout="table">
  <div class="btn-wrap">
    <button>按钮</button>
  </div>
  <div class="btn-wrap">
    <button>按钮</button>
  </div>
  <div class="btn-wrap">
    <button>按钮</button>
  </div>
</div>
.btn-group[data-layout="table"] {
    display: table;
    white-space: nowrap;
    width: calc(100% - 1rem);
    margin-left: auto;
}
.btn-group[data-layout="table"] > .btn-wrap {
    display: table-cell;
    padding-right: 1rem;
}
.btn-group[data-layout="table"] > .btn-wrap > button {
    width: 100%;
    height: 26px;
    color: #ef7077;
    border: 1px solid;
    border-radius: 13px;
    background: transparent;
}

效果如下:

img-05

优化

这里的优化可以从以下几点出发:

  • hoverfocus 效果
  • 长文本按钮

hoverfocus 效果

这只是一个思路,下面简单演示一下:

.btn {
    outline: none;
}

.btn:hover,
.btn:focus {
    background: #ef7077;
    color: #fff;
}

效果如下:

img-06

长文本按钮

这个结合 text-overflow: ellipsis 属性即可:

.btn {
    flex: auto;
    height: 26px;
    color: #ef7077;
    border: 1px solid;
    border-radius: 13px;
    background: transparent;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

效果如下:

img-07

结束语

涉及到键盘访问,有的同学可能会想到 tabindex,事实上这个属性不涉及到 form 表单提交的话,一般情况是不用添加的。

然后这里是 在线 demo