【CSS in Depth 2 精译_025】4.3 弹性布局的方向

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

  • 第一章 层叠、优先级与继承(已完结)
    • 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.1.1 创建一个基础的 Flexbox 菜单
      • 4.1.2 添加内边距与间隔
    • 4.2 弹性子元素的大小(已完结)
      • 4.2.1 使用 flex-basis 属性
      • 4.2.2 使用 flex-grow 属性
      • 4.2.3 使用 flex-shrink 属性
      • 4.2.4 实际应用
    • 4.3 弹性布局的方向 ✔️
      • 4.3.1 变更弹性布局的方向 ✔️
      • 4.3.2 登录表单的样式设计 ✔️
    • 4.4 对齐、间距等细节处理(精译中 ⏳)

文章目录

    • [4.3 弹性布局的方向](#4.3 弹性布局的方向)
      • [4.3.1 变更弹性布局的方向](#4.3.1 变更弹性布局的方向)
      • [4.3.2 登录表单的样式设计](#4.3.2 登录表单的样式设计)

4.3 弹性布局的方向

Flexbox 的另一重要功能是切换主轴与副轴的方向,通过弹性容器上的 flex-direction 属性进行控制。该属性的初始值(row)规定子元素从左至右排列,一如前面演示的案例效果。若改为 flex-direction: column,则沿垂直方向从上到下排列。此外,属性值还支持 row-reverse 从右到左排列,以及 column-reverse 从下到上排列(如图 4.14 所示)。

图 4.14 改变 flex-direction 就改变了主轴的方向,与之垂直的副轴方向也会随之改变

本节将在示例页靠右的侧边栏演示该属性的用法,让两个子板块产生纵向堆叠效果。这貌似有些画蛇添足,毕竟它们已经竖直排列好了,块级元素也理应如此。但这样的页面布局存在一个极为隐蔽的漏洞,仅在左边的正文板块包含更多内容时才会显现,如图 4.15 所示。

只要给正文区 column-main 列添加一些标题及段落内容,就会发现主板块的高度超过了右边的侧边栏。按理来说 Flexbox 是可以让两列高度相等的,这里怎么不生效了呢?

图 4.15 主板块延伸到了右侧板块总高度外围(虚线标出了 column-sidebar 的大小)

如图 4.15(注意标注的虚线框)所示,左右两个弹性子元素确实是等高的。问题在于右侧子元素中的两个子板块没能填满整个侧边栏区域。

理想的布局效果应如图 4.16 所示。即使左侧内容区更长,右侧的两个子板块也会自动延展开来,填满整个侧边栏。在 Flexbox 出现以前,纯靠 CSS 几乎是无法实现的(需要略微借助 JavaScript 才行)

图 4.16 目标布局效果:右边栏的板块与左边的大板块对齐。

4.3.1 变更弹性布局的方向

要让两个子板块延展到填满整个容器的高,就得把右边栏(column-sidebar)改为弹性容器,并设置 flex-direction: column;再给其中的两个子板块的 flex-grow 都赋上一个非零的属性值。如代码清单 4.9 所示,将以下样式更新到本地样式表。

代码清单 4.9 在右侧创建一个弹性布局列

css 复制代码
.column-sidebar { 
  /* 对外部弹性盒而言是弹性子元素,对内部元素而言则是弹性容器 */
  flex: 1;
  display: flex;          
  flex-direction: column; 
  gap: var(--gap-size);   
}

.column-sidebar > .tile {
  /* 给侧边栏内部的弹性子元素一个非零的 flex-grow 值 */
  flex: 1;
}

至此就创建了一个嵌套的弹性盒子。元素 <div class="column-sidebar"> 既是外层弹性盒子的弹性子元素,又是内部两个子板块的弹性容器。其整体结构如下所示(简洁起见,文本内容已省略):

html 复制代码
<main class="flex">
  <div class="column-main tile">
    ...
  </div>
  <div class="column-sidebar">
    <div class="tile">...</div>
    <div class="tile">...</div>
  </div>
</div>

这个内部的弹性盒子,其弹性布局的方向为 column,主轴方向由此转为从上到下(副轴方向则变为从左到右)。也就是说,此时 flex-basisflex-grow 以及 flex-shrink 属性仅对其弹性子元素的高度生效,而非宽度。由于子元素设置了 flex: 1, 它们的高度在必要时会延展到填满整个容器。无论左右两栏的高矮,此时主板块的底边都会和右边第二个小板块的底边始终对齐。

水平弹性盒子的大部分概念对于垂直方向(columncolumn-reverse)同样适用,但有个 关键区别 务必牢记:在 CSS 中高度的处理方式与宽度存在本质上的不同。弹性容器会 100% 填满可用宽度,而高度则始终由自身的内容决定。即便改变主轴方向,也不会改变这个本质特征。

弹性容器的高度则由弹性子元素决定,它们会正好填满容器。在纵向 Flexbox 布局中,子元素的 flex-growflex-shrink 属性不会起作用,除非有其他因素强行改变弹性容器的高度。本例中的"其他因素"就是外层弹性容器衍生过来的高度。

4.3.2 登录表单的样式设计

页面的整体布局告一段落,剩下的工作是给右侧两个子板块中更小的内容元素设计样式,即登录表单和注册链接部分。登录表单就不用弹性盒布局了,但为了演示的完整性再简要过一遍。最终设计好的表单效果如图 4.17 所示。

图 4.17 登录表单的最终效果

<form> 的样式类 login-form 为 CSS 选择器,分别对登录表单中的标题、输入框及按钮三个部分进行样式设计,并根据代码清单 4.10 更新到示例页面。

代码清单 4.10 登录表单的样式设计

css 复制代码
/* 标题设为加粗、右对齐、全大写 */
.login-form h3 {
  margin: 0;
  font-size: 0.9em;
  font-weight: bold;
  text-align: end;
  text-transform: uppercase;
}

/* 仅为文本类型的输入框(不包含复选框与单选按钮)设置样式 */
.login-form input:not([type=checkbox]):not([type=radio]) {
  display: block;
  inline-size: 100%;
}

/* 按钮的样式 */
.login-form button {
  margin-block-start: 1em;
  border: 1px solid #cc6b5a;
  background-color: white;
  padding: 0.5em 1em;
  cursor: pointer;
}

先来看标题,用的都是熟悉的字体属性。text-align 用于文字右对齐,text-transform 则用于设置文字大写。注意观察,示例 HTML 里的内容并没有写成大写形式。当字母大写仅仅视为一种样式时,正常的做法是在 HTML 中按照标准的语法规则书写,再用 CSS 转成大写。这样今后无需重新输入 HTML 中的文字就能控制大小写。

第二组规则集处理的是输入框。这里的选择器比较特殊,主要是因为 <input> 元素很特殊。<input> 元素既可以输入文本和密码,也可以输入很多类似的 HTML5 数据,如数字、电子邮箱及日期;此外还能记录看上去截然不同的表单项数据,比如单选按钮和复选框的选中结果。

示例中 :not() 伪类选择器与属性选择器 [type=checkbox][type=radio] 组合起来的写法(详见附录 A),可以选中除复选框和单选按钮以外的所有 <input> 元素。这是一个黑名单方式:把不想选中的元素剔除掉。也可以采用白名单方式:将想要选中的所有 <input> 元素类型通过属性选择器一一罗列,但这样写起来就会显得十分冗长。

注意

尽管示例表单只出现了文本和密码输入框,但演示的重点在于,该 CSS 样式可能影响到后续其他的 HTML 标记,需要尽量予以兼顾。

在这组规则集中,输入框加上了 display: block 的样式,令其独占一行,同时将宽度设为 100%。通常情况下,块级元素会自动填满可用宽度,但 <input> 比较特殊,其宽度由 size 属性决定。该属性表示输入框在不出现滚动条的情况下大致能够容纳的字符数。若不指定 size 的值,则会赋一个默认值。也可以用 CSS 的 widthinline-size 属性强制设置一个宽度。

第三组规则集处理的是登录按钮。这些样式大多很简单,只有 cursor 属性可能相对陌生。它控制的是鼠标指针悬停在元素上方时的外观效果。其值为 pointer 时,鼠标指针会变成一个具有指示效果的手型,鼠标悬停到链接元素时的默认效果就是这个形状。它告诉用户该元素是可以点击的,这一细节处理可以让按钮样式更加完美。

相关推荐
luckycoke7 分钟前
小程序的右侧抽屉开关动画手写效果
前端·javascript·微信小程序·uni-app
慢慢雨夜1 小时前
uniapp 苹果安全域适配
java·前端·uni-app
凄凄迷人1 小时前
前端基于Rust实现的Wasm进行图片压缩的技术文档
前端·rust·wasm·图片压缩
敲代码不忘补水1 小时前
二十种编程语言庆祝中秋节
java·javascript·python·golang·html
史努比的大头1 小时前
前端开发深入了解性能优化
前端
码农研究僧1 小时前
Java或者前端 实现中文排序(调API的Demo)
java·前端·localecompare·中文排序·collator
吕永强2 小时前
HTML表单标签
前端·html·表单标签
范特西是只猫2 小时前
echarts map地图动态下钻,自定义标注,自定义tooltip弹窗【完整demo版本】
前端·javascript·echarts
麒麟而非淇淋2 小时前
AJAX 进阶 day4
前端·javascript·ajax
图灵苹果2 小时前
【个人博客hexo版】hexo安装时会出现的一些问题
前端·前端框架·npm·node.js