原文链接:Intrinsic Sizing In CSS,by Ahmad Shadeed
CSS 中存在两种尺寸:内在尺寸(intrinsic)和外在尺寸(extrinsic)。为元素的 width
、height
设置的固定属性值,就是指外部尺寸,这是最常用的方式。而内部尺寸,则是由元素包含的内容量决定的。
本篇将会详细介绍控制内在尺寸的每个值,看看它们的使用能带来什么好处。同时,我还会举例说明这些值与 CSS Grid 布局/其他属性如何结合使用。
外在尺寸
外在尺寸是指用精确的值指定元素尺寸。举个例子:
.c-button {
width: 100px;
}
这个按钮的尺寸是 100px
,这就是外在尺寸了。再比如一个 <div>
元素,它默认是个块级元素,就是说它的宽默认等于 100%
父元素的宽。
有时,我们想要根据元素实际的内容来设置尺寸,这个时候,使用外在尺寸就没有用了。接下来,我们来看看如何是用内在属性值来解决问题的吧!
min-content
min-content
值表示内在最小宽度(译注:这里说的不准确,也可以是“最小高度”,因此应该称为“最小尺寸”),它等于元素内容里最长的那个单词宽度。
CSS Working Group (CSSWG) 的说法是:
The inline size that would fit around its contents if all soft wrap opportunities within the box were taken.
坦率地讲,我太理解 CSSWG 关于这个概念的定义。我自己是这么理解的:我在元素的周围包裹了一个框,元素内容(很多单词)会因此而折行,这个框的宽度将等于元素中最长的那个单词。如果我这里表述有误的话,希望大家来更正。
举一个例子,有一个标题元素:
<h2>A title for an awesome article</h2>
h2 {
width: min-content;
}
大家可以看见,当元素的 width
设置成 min-content
后,其宽度等于最长单词的宽度,也就是这里的“awesome”。
max-content
max-content
表示元素的内在首选宽度(intrinsic preferred width),它等于元素内容的宽。
还举一个标题元素的例子,不过这次改用 max-content
了:
h2 {
width: max-content;
}
注意观察,元素宽度等于标题宽度了。这个宽度是动态的,随着标题内容的改变,max-content 所代表的值也相应改变。
fit-cotent
这个属性可以看成是 min-content
和 max-content
的结合。搜索的时候,我发现 Stackoverflow 上的这个回答我很喜欢:
fit-content
默许使用max-content
;如果 available <max-content
,那就使用 available;如果 available <min-content
,那就使用min-content
。
画一个流程图表示,就是下面这样的:
注意,这里的“available”表示元素在视口中的可用空间。
🤔 译注 |
---|
上面的流程图跟 Stackoverflow 上的回答比起来,并不十分清晰,反而是后者更容易理解起来。关于 Stackoverflow 上的回答我的理解如下:fit-content 属性到底取用何值,跟当前元素的可用空间(available)是紧密相关的。1. 如果可用空间充足,那就用你元素的 max-conetnt 又何妨,反正够装你的。2. 如果可用空间不够充裕,比 max-conetnt 小点,那就得用可用空间的值了,这才显得合适(fit),不会导致内容越界。3. 如果可用空间很少,甚至比 min-conetnt 还小,那不好意思,得用 min-content 了,不然显示会很难看,就不合适了。 |
让我们举个例子看看它是如何工作的。
h2 {
width: fit-content;
}
查看下面的 GIF 图,观察标题尺寸是如何随着视口的变化做调整的。
我们再回顾一下关于 fit-content
的知识:如果当前的可用空间比 max-content
还大的话,width
就等于 max-content
;如果可用空间比 max-content
的小的话,那么 width
就等于可用空间的宽了;最后,如果可用空间比 min-content
还小,那么 width
就等于 min-content
。
到目前为止,我解释完了每一个内在值。让我们转向真实的案例来看下吧。
使用案例
<figure>
和 <caption>
现在我们假设有一个带 <caption>
的 <figure>
,因为它是个块级元素,因此默认等于 100% 父元素宽度的。
<figure>
<img src="blueberry-cheesecake-x.png" alt="">
<figcaption>..</figcaption>
</figure>
我们预期的行为是希望 <figure>
包裹图像的,使用 max-content
就能取得这些效果,让 <figure>
与内容(最大)宽度一样。
figure {
width: max-content;
margin-left: auto;
margin-right: auto;
}
但有一个问题,如果图片比视口范围还大的话,这时因为 <figure>
的宽度就等于图片的宽度,因此就会导致水平滚动条的出现。
为了解决这个问题,我们就要为图片使用 fit-content
了。它不会让大图片超出视口之外显示。
figure {
width: fit-content;
}
带分隔符的标题
在这个例子里,“Top Stories”要折成两行显示。宽度还是动态的,就是说不管实际标题如何,都需要折行。为了实现这个效果,我们可以使用 min-content
。
span {
width: min-content;
}
带下划线的标题
内在值的另一个有趣的用例是带边框的标题,要求边框跟标题内容一样长。考虑下图:
注意,标题是个块状元素。为了得到上述的效果,以前的做法是将内容包装在 <span>
标签里,给 <span>
设置边框效果。
<h2><span>A title for an awesome article</span></h2>
h2 span {
border-bottom: 2px solid #e2deed;
}
当然,我们还可以借助 fit-content
来让标题宽度与内容一样长。
h2 {
width: fit-content;
margin-left: auto; /* For centering */
margin-right: auto; /* For centering */
border-bottom: 2px solid #e2deed;
}
导航
如果一个页面导航的宽度是基于内容的。那么,可以通过使用 max-content
,轻松实现效果:
.c-nav {
width: max-content;
}
Todo 列表
在网上找内在值的使用案例的时候,看到了 一篇文章,将我吸引了。
考虑下面的例子:
这个 Todo 列表包含:页眉、列表和页脚。
不管有多少列表项,中间部分的高度都应该是 100% - header - footer
。为了实现这个效果,我们可以将 CSS Grid 与 min-content
搭配使用。
.c-todo {
display: grid;
grid-template-rows: min-content auto min-content;
height: 100vh;
}
你可能想知道,如果我们不使用 min-content
,会是什么结果呢?好吧,来看看:
聊天窗口
设想构建一个聊天程序。在下面的示例里,布局结构与 Todo 列表非常相似。当没有\聊天记录,并且没有使用 min-content
时,就会导致布局遭到破坏。
Hero
假设我们页面 <header>
里包含一个 Hero 组件。我们的目标是让这个 Hero 组件实现动态布局,占据一屏里剩下的空间。
.c-section {
display: grid;
grid-template-rows: min-content 1fr;
}
有两行内容,第一行使用的是最小内容高度,而第二行则可以扩展、填充完剩下的可用空间。
Sidebar 和 Main
我总是想知道为什么我们非要给侧边栏一个固定宽度呢。如果它的宽度是基于内容的呢?比如说,它有一个基于内容的最小宽度和一个最大宽度?我们来试试。
<div class="wrapper">
<aside></aside>
<main></main>
</div>
.wrapper {
grid-template-columns: fit-content(150px) 1fr;
grid-gap: 1rem;
}
通过使用 CSS Grid fit-content
函数,我们可以确保侧边栏的宽度不会超过 150px
,并且可以在内容很短的情况下缩小到 150px
以下。
当侧边栏的内容很少时,它会缩小一点:
🤔译注
这的
fit-content()
文中并没有讲到。可以这样简单理解:一般使用这个功能函数时,所用参数一般都是小于元素的
max-content
值的。比如fit-content(150px)
,那么说150px
是小于元素max-content
值的。这种情况下,元素最终的渲染尺寸是介于min-content ~ 150px
之间的。具体是多少还要看当前的可用空间,如果可用空间充足,拿就显示最大的150px
,如果可用空间小,那么就取min-content ~ 150px
之间的某个值,如果可用空间不足(比min-content
还小),那就用最小值min-content
,不能再小了。当然,如果
fit-content()
里的值比元素max-content
还大,那么元素最终的渲染尺寸是介于min-content ~ max-content
之间的。具体是多少还要看当前的可用空间,与上面类似。反正,
fit-content()
返回的最小值是min-content
,不能比min-content
更小了。更多信息,查看 MDN 上的 fit-content() 文档。
标题和描述
我们有一个标题和一个描述文本。描述文字的宽度不能超过主标题的宽度。对我来说,这是一个有趣的用例,我以前认为它不可能仅用 CSS 就能实现。
看下下面的模型。
为了实现上述功能,我们需要将 min-content
设置为包装元素的宽度,而为标题元素设置 width: max-content
。
section {
width: min-content;
margin: 0 auto;
text-align: center;
}
h2 {
width: max-content;
}
请注意,上面代码需要在移动端做些调整额,否则可能会导致导致水平滚动条的出现。
浏览器兼容性
根据 Can I Use 数据,除了 Microsoft Edge (EdgeHTML) 之外的所有主流浏览器都支持内在值的设置了。
注意:Microsoft Edge (Chromium) 从发布的第一个版本(79)就已经支持了。
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。
(完)