[ 基础系列 ] - CSS 小测 08

525 阅读6分钟

系列文章

说在前面

本篇是张鑫旭老师的 CSS 基础测试9 的阅后笔记。(XboxYan 依然是秀的我脑壳痛)

题目

先来看看题目。

img-00

其他需求:

  • 最终布局垂直对齐良好
  • 代码友好

思路

这题看上去和 CSS 小测 - 01 非常相似。

关键点是

  • 右侧标签栏留安全宽度
  • 左侧文本内容自适应

实现方案挺多:

  • flex(不兼容 IE8)
  • 原生流体特性
  • float
  • table

下面分别来看看。

flex

先看看最简单的 flex,虽然不兼容 IE8,不过 flex 布局在单行自适应上非常具有优势。

关键点为:flex: auto

.story-list {
    padding: 0;
    list-style: none;
} 

.story-item {
    margin: 5px 0;
    display: flex;
}

.story-content {
    margin: 0;
    flex: auto;
    color: #9a9da4;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.story-label {
    display: inline-flex;
}

.story-label .story-tab {
    margin: 0 2px;
    padding: 0 2px;
    white-space: nowrap;
    border: 1px solid;
    border-radius: 2px;
    font-size: 14px;
    font-weight: 700;
} 

.story-label [tab-type="type"] {
    color: #9a9da4;
    border-color: #d5d7da;
}

.story-label [tab-type="state"] {
    color: #f16b71;
    border-color: #f9babb;
}

.story-label [tab-type="count"] {
    color: #498bed;
    border-color: #b3d6f9;
}
<ul class="story-list">
  <li class="story-item">
    <p class="story-content">
      这次是一个新的故事这次是一个新的故事
    </p>
    <div class="story-label">
      <span class="story-tab" tab-type="type">都市</span>
      <span class="story-tab" tab-type="state">连载中</span>
      <span class="story-tab" tab-type="count">54.82万字</span>
    </div>
  </li>
  <li class="story-item">
    <p class="story-content">
      穿越天地复苏的平行世界穿越天地复苏的平行世界
    </p>
    <div class="story-label">
      <span class="story-tab" tab-type="type">都市</span>
      <span class="story-tab" tab-type="state">完本</span>
      <span class="story-tab" tab-type="count">1万字</span>
    </div>
  </li>
  <li class="story-item">
    <p class="story-content">
      修真四万年
    </p>
    <div class="story-label">
      <span class="story-tab" tab-type="type">科幻</span>
      <span class="story-tab" tab-type="state">完本</span>
      <span class="story-tab" tab-type="count">1059.98万字</span>
    </div>
  </li>
</ul>

需要注意的是,这里通过将 story-lable 设置为 display: inline-flex 防止标签换行。

效果如下:

img-01

原生流体特性

原生流体特性在 CSS深入理解流体特性和BFC特性下多栏自适应布局 中有非常详细的介绍,有兴趣的同学可以看看。

这里我们为右边的标签组设定安全宽度,让其靠右:

.story-label {
    width: 11.5rem;
    margin-left: auto;
    text-align: right;
}

效果如下:

img-02

看过我之前写的 CSS 小测 - 01 的同学应该很清楚这个场景了,我们为左侧设定 margin 即可实现自适应布局。

.story-content {
    margin: 0 11.5rem -1.25rem 0;
    color: #9a9da4;
}

效果如下:

img-03

现在加上长文本缺省效果即可:

.story-content {
    margin: 0 11.5rem -1.25rem 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: #9a9da4;
}

效果如下:

img-04

float

float 配合 overflow: hidden 即常说的 BFC。

原理是 overflow: hidden 可以创建格式化上下文,自动分配剩余空间,不会受到浮动影响,用 inline-block 也行。

<ul class="story-list">
  <li class="story-item">
    <div class="story-label">
      <span class="story-tab" tab-type="type">都市</span>
      <span class="story-tab" tab-type="state">连载中</span>
      <span class="story-tab" tab-type="count">54.82万字</span>
    </div>
    <p class="story-content">
      这次是一个新的故事这次是一个新的故事
    </p>
  </li>
</ul>
.story-label {
    float: right;
}

.story-content {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: #9a9da4;
}

效果如下:

img-05

利用 float 进行布局的缺点是:DOM 元素与视觉信息不符。

可以看到上面贴出的 HTML 中,story-content 放在 story-label 之后,而从视觉上来看,应该是反过来的。

table

这个布局是答疑中的重中之重,所以这里就多费些笔墨,简单介绍一下 table 布局。

首先兼容性的话,display: table 兼容 IE8+,然后来看看一些常用的可选值:

  • display: table:指定对象作为块元素级的表格,相当于html标签 <table>
  • display: inline-table:指定对象作为内联元素级的表格,相当于html标签 <table>
  • display: table-cell:指定对象作为表格单元格,相当于html标签 <td>
  • display: table-row:指定对象作为表格行,相当于html标签 <tr>

分析需求,我们可以把单行当作一个表格的一行,左右各作一个单元格:

.story-item {
    display: table;
}

.story-content {
    display: table-cell;
}

.story-label {
    display: table-cell;
    white-space: nowrap;
}

效果如下:

img-06

这个时候,只要让左边文字过长缺省即可:

.story-content {
    display: table-cell;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

效果如下:

img-07

可以看到,效果与我们预期的并不相符,直接变成了整体元素的自适应布局。原因是非 table-layout: fixed 的表格,其每个单元格尺寸宽度是根据里面内容自动分配的,如果设置了 white-space: nowrap 是自动宽度自适应的,则宽度会变成一个固定值,无法自适应。解决方案有两种:

  • 将文本内容包裹起来,通过绝对定位让其浮在单元格上,让文本块实现长文本缺省
  • 再嵌套一层 display:table 使用 table-layout:fixed 来完成效果

方案一

本方案来自 XboxYan 同学

.story-content {
    display: table-cell;
    position: relative;
    text-align: left;
}

.story-content:before {
    content: "x x x x x x x x x x x x x x x x x xx x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x";
    height: 0;
    display: block;
    visibility: hidden;
}

.story-content p {
    margin: 0;
    padding: 0;
    display: inline;
    position: absolute;
    left: 0;
    right: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 16px;
    color: #a2a5ac;
}

效果如下:

img-08

方案二

.story-item {
    display: table;
    width: 100%;
}

.story-label {
    display: table-cell;
    white-space: nowrap;
}

.story-content {
    display: table-cell;
    width: 9999px;
}

.story-content div {
    display: table;
    table-layout: fixed;
    width: 100%;
}

.story-content p {
    margin: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    color: #9a9da4;
}
<li class="story-item">
    <div class="story-content">
      <div>
        <p>这次是一个新的故事这次是一个新的故事</p>
      </div>
    </div>
    <div class="story-label">
      <span class="story-tab" tab-type="type">都市</span>
      <span class="story-tab" tab-type="state">连载中</span>
      <span class="story-tab" tab-type="count">54.82万字</span>
    </div>
  </li>

效果如下:

img-09

反向文字缺省

这个在之前的 CSS 小测 - 03 也有提到过,就是 direction: rtl

.story-list[reserve] .story-content{
    direction: rtl;
    text-align:left; /* 兼容 IE8 */
}

效果如下:

img-10

结束语

平日里多注意细节,积累,布局技巧其实无非就是那么多,万变不离其宗。今天就到这里吧。

然后这里是 在线 demo