- Published on
shrink-to-fit(自适应宽度)
- Authors
- Name
- Pursue
开篇
自适应宽度是指当未明确设定容器的宽度(或外边距设为 auto)时,再特定的情况下容器的宽度会根据情况自行设定,而设定的结果往往并不是我们想要的。
W3C 规范中描述的几种 shrink-to-fit 的情况
- 10.3.5 Floating, non-replaced elements
- 10.3.7 Absolutely positioned, non-replaced elements
- 10.3.8 Absolutely positioned, replaced elements
- 10.6.4 Absolutely positioned, non-replaced elements
规范中提到了一个基本概念,我们先来了解一下。
replaced elements & non-replaced elements
css 把 html 元素分为了两类:替换元素和非替换元素。
1.可替换元素
:
可替换元素是这样一些元素,其展现不是由 CSS 来控制的。这些外部元素的展现不依赖于 CSS 规范。 典型的可替换元素有 <img>、 <object>、 <video>
以及 <textarea>、 <input>
这样的表单元素。 一些元素,比如 <audio>
和 <canvas>
,只在一些特殊情况下是可替换元素。 使用了 CSS content 属性插入的对象被称作匿名的可替换元素。
2.不可替换元素
:
反之,则为不可替换元素。
了解了概念后,我们回归主题。shrink-to-fit 的情况有多种,这里介绍一种最常见的情况,即不可替代元素浮动时的自适应宽度(Floating, non-replaced elements),听起来有点抽象,先看一个例子:
html&css
<!DOCTYPE html>
<html>
<style type="text/css">
.outer {
width: 800px;
background: black;
overflow: hidden;
}
.inner {
float: left;
background: red;
}
.sub1 {
width: 26%;
background: blue;
}
.sub2 {
width: 50%;
background: green;
}
</style>
<head> </head>
<body>
<div class="outer">
<div class="inner">
<div class="sub1">this is 1th line this is 2th line this is 3th line this is 4th line</div>
<div class="sub2">sub2 block</div>
</div>
</div>
</body>
</html>
这段样式定义了一个 outer 容器,背景为黑色且有宽度,它里面还有一个内部容器 inner,无宽度且左浮动,inner 里有两个小块 sub1 和 sub2。
那么问题来了,请问inner,sub1,sub2具体的宽度为多少?
先看效果图再回答:
结果应该会出乎你的意料:inner(红色背景)的宽度并不是 outer(黑色背景)的宽度(正常情况下应该可以继承父容器的宽度),因而 sub1 和 sub2 比我们预想的要小得多。
再回答这个问题之前,我们先试图修改一下,看能否从中找到出现这个问题的原因。经过调试,发现两种最简单的方案可以解决这个问题:
1.给inner加宽度width: 100%;
2.取消inner的浮动。
解决后的效果如下:
这的确是我们想要的,可这却巧妙地'躲'过了不可替换元素浮动这个场景。老实讲,我多次遇到过这个场景,但是无非也就是利用上述两个方案去尝试,可并不知晓真正的原因,于是还是啃了一下 W3C 有关这方面的规范,规范的描述如下:
首先不说英文的问题,单纯的'Roughly'和‘CSS 2.1 does not define the exact algorithm’这两句就让人哭笑不得,然后还给出了 shrink-to-fit 的一个公式:
min(max(preferred minimum width, available width), preferred width)
呵呵,然并卵啊,天知道这三个值怎么算。
再网上 google 一下,发现很多人都遇到这个问题,但也是读不懂规范,也有人把上面一段翻译了一下,大家可以看看:
CSS2.1 并未给出 preferred minimum width、available width 和 preferred width 确切算法,通常,将内容中非明确的换行外的其他部分强制不换行来计算 preferred width;反之,尝试将内容尽可能的换行,以得到 preferred minimum width;available width 即该元素的包含块的宽度减去 'margin-left','border-left-width','padding-left','padding-right','border-right-width','margin-right' 的值以及任何存在的纵向滚动条的宽度。
已被这段翻译绕晕的请举手。。。。。。。。。。。。。
再次回归主题,经过近一个小时的摸索,终于让我把这段难懂的英文捋顺了:
这里有三个参数,分别为:preferred minimum width, available width, preferred width. 只需关心 preferred width 的计算方式即可,preferred width 的计算方式如下:
让元素内容强制不换行后的最大宽度即为shrink-to-fit后的宽度
具体拿上面的例子,inner 中的 sub1 的内容由于宽度不够被换行了,将其强制不换行算出的宽度就是 inner 自适应的宽度(inner 本身没设宽度喔~),如何强制不换行也很简单,慢慢的将 sub1 的宽度调大,就会发现调至 100%时恰好足够用一行来现实其内容,这时内容的宽度就是 inner 自适应后的宽度。直接上图:
总结:对于浮动或者特殊的定位方式,推荐显式的设置容器宽度,避免出现意想不到的结果