当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 第一章 层叠、优先级与继承(已完结)
- 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-basis
、flex-grow
以及 flex-shrink
属性仅对其弹性子元素的高度生效,而非宽度。由于子元素设置了 flex: 1
, 它们的高度在必要时会延展到填满整个容器。无论左右两栏的高矮,此时主板块的底边都会和右边第二个小板块的底边始终对齐。
水平弹性盒子的大部分概念对于垂直方向(column
或 column-reverse
)同样适用,但有个 关键区别 务必牢记:在 CSS 中高度的处理方式与宽度存在本质上的不同。弹性容器会 100% 填满可用宽度,而高度则始终由自身的内容决定。即便改变主轴方向,也不会改变这个本质特征。
弹性容器的高度则由弹性子元素决定,它们会正好填满容器。在纵向 Flexbox 布局中,子元素的 flex-grow
和 flex-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 的 width
或 inline-size
属性强制设置一个宽度。
第三组规则集处理的是登录按钮。这些样式大多很简单,只有 cursor
属性可能相对陌生。它控制的是鼠标指针悬停在元素上方时的外观效果。其值为 pointer
时,鼠标指针会变成一个具有指示效果的手型,鼠标悬停到链接元素时的默认效果就是这个形状。它告诉用户该元素是可以点击的,这一细节处理可以让按钮样式更加完美。