如何在内联元素中布局图片

322 阅读3分钟

最近遇到了一个比较棘手的需求,大概如下图所示:

requirement.jpg

需要实现的功能点:

  1. 长按句子背景高亮;
  2. “火”的标志要显示在需要高亮句子右上侧;

另外还有几点补充说明:

  1. 页面的布局和嵌套是按照: div.para > span.sent > button.word
  2. 段落之间有水平空间,句子是首位相连的,需要高亮的是句子

我们面对的问题有如下几个:

  1. 如何实现图中的高亮?
  2. 如果定位“火”在句子的右上侧?

那么问题来了,如果实现呢?可以通过纯 CSS 方式实现吗?

句子高亮

在不考虑“火”的情况下,我们已经确定的页面结构可以简化如下:

<div class="container">
  <div class="para">
    <span class="sent">
      <span class="word">The</span>
      <span class="word">bad</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">time</span>
      <span class="word">files</span>
      <span class="sign">.</span>
      <span class="word">The</span>
      <span class="word">good</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">you're</span>
      <span class="word">the</span>
      <span class="word">pilot</span>
      <span class="sign">.</span>
    </span>
    <span class="sent">
      <span class="word">As</span>
      <span class="word">night</span>
      <span class="word">falls,</span>
      <span class="word">the</span>
      <span class="word">Qianlingshan</span>
      <span class="word">sports</span>
      <span class="word">park</span>
      <span class="word">begins</span>
      <span class="word">to</span>
      <span class="word">buzz</span>
      <span class="sign">.</span>
    </span>
    <span class="sent hi">
      <span class="word">The</span>
      <span class="word">bad</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">time</span>
      <span class="word">files</span>
      <span class="sign">.</span>
      <span class="word">The</span>
      <span class="word">good</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">you're</span>
      <span class="word">the</span>
      <span class="word">pilot</span>
      <span class="sign">.</span>
      <span class="word">As</span>
      <span class="word">night</span>
      <span class="word">falls,</span>
      <span class="word">the</span>
      <span class="word">Qianlingshan</span>
      <span class="word">sports</span>
      <span class="word">park</span>
      <span class="word">begins</span>
      <span class="word">to</span>
      <span class="word">buzz</span>
      <span class="sign">.</span>
    </span>
    <span class="sent">
      <span class="word">The</span>
      <span class="word">bad</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">time</span>
      <span class="word">files</span>
      <span class="sign">.</span>
      <span class="word">The</span>
      <span class="word">good</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">you're</span>
      <span class="word">the</span>
      <span class="word">pilot</span>
      <span class="sign">.</span>
    </span>
  </div>
</div>
.hi {
  background-color: #fff3d1;
}

最终得到的效果如下图所示:

highlight_bad.jpg

句子的右侧不整齐,这显然不是我们想要的结果。其实解决办法也挺简单,从现象上来看,是单词左对齐导致的,如果我们使用两端对齐不就可以解决问题了吗?这时候如果你设置 sent 的样式 text-align: justify 会发现没有变化。原因很简单,MDN 官网对 text-align 的描述如下:

The text-align CSS property sets the horizontal alignment of the content inside a block element or table-cell box. This means it works like vertical-align but in the horizontal direction.

那这个时候只有一个选择了,那就是在 para 上使用 justify 。 新增 CSS 如下:

.para {
  text-align: justify;
}

highlight_good.jpg

💯 完美!

右侧的“火”

最容易想到的实现方式,就是让“火”相对于句子绝对定位,根据设计图定位到相应的右侧位置即可。真的可以吗?我们可以做一下尝试:

<div class="container">
  <div class="para">
    // 省略上文
    <span class="sent hi">
      <img class="fire" src="https://media-image1.baydn.com/storage_media_image/qtvmnf/cb7402fb943df88d0f4285c614b81e51.47aee7d51547db425fea728a4c9ec426.png" alt="fire">
      <span class="word">The</span>
      <span class="word">bad</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">time</span>
      <span class="word">files</span>
      <span class="sign">.</span>
      <span class="word">The</span>
      <span class="word">good</span>
      <span class="word">news</span>
      <span class="word">is</span>
      <span class="word">you're</span>
      <span class="word">the</span>
      <span class="word">pilot</span>
      <span class="sign">.</span>
      <span class="word">As</span>
      <span class="word">night</span>
      <span class="word">falls,</span>
      <span class="word">the</span>
      <span class="word">Qianlingshan</span>
      <span class="word">sports</span>
      <span class="word">park</span>
      <span class="word">begins</span>
      <span class="word">to</span>
      <span class="word">buzz</span>
      <span class="sign">.</span>
    </span>
    // 省略下文
  </div>
</div>
.hi {
  background-color: #fff3d1;
}

.container {
  padding: 10px 20px;
}

.para {
  text-align: justify;
}

.sent {
  position: relative;
}

.fire {
  position: absolute;
  right: 0;
  top: 0;
  width: 30px;
  height: 30px;
}

最终效果如下图:

fire_bad.jpg

从图中可以看到,“火”的位置非常奇怪,经过调试发现,“火”的位置是根据“句子”的起始和结束的位置来进行定位的。

虽然定位没有能解决问题,但是我们的思路还是很明确的,必须脱离文档流,照着这个思路,我们想到了本文的主角 float

当我们使用 float: right 页面如下所示:

fire_float_right.jpg

那这下就好办了,我们只需要让火往右侧偏移即可,使用如下代码:

// 省略其他 CSS 代码

.fire {
  float: right;
  width: 30px;
  height: 30px;
  margin-right: -30px;
}

最终得到如下图所示效果:

fire_good.jpg

💯 完美!

总结

  1. 思路很重要,脱离文档流是一个很重要的思考方向;
  2. 需要掌握 float 的相关特性;
  3. 利用 margin-right: -30px 进行右侧偏移,并将空间留给单词。