【CSS in Depth 2 精译_087】14.4:CSS 中的浮动特效以及在文字环绕中的应用 + 14.5:本章小结

当前内容所在位置(可进入专栏查看其他译好的章节内容)

  • 第四部分 视觉增强技术 ✔️
  • 【第 14 章 蒙版、形状与剪切】 ✔️
    • 14.1 滤镜
      • 14.1.1 滤镜的类型
      • 14.1.2 背景滤镜
    • 14.2 蒙版
      • 14.2.1 带渐变效果的蒙版特效
      • 14.2.2 基于亮度来定义蒙版
      • 14.2.3 其他蒙版属性
    • 14.3 剪切路径
      • 14.3.1 多边形的裁剪路径
      • 14.3.2 Firefox 内置的剪切路径工具
      • 14.3.3 其他剪切路径类型
    • 14.4 浮动与形状 ✔️
      • 14.4.1 浮动 ✔️
      • 14.4.2 形状的定义 ✔️
    • 14.5 本章小结 ✔️

《CSS in Depth》新版封面

《CSS in Depth》新版封面

译者按
趁着今天冬至,本着夏练三伏冬练三九的原则,顺便把第 14 章的剩余内容全部拿下。这一节作者其实是在为 CSS 的浮动特效正名,多年来浮动特效一直被业内人士带偏,还美其名曰“浮动布局”;而它真正的设计初衷一直被人们忽略,直到 Flexbox 和 Grid 布局的出现情况才逐渐改善。要是再将浮动与 CSS 新推出的文字环绕形状相结合,就能实现很多经常在 PPT 中才会见到的效果。一起来看看吧!

14.4 浮动和形状 Floats and shapes

使用蒙版和剪切路径来重塑元素外观看着很有意思,但从页面布局的角度看,该元素仍然是一个普通的矩形框。想让基础布局拥有更复杂的形状,就需要用到 shape-outside 属性。这就会让文本这样的行内内容(inline content)以另外一种方式环绕在该元素周围,不同于以往沿着元素的直角边进行排列。

shape-outside 属性非常适合与遵循相同轮廓的蒙版、剪切路径或圆角半径相结合来实现一些页面特效。此时,页面元素看似有了不同的形状,文字也紧密环绕在相同的形状周围。图 14.12 就给出了这样一个典型案例:猎鹰图片被剪切成圆形,一旁的文字也围绕在由 shape-outside 属性定义的同心圆周围。

图 14.12 定义形状会让行内内容围绕该形状的轮廓进行排列

【图 14.12 定义形状会让行内内容围绕该形状的轮廓进行排列】

要使用 shape-outside 属性,元素就必须设为 浮动(floated 元素。设为浮动元素后,该元素将向页面左右两侧的某一侧靠拢,并让行内内容围绕其外边距盒(margin box)排布。鉴于浮动本身就是个复杂的话题,本节将先行阐述它的基本概念与工作原理,然后再介绍与形状(shapes)相关的知识。

14.4.1 浮动 Floating

浮动设置会将一个元素(通常为图片)拉到所在容器的左侧或右侧,让文档流环绕在该元素周围。某浮动元素在一段文字内的渲染效果如图 14.13 所示。由于这样的布局在报纸和杂志排版中非常常见,CSS 也为此添加了浮动这一特效。

图 14.13 多行文本环绕在浮动元素周围的效果示意图

【图 14.13 多行文本环绕在浮动元素周围的效果示意图】

浮动元素会从常规文档流中移除,并被带往所在容器的边缘位置。随后,文档流重新排布,但行内内容会围绕浮动元素当前占据的空间进行排列。浮动元素并没有从文档流中的初始位置向上或向下移动;换句话说,其最终位置取决于该元素在 HTML 文本中的初始方位。

通过声明 float: left 或者 float: right 可以将一个元素浮动到指定的方向。如果将多个元素浮动到同一个方向,这些元素就会并排排列,如图 14.14 所示。

图 14.14 并排排列的两个浮动元素效果图

【图 14.14 并排排列的两个浮动元素效果图】

下面我们将在示例页中添加一些内容,实现图片浮动到一旁的效果。然后再设置一些剪切特效,让文字排列呈现出某个形状。请根据代码清单 14.13 同步更新本地 HTML 示例页面。您既可以删除 <body> 元素中的内容,也可以将示例代码添加到现有内容的下面。

代码清单 14.13 带浮动图片的示例页 HTML 标记

<div>
  <div class="poem-image"><!-- 待浮动的元素 -->
    <img src="images/eagle.jpg" alt="Golden Eagle">
  </div>
  <h1>Hope is the thing with feathers</h1>
  <p><cite>Emily Dickinson</cite></p>
  <p>
    “Hope” is the thing with feathers<br>
    That perches in the soul,<br>
    And sings the tune without the words,<br>
    And never stops at all,
  </p>
  <p>
    And sweetest in the Gale is heard;<br>
    And sore must be the storm<br>
    That could abash the little bird<br>
    That kept so many warm.
  </p>
  <p>
    I’ve heard it in the chillest land,<br>
    And on the strangest sea;<br>
    Yet, never, in extremity,<br>
    It asked a crumb of me.
  </p>
</div>

提示

在本例中,<img> 元素被放在了一个 div 容器中。这并非浮动样式的专属写法。但我发现在某些情况下,在 “普通”(“normal”) 元素上处理形状比在图片元素上更简单。从专业技术的角度看,图片元素在 HTML 中是一个 可替换元素(replaced element;在某些情况下,该元素的尺寸大小及方位可能与普通元素的行为模式略有不同。具体来说,在 Chrome 浏览器中使用 object-position 属性会出现一个 Bug,可能会对环绕在该元素附近的文本位置产生不良影响。

接着,我们将设置一些 CSS 样式来适当调整图片的尺寸,并将其浮动到页面左侧。完成设置后的页面最终效果将如图 14.15 所示。

图 14.15 将图片浮动到文字左侧的页面效果图

【图 14.15 将图片浮动到文字左侧的页面效果图】

请将代码清单 14.14 中的 CSS 样式添加到本地样式表,并在浏览器中查看渲染效果。我们在图片上声明了 display: block,这样行高就不会给父级 div 元素增加额外的高度 —— 尽管在重置样式(reset styles)中我也常常这样声明(详见第 8 章)。

代码清单 14.14 将图片元素浮动到页面左侧的示例样式代码

.poem-image {
  float: left;
  margin-right: 15px;
}

.poem-image > img {
  display: block;
  height: 350px;
  width: 350px;
  object-fit: cover;
}

在 HTML 中,浮动元素在其余行内内容中的位置,对于确定哪些文本行将会环绕该元素而言至关重要。图片上方的文字仍旧在图片上方不变,但与图片同行或者在该行下方渲染的文字将会环绕该浮动元素排列。在本例中,我们希望整首诗歌都围绕在图片的右侧,因此需要将图片放到 HTML 文档的最前面。

如果对浮动的基本特性不太熟悉,建议您挪一挪该浮动元素来切身感受它的特点。比如将其放到段落中间,看看渲染出的最终位置。如果浮动元素是一个行内元素(inline element),还可以将其放到某个句子中。

浮动元素的另一个有趣、偶尔也会让人猝不及防的行为特征,是它们不会给所在的父元素贡献任何高度。如果一个浮动元素是某个 <div> 元素的唯一子元素,则该 div 的高度将渲染为 0。这么做是为了让您可以在某个段落(<p>)内浮动一张图片时,让后续段落的内容也能继续围绕该图片排列,如图 14.16 所示。

图 14.16 某容器内的浮动样式会扩展到下一个容器,让两个容器内的文字均围绕该浮动元素排列

【图 14.16 某容器内的浮动样式会扩展到下一个容器,让两个容器内的文字均围绕该浮动元素排列】

浮动的这一行为特征,不仅在两个容器均为段落元素时是有意义的,且当它们是两个 div 元素、或者其他任意块级元素(block-level element)时也同样适用。若偏要让另一个元素出现在浮动元素的下方,则需要使用 clear: both;当然除了 both 外,也可以使用 leftright 来清除指定方向上的元素浮动。

此外,还可以在容器的 ::after 伪元素上设置 clear 属性来让容器强行包含其浮动的子元素。这样一来容器元素的高度便可以扩展到浮动子元素的底部:

.contain-floats::after {
  display: block;
  content: "";
  clear: both;
}

在 CSS 引入 Flexbox 布局或网格布局之前,浮动元素(floats)是构建页面复杂布局的唯一选择。由于这并非浮动样式的设计初衷,因此在实现页面布局的过程中往往存在一定的困难,实现手法也不太优雅;但随着全新布局技术的出现,这样的局面已然成为了历史。人们可以仅仅出于浮动设计的本意来使用浮动,即:当确实需要让文字环绕在某元素周围时,再考虑启用浮动。

14.4.2 形状的定义 Defining a shape

让示例页中的图片浮动起来后,就可以利用 shape-outside 属性为一旁的文字定义形状了。该属性的合法值与 clip-path 属性大同小异,都支持:margin-boxborder-boxpadding-boxcontent-boxinset()circle()ellipse() 以及 polygon();最显著的区别在于处理 SVG 路径时的 path() 函数。尽管这个值已经纳入 CSS 规范,但目前在任何浏览器中 shape-outside 均不支持属性值为 path()。没准今后就可以用了。

这就意味着,人们通常可以给元素的剪切路径和形状指定完全相同的属性值。一个值得推荐的做法是:将这个值赋给某个自定义属性,然后在设置这两个属性时直接引用这个值。该做法尤其适用于需要定义某个复杂多边形的应用场景中。请根据代码清单 14.15 同步更新本地样式表,按照上述思路将这个属性值设为圆形。

代码清单 14.15 剪切路径和形状皆为圆形时的示例样式代码

.poem-image {
  float: left;
  margin-right: 15px;
  --shape: circle(50%);
  clip-path: var(--shape);
  shape-outside: var(--shape);
}

.poem-image > img {
  display: block;
  height: 350px;
  width: 350px;
  object-fit: cover;
}

这样一来,猎鹰图片按圆形剪切,并且旁边的文字会整机环绕在它周围,最终效果如图 14.17 所示(与前面展示的图 14.12 相同)。

图 14.17 文字同样按圆形环绕排列的效果图

【图 14.17 文字同样按圆形环绕排列的效果图】

您也可以将自定义属性 --shape 改为其他值,例如 polygon()ellipse() 或者其他有效取值,然后观察文字对应的环绕情况。如果想让文字紧密环绕浮动元素的圆角半径 border-radius 时,也可以考虑以下属性值:margin-boxborder-boxpadding-box 以及 content-box

另外,鉴于圆形也可以通过设置圆角半径为 50% 来实现,因此也可以不通过剪切路径、而改用圆角半径来达到同样的效果,如代码清单 14.16 所示。注意,此时需要同时在图片元素(为了剪切图片)和图片所在的 div 容器上(为了影响 shape-outside 属性)设置圆角半径。

代码清单 14.16 围绕边框圆角定义的形状样式代码

.poem-image {
  float: left;
  margin-right: 15px;
  shape-outside: margin-box; /* 围绕圆角边框轮廓定义的形状 */
  border-radius: 50%;
}

.poem-image > img {
  display: block;
  height: 350px;
  width: 350px;
  object-fit: cover;
  border-radius: 50%;
}

在本例中,我们用了一个右外边距来将图片和环绕文字隔开一小段距离。也可以使用 shape-margin 属性,例如声明 shape-margin: 15px 将在 shape-outside 指定的轮廓周围再增加 15px 的外边距。

但是设置的 shape-margin 外边距并不会延伸到浮动元素的外边距之外。此时,剪切路径只能到达元素的边缘而非外边距边缘,这并非我们想要的效果。尽管上下两端的文字依然会环绕圆形轮廓排列,但中间的文本环绕的却是由元素外边距盒(margin box)构成的直角边。并且在使用 shape-margin 前,最好能确保环绕形状的边缘与元素边缘留有足够的空间才敢放心使用。关于这一点稍后我会用一个案例来演示说明。

译注

改为 shape-margin 后的这段描述感觉有点抽象,为便于理解,这里附上我本地实测的效果截图:

补图:容器样式改为 shape-margin: 15px 后的实际文字环绕效果

【补图:容器样式改为 shape-margin: 15px 后的实际文字环绕效果】

14.4.2.1 让形状贴合渐变蒙版 Matching a shape to a gradient mask

shape-outside 属性也可以像蒙版那样对某个图片元素生效。这对渐变特效来说尤为适用,因为这样一来就能将元素沿某个斜边进行剪切并让文字环绕斜边排列,如图 14.18 所示。

图 14.18 利用线性渐变定义的对角线形状

【图 14.18 利用线性渐变定义的对角线形状】

在本例中,我们在图片蒙版以及环绕形状上同时设置了相同的线性渐变特效,倾斜角均为 65 度。试根据代码清单 14.17 提供的渐变样式代码同步修改本地样式表。注意,示例代码中并未限制图片的宽度,这样可以给斜边提供更多空间。

代码清单 14.17 利用渐变特效定义的环绕形状的样式代码

.poem-image {

  float: left;
  --gradient: linear-gradient( /* 对角线型渐变样式 */
    65deg,
    black 0 375px,
    transparent 375px);
  mask: var(--gradient);
  shape-outside: var(--gradient);
  shape-margin: 15px;
}

.poem-image > img {
  display: block;
  height: 350px;
  object-position: -100px 0; /* 将猎鹰调整到画面中心 */
}

将颜色节点设置在 375px 的位置,可以实现从黑色到透明的突变效果。该节点的位置坐标、连同 65 度的倾斜角,都是在浏览器的开发者工具中微调得到的。接着我又设置了 object-position 属性,将猎鹰重新调至画面正中位置,否则会被右侧的环绕形状切掉一部分。建议您在浏览器中多改改这些数值,看看渐变效果会怎样变化。

由于浮动元素向右延伸并超出了环绕形状的边缘,此时改用 shape-margin 也是没问题的。此外,也可以使用径向渐变,例如:将自定义属性 --gradient 改为 radial-gradient(circle at 175px, black 175px, transparent 175px) 将得到一个圆形的剪切路径特效,几乎与代码清单 14.15 中演示的 circle(50%) 的效果完全相同。

在本例的线性渐变特效中,我们定义了一个从黑色突变到透明色的颜色节点,但这并不是什么固定操作。如果定义的是一个由黑色平滑过渡到透明的渐变特效,则环绕形状的边缘将由不透明度变为 0% 时的位置来界定。

您也可以通过 shape-image-threshold 属性来动手调整渐变效果对应的边缘。例如,指定 shape-image-threshold: 0.3 会让文字紧密环绕在图片不透明度渐变到 30% 时所形成的形状周围。您也可以利用该方法实现文字与图片的重叠渲染,让文字环绕在图片仍然依稀可见的位置,效果如图 14.19 所示。

图 14.19 设置容器的 shape-image-threshold 属性可以定义形状边缘对应的不透明度

【图 14.19 设置容器的 shape-image-threshold 属性可以定义形状边缘对应的不透明度】

本章演示的页面特效能够让您的页面从网上大量的常见样式设计中脱颖而出。这些功能特性往往更接近人们在报刊杂志或者其他类型的印刷设计中见到的样式效果。随着 Flexbox 弹性布局和 Grid 网格布局的出现,利用浮动元素来实现页面布局的做法几乎销声匿迹了,但浮动样式仍然有它的用武之地,尤其是当您想实现某些独具风格且引入注目的页面特效时,情况更是如此。


14.5 本章小结

  • 滤镜具备的颜色管理功能与模糊特效将会在整个元素范围内生效。
  • 背景滤镜的滤镜特效只对透过当前元素背后渲染出来的图片或内容部分生效。
  • 蒙版可以根据蒙版图片或蒙版渐变特效中的透明部分有选择地隐藏被遮挡元素的局部区域。
  • 剪切路径可以根据其路径定义的形状有选择地隐藏元素的局部区域。该路径通常为圆形、椭圆形或其他自定义的多边形。
  • 设置了浮动的页面元素将被拉到所在容器的左侧或右侧,并使得行内内容(inline content)围绕浮动元素边缘排列。
  • 浮动元素的文字环绕形状可以通过 shape-outside 属性手动调整。其属性值可以利用元素的剪切路径或者蒙版图片来定义。这样一来,一旁的文字将紧密环绕在元素可见区域形成的轮廓外围。


关于《CSS in Depth》(中译本书名《深入解析 CSS》)

第 1 版第 2 版
读者评分原版:4.7(亚马逊);中文版:9.3(豆瓣)原版:5.0(亚马逊);中文版:暂无,待出版
出版时间原版:2018 年 3 月;中文版:2020 年 4 月原版:2024 年 7 月;中文版:暂无,待出版
原价原版:$44.99;中文版:¥139.00原版:$59.99;中文版:暂无,待出版
现价原版:$36.49;中文版:¥52.54 起步原版:$52.09;中文版:暂无,待出版
原版国内预订起步价 ¥461.00起步价 ¥750.00

本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!

目前已完结的章节(可进入本专栏查看详情,连载期间完全免费):

  • 第一章 层叠、优先级与继承(已完结)
    • 1.1 层叠
    • 1.2 继承
    • 1.3 特殊值
    • 1.4 简写属性
    • 1.5 CSS 渐进式增强技术
    • 1.6 本章小结
  • 第二章 相对单位(已完结)
    • 2.1 相对单位的威力
    • 2.2 em 与 rem
    • 2.3 告别像素思维
    • 2.4 视口的相对单位
    • 2.5 无单位的数值与行高
    • 2.6 自定义属性
    • 2.7 本章小结
  • 第三章 文档流与盒模型(已完结)
    • 3.1 常规文档流
    • 3.2 盒模型
    • 3.3 元素的高度
    • 3.4 负的外边距
    • 3.5 外边距折叠
    • 3.6 容器内的元素间距问题
    • 3.7 本章小结
  • 第四章 Flexbox 布局(已完结)
    • 4.1 Flexbox 布局原理
    • 4.2 弹性子元素的大小
    • 4.3 弹性布局的方向
    • 4.4 对齐、间距等细节处
    • 4.5 本章小结
  • 第五章 网格布局(已完结)
    • 5.1 构建基础网格
    • 5.2 网格结构剖析 (上)
      • 5.2.1 网格线的编号(下)
      • 5.2.2 网格与 Flexbox 配合(下)
    • 5.3 两种替代语法
      • 5.3.1 命名网格线
      • 5.3.2 命名网格区域
    • 5.4 显式网格与隐式网格(上)
      • 5.4.1 添加变化 (中)
      • 5.4.2 让网格元素填满网格轨道(下)
    • 5.5 子网格(全新增补内容)
    • 5.6 对齐相关的属性
    • 5.7 本章小结
  • 第六章 定位与堆叠上下文(已完结)
    • 6.1 固定定位
      • 6.1.1 创建一个固定定位的模态对话框
      • 6.1.2 在模态对话框打开时防止屏幕滚动
      • 6.1.3 控制定位元素的大小
    • 6.2 绝对定位
      • 6.2.1 关闭按钮的绝对定位
      • 6.2.2 伪元素的定位问题
    • 6.3 相对定位
      • 6.3.1 创建下拉菜单(上)
      • 6.3.2 创建 CSS 三角形(下)
    • 6.4 堆叠上下文与 z-index
      • 6.4.1 理解渲染过程与堆叠顺序(上)
      • 6.4.2 用 z-index 控制堆叠顺序(上)
      • 6.4.3 深入理解堆叠上下文(下)
    • 6.5 粘性定位
    • 6.6 本章小结
  • 第七章 响应式设计(已完结)
    • 7.1 移动端优先设计原则(上篇)
      • 7.1.1 创建移动端菜单(下篇)
      • 7.1.2 给视口添加 meta 标签(下篇)
    • 7.2 媒体查询(上篇)
      • 7.2.1 深入理解媒体查询的类型(上篇)
      • 7.2.2 页面断点的添加(中篇)
      • 7.2.3 响应式列的添加(下篇)
    • 7.3 流式布局
    • 7.4 响应式图片
    • 7.5 本章小结
  • 第八章 层叠图层及其嵌套
    • 8.1 用 layer 图层来操控层叠规则(上篇)
      • 8.1.1 图层的定义(上篇)
      • 8.1.2 图层的顺序与优先级(下篇)
      • 8.1.3 revert-layer 关键字(下篇)
    • 8.2 层叠图层的推荐组织方案
    • 8.3 伪类 :is() 和 :where() 的用法
    • 8.4 CSS 嵌套的使用
      • 8.4.1 嵌套选择器的使用
      • 8.4.2 深入理解嵌套选择器
      • 8.4.3 媒体查询及其他 @规则 的嵌套
    • 8.5 本章小结
  • 第九章 CSS 的模块化与作用域
    • 9.1 模块的定义
      • 9.1.1 模块和全局样式
      • 9.1.2 一个简单的 CSS 模块
      • 9.1.3 模块的变体
      • 9.1.4 多元素模块
    • 9.2 将模块组合为更大的结构
      • 9.2.1 模块中多个职责的拆分
      • 9.2.2 模块的命名
    • 9.3 CSS 的作用域
      • 9.3.1 CSS 作用域的就近原则
      • 9.3.2 划定作用域的边界
      • 9.3.3 CSS 中的隐式作用域
      • 9.3.4 关于 CSS 作用域与层叠图层
    • 9.4 CSS 模式库
    • 9.5 本章小结
  • 第十章 CSS 容器查询
    • 10.1 容器查询的一个简单示例
      • 10.1.1 容器尺寸查询的用法
    • 10.2 深入理解容器
      • 10.2.1 容器的类型
      • 10.2.2 容器的名称
      • 10.2.3 容器与模块化 CSS
    • 10.3 与容器相关的单位
    • 10.4 容器样式查询的用法
      • 10.4.1 将模块与所在容器解耦
      • 10.4.2 减少重复代码
    • 10.5 本章小结
  • 第 11 章 颜色与对比
    • 11.1 通过对比进行交流
      • 11.1.1 模式的建立
      • 11.1.2 还原设计稿
    • 11.2 颜色的定义
      • 11.2.1 色域与色彩空间
      • 11.2.2 CSS 颜色表示法(RGB、Hex、HSL、HWB、LAB/OKLAB、LCH/OKLCH)
    • 11.3 利用 OKLCH 处理颜色(上篇)
      • 11.3.4 从页面其他颜色衍生出新颜色(下篇)
    • 11.4 思考字体颜色的对比效果
    • 11.5 本章小结
  • 第 12 章 CSS 排版与间距
    • 12.1 间距设置
      • 12.1.1 使用 em 还是 px
      • 12.1.2 对行高的深入思考
      • 12.1.3 行内元素的间距设置
    • 12.2 Web 字体
    • 12.3 谷歌字体
    • 12.4 @font-face 的工作原理
      • 12.4.1 字体格式与回退处理
      • 12.4.2 同一字型的多种变体形式
    • 12.5 性能因素考量
      • 12.5.1 font-display 属性解析
      • 12.5.2 可变字体的用法
    • 12.6 调整字间距,提升可读性
      • 12.6.1 正文的字间距
      • 12.6.2 标题、小元素和间距
    • 12.7 本章小结
  • 第 13 章 渐变、阴影与混合模式
    • 13.1 渐变
      • 13.1.1 使用多个颜色节点(上)
      • 13.1.2 颜色插值方法(中)
      • 13.1.3 径向渐变(下)
      • 13.1.4 锥形渐变(下)
    • 13.2 阴影
      • 13.2.1 利用渐变和阴影打造立体感
      • 13.2.2 使用扁平化设计创建元素
      • 13.2.3 创建混合风格的按钮外观
    • 13.3 混合模式
      • 13.3.1 为图片上色
      • 13.3.2 混合模式的类型
      • 13.3.3 图片纹理的添加
      • 13.3.4 融合混合模式的用法
    • 13.4 本章小结
  • 附录
    • 附录A:CSS 选择器参考
    • 附录B:CSS 预处理器简介
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安冬的码畜日常

您的鼓励是我持续优质内容的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值