当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 第一章 层叠、优先级与继承(已完结)
- 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.1.1 内容水平居中
- 3.1.2 逻辑属性
- 3.1.3 用好逻辑属性的简写形式
- 3.2 盒模型(已完结)
- 3.2.1 避免使用魔数
- 3.2.2 调整盒模型
- 3.3.3 全局设置 border-box
- 3.3 元素的高度
- 3.3.1 控制溢出行为
- 3.3.2 百分比高度的备选方案
- 3.3.3 使用 min-height 和 max-height
- 3.4 负的外边距
- 3.5 外边距折叠
- 3.5.1 文字折叠
- 3.5.2 多个外边距折叠
- 3.5.3 向容器外折叠
- 3.6 容器内的元素间距问题 ✔️
- 3.6.1 当内容改变时的处理 ✔️
- 3.6.2 更通用的解决方案 ✔️
- 第四章 Flexbox 布局
- 4.1 Flexbox 布局原理(精译中 ⏳)
文章目录
- 3.6 容器内的元素间距问题
- 3.6.1 当内容改变时的处理
- 3.6.2 更通用的解决方案
- 3.7 本章小结
3.6 容器内的元素间距问题
图 3.18 间距适中的社交模块最终布局效果
先处理两个社交按钮的样式(译注:赞助商链接后续会添加,这里暂不用管)。页面已经预留了一个 button-link
类,用作 CSS 选择器再好不过了。
由于设计的是链接的通用样式,指定其为块级元素,不仅能让样式充满容器的整个宽度,还能让每个链接按钮独占一行。按以下代码更新页面样式:
代码清单 3.12 设置侧边栏按钮的大小、字体和颜色
.social-links {
max-inline-size: 25em; /* 收窄容器宽度 */
padding: 1em 1.5rem;
background-color: #fff;
border-radius: 0.5em;
}
.button-link {
display: block; /* 块级元素将填满所有可用宽度,并将每个链接独占一行 */
padding: 0.5em;
color: #fff;
background-color: var(--brand-color);
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
链接样式搞定后,还得处理好它们之间的间距。如果不指定外边距,按钮就会直接堆叠在一起,就像现在这样。备选方案有两个:在必然发生外边距折叠的两个社交按钮间,要么分别设置、要么同时设置它们的上下外边距。
然而不管采用哪种方案,都会遇到一个问题:元素外边距与所在容器的内边距将同时生效。例如给两个按钮加上样式 margin-top: 1.5em
,最终效果如图 3.19 所示。
图 3.19 按钮的顶部外边距在感官上增大了容器的内边距
此时,第一个按钮新增的顶部外边距令容器顶部间隙过大,与其余三边一对比显得很不协调。
这个问题有很多种解决方案,代码清单 3.13 给出的是一种较简单的版本。利用相邻兄弟组合选择器(+
)选中同一父元素下紧邻其他 button-link
后的 button-link
元素。此时所设置的外边距样式只对两个按钮之间的部分生效。
代码清单 3.13 使用相邻兄弟组合样式在按钮间应用外边距
.button-link {
display: block;
padding: 0.5em;
color: #fff;
background-color: var(--brand-color);
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
.button-link + .button-link {
/* 对紧跟某按钮链接的另一按钮链接应用顶部外边距 */
margin-block-start: 1.5em;
}
该方案应该是有效的。如图 3.20 所示,第一个按钮的上边距不见了,容器四周的间距都是一致的。
图 3.20 按钮周围应用了一致的间距
这种写法充分利用了 +
组合选择器,可以推广应用到需要设置容器内元素间隙的场景中。同理,该写法也适用于在一系列行内元素、或行内块级元素之间设置左外边距。相关组合选择器的汇总梳理,详见本书附录 A。
3.6.1 当内容改变时的处理
刚才的做法思路倒没问题,但只要向侧边栏添加更多内容,间距的问题就又出现了。比如按照以下内容,在页面上再加一个友情赞助的超链接,并指定一个样式类 sponsor-link
以便设置新样式。
代码清单 3.14 给侧边栏添加一个不同类型的链接
<aside class="social-links">
<a href="/mastodon" class="button-link">
Follow us on Mastodon
</a>
<a href="/facebook" class="button-link">
Like us on Facebook
</a>
<!-- 给侧边栏添加一个不同类型的链接 -->
<a href="/sponsors" class="sponsor-link">
Become a sponsor
</a>
</aside>
接着,就得为该链接设置样式,但同时还得处理好它与其他按钮之间的间距。图 3.21 是处理间距 之前 的样子。
图 3.21 第二个按钮与底部链接之间缺少间距
新链接的样式如下所示。样式更新后,您可能首先想的是再加个顶部外边距来解决间距问题。先别急,我接下来会给出另一个巧妙的替代方案。
代码清单 3.15 赞助商链接的样式
.sponsor-link {
display: block;
color: var(--brand-color);
font-weight: bold;
text-decoration: none;
}
再加一个顶部外边距固然正确,但鉴于 HTML 改动频繁的沉疴顽疾,没准下个月或来年,该侧边栏中的某些内容就得挪挪位置或者被替换掉,比如把友情赞助链接移到侧边栏的顶部,又或者需要添加一个组件来注册邮箱简讯等。
只要内容一变,相应的边距问题也只能再搞一遍,以确保每块内容之间都能间隔一致,但容器的上下边缘除外。
3.6.2 更通用的解决方案
Web 设计师 Heydon Pickering 曾表示,外边距“就像是在一个物体的某一侧抹了胶水,而你还没想好要不要把它贴到哪儿或者贴到什么东西上”。与其在当前页面反复设置同样的外边距,不如以一种更通用的方式固定写死,使得该间距任由页面结构如何调整都能生效。这就要用到一类特殊的选择器,Pickering 称之为 迟钝的猫头鹰选择器(lobotomized owl selector),因为它长这样:* + *
。关于该选择器的详细用法,Pickering 还特地写了一篇博客 https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/。
该选择器开头是一个可以选中任意元素的通用选择器(*
),接着是一个相邻兄弟组合器(+
),最后是另一个通用选择器。它因形似一只眼神呆滞的猫头鹰而得名。这只做了脑叶切除术的呆头鹰功能上与前面用过的选择器 .social-button + .social-button
差不多。区别在于它不会选中紧跟在其他按钮后的按钮,而是选中紧跟在任意元素后的任意元素。也就是说,它选中的是除首个子元素外所有同一父元素下的子元素。(也可以使用 :not(:first-child)
选择器等效替换)
接下来演示该选择器在设置页面顶部外边距的具体用法,不妨令其与一个新的“stack”类相结合,添加到需要设置子元素纵向间距的任意容器中。最终效果如图 3.22 所示。
图 3.22 所有元素间距一致
按代码列表 3.16 更新样式。这里用到了另一个组合选择器:子组合器(>
),让这只“呆萌猫头鹰”(lobotomized owl)只对 stack
类下的直接后代元素生效。这段代码在页面上大有用处。
代码清单 3.16 创建一个 stack 容器来纵向排布各元素间距
.stack > * + * {
/* 指向堆栈中除第一个以外的所有子项 */
margin-block-start: 1.5em;
}
接下来,就可以将 stack
类添加到任何需要设置子元素间距的容器中了。先加到 <body>
上,这样 <header>
和 <div class="container">
之间就隔开了;再加到 <div class="container">
上,这样主内容区和社交链接容器间也有了一致的间距;最后是社交链接容器,这样三个链接元素也统一隔开了。
加上该间距后,整个页面就大功告成了。完整样式如代码清单 3.17 所示:
代码清单 3.17 最终样式表
*,
*::before,
*::after {
box-sizing: border-box;
}
:root {
--brand-color: #0072b0;
--column-width: 1080px;
}
body {
margin: unset;
background-color: #eee;
font-family: Helvetica, Arial, sans-serif;
}
.page-header {
color: #fff;
background-color: var(--brand-color);
}
.page-header h1 {
max-inline-size: var(--column-width);
margin: 0 auto;
padding: 1em 1.5rem;
}
.container {
max-inline-size: var(--column-width);
margin-inline: auto;
}
.main {
padding: 1em 1.5rem;
background-color: #fff;
border-radius: 0.5em;
}
.social-links {
max-inline-size: 25em;
padding: 1em 1.5rem;
background-color: #fff;
border-radius: 0.5em;
}
.button-link {
display: block;
padding: 0.5em;
color: #fff;
background-color: var(--brand-color);
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
.sponsor-link {
display: block;
color: var(--brand-color);
font-weight: bold;
text-decoration: none;
}
.stack > * + * {
margin-block-start: 1.5em;
}
3.7 本章小结
- 在常规文档流中,行内元素并排排布,必要时换行。块级元素各自独占一行,并默认填满其容器的宽度。
- 逻辑属性指的是元素在文档流中的各边(sides)或尺寸大小,而非其明确方位。
- 盒模型描述了外边距、边框、内边距以及内容如何定义元素的尺寸大小。使用
box-sizing: border-box
可以让该尺寸大小的行为定义更加直观。 - 元素的高度是根据其内容动态确定的。明确限制高度可能会导致溢出问题。
- 元素的外边距可以与其容器外的其他外边距发生折叠,从而导致元素间的间距异常。应用
overflow: auto
可有效处理该问题。 - 在统一设置块级元素之间的间距方面,呆头鹰选择器不失为一个好用的工具。