Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSS 是怎样确定图像大小的? #44

Open
anjia opened this issue Jan 1, 2019 · 1 comment
Open

CSS 是怎样确定图像大小的? #44

anjia opened this issue Jan 1, 2019 · 1 comment
Labels
CSS cascading style sheets 文章

Comments

@anjia
Copy link
Owner

anjia commented Jan 1, 2019

今天,和大家聊聊 CSS 是如何确定图像的显示大小的。

热热身

先来看个例子,热热身。

上面这张图像的原始尺寸是:宽 54px 高 49px。
那么,在以下代码中,每张图像显示的最终尺寸是多少?

https://p1.ssl.qhimg.com/t01068da1826ad05875.png 是该图片的 url

图像由<img src="">指定,代码如下:

<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png">
<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" width="30" height="30">
<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" width="30">
<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" height="30">
点击查看:显示的尺寸依次是...
  1. 宽 54px,高 49px
  2. 宽 30px,高 30px
  3. 宽 30px,高 30/(54/49)=27.22px
  4. 宽 30*(54/49)=33.06px,高 30px

图像由background-image指定,代码如下:

<style>
.img {
    display: inline-block;
    background-color: #eee;
    background-image: url('https://p1.ssl.qhimg.com/t01068da1826ad05875.png');
    background-repeat: no-repeat; 
    background-size: auto; /*auto 是默认值*/
}
</style>
<span class="img" style="width: 100px; height: 100px;"></span>
<span class="img" style="width: 30px; height: 30px;"></span>
<span class="img" style="width: 30px; height: 30px; background-size: 10px 10px;"></span>
<span class="img" style="width: 30px; height: 30px; background-size: contain;"></span>
<span class="img" style="width: 100px; height: 100px; background-size: cover;"></span>
点击查看:显示的尺寸依次是...
  1. 宽 54px,高 49px
  2. 宽 54px,高 49px
  3. 宽 10px,高 10px
  4. 宽 30px,高 27.22px
  5. 宽 100px,高 100px

以上 9 道题,你都答对了吗?

确定图像大小的过程

为了方便讨论,我们先来认识四个术语:

  1. 固有尺寸:是固有宽度、固有高度和固有宽高比的集合。对于特定对象,这三个尺寸可能都存在,也可能都不存在。比如光栅图像同时拥有这三个,SVG 图像只有固有宽高比,CSS 渐变就没有任何固有尺寸
  2. 指定大小:是通过width height background-size中的一个或多个指定的
  3. 默认对象大小:是一个具有确定宽高的矩形。在既没有固有尺寸,也没有指定大小时生效
  4. 具体对象大小:是对象最终显示的大小,即有明确宽度和高度值的矩形

通常情况,计算图像大小的默认过程是:

  1. 优先使用指定大小,得到要显示的宽和高
  2. 如果只指定了一个宽度,或只指定了一个高度,那么
    2.1 如果有固有宽高比,则用它和给出的那个,计算出来另一个
    2.2 否则,就取固有尺寸里的
    2.3 如果也没有固有尺寸,那就取默认对象大小的
  3. 如果没有指定大小
    3.1 先用固有尺寸里的
    3.2 如果没有固有尺寸,那就取默认对象大小的

初听起来有些绕,我们用刚才提到的例子具象下这个过程。

光栅图像是有三个固有尺寸的。以开头给出的 Logo 图像为例,它的固有尺寸分别是:

  • 固有宽度 54px
  • 固有高度 49px
  • 固有宽高比 54/49

<img>

我们先来看用<img src="">指定的那四个:

demo1.

<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png">

没有指定大小,那就用固有尺寸。所以,最终显示的尺寸是宽 54px,高 49px

demo2.

<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" width="30" height="30">

有指定的宽和高,所以,最终显示的尺寸是宽 30px,高 30px

demo3.

<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" width="30">

只有一个指定的宽,那就用固有宽高比计算出高来。所以,最终显示的尺寸是宽 30px,高 30/(54/49)=27.22px

demo4.

<img src="https://p1.ssl.qhimg.com/t01068da1826ad05875.png" height="30">

只有一个指定的高,那就用固有宽高比计算出宽来。所以,最终显示的尺寸是宽 30*(54/49)=33.06px,高 30px

以上四个示例的 UI 依次是:

background-image

接下来,看用background-image指定的五个。

在这个上下文里,背景区域的大小即图像的默认对象大小,background-size属性提供指定大小。

background-size有两个关键字containcover,它们分别对应包含约束和覆盖约束。

  • 包含约束(contain constraint )遵循固有宽高比,宽高都小于等于背景区域,然后尽可能的大。
  • 覆盖约束(cover constraint)遵循固有宽高比,宽高都大于等于背景区域,然后尽可能的小。

demo1.

<span class="img" style="width: 100px; height: 100px;"></span>

autobackground-size的默认值,意思是按图像的固有尺寸来,所以最终显示的尺寸是宽 54px,高 49px

demo2.

<span class="img" style="width: 30px; height: 30px;"></span>

同上,auto按图像的固有尺寸来,所以最终显示的尺寸是宽 54px,高 49px

demo3.

<span class="img" style="width: 30px; height: 30px; background-size: 10px 10px;"></span>

这里background-size: 10px 10px给出了具体的指定大小,所以最终显示显示的尺寸就是宽 10px,高 10px

demo4.

<span class="img" style="width: 30px; height: 30px; background-size: contain;"></span>

根据contain的含义,包含约束要在背景框里尽可能的大。背景框宽 30px 高 30px,图像固有宽 54px 固有高 49px,所以包含约束取宽 30px,高根据固有宽高比算出来 30/(54/49)=27.22px,也就是指定大小是宽 30px 高 27.22px。对于背景区域未覆盖到的地方将会用背景色来填充。所以最终显示的尺寸是宽 30px 高 27.22px。

demo5.

<span class="img" style="width: 100px; height: 100px; background-size: cover;"></span>

根据cover的含义,覆盖约束要在大于等于背景框的前提下尽可能的小。背景框宽 100px 高 100px,图像固有宽 54px 固有高 49px,所以覆盖约束取高 100px,宽根据固有宽高比算出来 100*(54/49)=110.20px,也就是指定大小是宽 110.20px 高 100px。 对于超出背景区域的部分,会被裁切掉,所以最终显示的尺寸是宽 100px 高 100px。

以上五个示例的 UI 依次是:

总结

  1. 理解四个尺寸
    • 固有尺寸:固有宽度、固有高度、固有宽高比
    • 指定大小:width height background-size
    • 默认对象大小:依据不同的上下文而定
    • 具体对象大小:它就是最终要显示的大小
  2. 计算图像大小的过程,即算图像最终要显示的大小,也就是算它最终的“具体对象大小”
    • 根据固有尺寸 + 指定大小 + 默认对象大小,计算具体对象大小
    • 使用的优先级:指定大小 > 固有尺寸 > 默认对象大小
    • 两种比较常见的指定大小约束:包含约束、覆盖约束
  3. 当计算出的“具体对象大小”和图像的“固有尺寸”不一致时,图像就要调整自身,以匹配“具体对象大小”
    • 调整图像大小的属性background-size
      • 当是<img>时,也有个相应的属性可以调整图像大小,即 object-fit
    • 图像超出背景区域的部分,会被裁剪掉;覆盖不全的部分,会用背景色来填充

参考

CSS Images Module Level 3

@anjia anjia added CSS cascading style sheets 文章 labels Jan 2, 2019
@anjia anjia changed the title 确定图像的大小 CSS 确定图像的大小 Jan 2, 2019
@anjia anjia changed the title CSS 确定图像的大小 CSS 是怎样确定图像大小的? Jan 2, 2019
@anjia anjia mentioned this issue Jan 2, 2019
@anjia
Copy link
Owner Author

anjia commented Jan 2, 2019

示例,在线预览:https://codepen.io/anjia/pen/jXYmmv

@anjia anjia mentioned this issue May 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CSS cascading style sheets 文章
Projects
None yet
Development

No branches or pull requests

1 participant