假设:有一个产品展示模块,图片尺寸为 200 * 200 ,所以你把宽度与高度设置为固定值 200px

<style>
        div { width: 200px; height: 200px; border: 10px solid #000; margin: 10px; float: left; }
        img { width: 100%; height: 100%; }
</style>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
</body>

有一天,客户上传了一张 3000 * 1000 的产品图:

网页效果图

“我靠,怎么搞的,把我产品图都挤成正方形了?!”客户生气的看着眼前的网页。

于是他找到了产品经理并大骂了他一顿。产品经理也找到了你,把你大骂了一顿。你愁眉苦脸的开始寻找解决办法:

既然上面是固定了宽度和高度才导致图片被严重挤压的,那我就不设置宽度和高度,让图片自适应呗!

你欢呼雀跃地敲起了代码:

<style>
    div { width: auto; height: auto; border: 10px solid #000; float: left; margin: 10px; }
    img { width: 100%; height: 100%; }
</style>
    <div><img src="images/3000_1000.jpg" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
</body>
“不设置宽高的话,这一整个 div 都占了一整行啊”

“一行我可不止要放一个产品图,这可怎么办啊!”眼看着布局结构都被打乱,你开始焦虑起来。

“算了,继续固定吧,记得有个属性 object-fit:cover; 可以保持纵横比缩放图片。”

<style>
    div { width: 200px; height: 200px; border: 10px solid #000; float: left; margin: 10px; }
    img { width: 100%; height: 100%; object-fit:cover; }
</style>
    <div><img src="images/3000_1000.jpg" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
</body>
反正就一张图片没看到完整内容,就这样吧!
几天后,产品经理又噼里啪啦数落了你一通,就像客户数落他那样:

“怎么回事,到了手机上看怎么成这鸟样了!给了你们这么长时间,连响应式都没有!再这样下去就没必要合作了!!”

“响应式……”,你低头沉思了一会,决定

将每个 div 宽度设置为25%,这样3个 div 都能容纳在一行里,div宽度还能随着视口宽度的变化而变化。

你美美的想着竟然笑出了声,连忙控制了一下面部表情。

<style>
    div { width: 25%; height: 200px; border: 10px solid #000; float: left; margin: 10px; }
    img { width: 100%; height: 100%; object-fit:cover; }
</style>
    <div><img src="images/3000_1000.jpg" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
</body>

这下不用客户挑毛病,你也能看出来哪里不对劲了。虽然图片都没变形,但没有一张图片显示完整,你坐不住了。

“高度……高度!高度自适应一定能解决”,你双目怒睁望道。

<style>
    div { width: 25%; height: auto; border: 10px solid #000; float: left; margin: 10px; }
    img { width: 100%; height: 100%; object-fit:cover; }
</style>
    <div><img src="images/3000_1000.jpg" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
    <div><img src="images/350a8f0c766f5460.png" alt=""></div>
</body>

“一行内比例差这么多。完了,这下彻底完了。”你心灰意冷地背起行李,决定提桶跑路。

忽然,脑子里突然有一个声音,似乎在远程指导你:

首先,我们得固定图片的比例,保证用户上传图片的宽高多奇葩 布局都不会变。

  • 图片大小为 1013px * 776px 。先固定一个宽度为25%,宽度相对于父元素(body、html),这样无论视口宽度怎么变化,宽度永远是视口的25%。
  • 接着,我们来计算高度的百分比。只要计算出宽度与px的换算比例,就能计算出高度。

  • 宽度等于25%,那么就用 1013px / 25 = 40.52px
  • 40.52像素等于1个百分比,那么776个像素呢?再用图片高度 776px / 40.52px = 19.15103652517275%(19.15%)取小数点两位足矣。
  • 好了,我们得到 宽度 = 25%,高度 = 19.15%

    你跟着迷迷糊糊地按下回车键:

    ~ 哦豁,忘记告诉你了。屏幕宽度会有变化,是因为不同设备之间的差距,但是高度却几乎不会有变化。

    在电脑上:

  • 宽度25% = 1013px像素,高度19.15% = 776像素(等比例)
  • 在手机上:

  • 宽度25% = 93.75px ( 375 / 100 = 3.75 * 25 = 93.75 )
  • 高度19.15% = 127.73px ( 667 / 100 = 6.67 * 19.15 = 127.7305 )
  • 别说等比例了,反比例都给整出来了。

    通过高度百分比来达到图片等比例缩放效果,是不可能的!

    那么有没有一种东西,能获取 元素宽度的变化 呢?我知道你想说JS,用这个 Api 获取那个 DOM ……但别急,还要更好的方法—— padding

    平时我们都习惯了 padding 属性的单位 px 做各种各样的间距。可很少有人注意到:

    padding的百分比单位是相对于父元素的宽度。

    已知:father宽度300px

    <style>
        .container { width: 300px; height: auto; background: #bfa; }
    </style>
        <div class="father">
            <div class="son"></div>
        </div>
    </body>
    

    求:不固定高度如何能得到 1:1 的正方形?

    <style>
        .father { width: 300px; height: auto; background: #bfa; }
        .son { padding-bottom: 100%; }
    </style>
        <div class="father">
            <div class="son"></div>
        </div>
    </body>
    

    答:只需要添加一句css属性 padding-bottom:100% 即可。

    看明白了吗?反正 padding 单位 % 是相对于父元素的的宽度。当父元素的宽度也设置为 % 时,它有300px,子元素就有300px,它有800px,子元素就有800px。

    明白了原理后,我们也可以推断出,padding-top同样有如此效果。

    回归正题,把 height设置为 auto ,再在 img 的外边添加一个类名为 pb 的容器:

        <style>
            .box { width: 25%; height: auto; border: 10px solid #000; float: left; margin: 10px; }
            .pb { padding-bottom: 100%; }
            img { width: 100%; height: 100%;}
        </style>
            <div class="box">
                <div class="pb">
                    <img src="images/3000_1000.jpg" alt="">
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <img src="images/350a8f0c766f5460.png" alt="">
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <img src="images/350a8f0c766f5460.png" alt="">
                </div>
            </div>
        </body>
    

    为什么看不见图片?因为此时的高度是padding撑起来的 pb 实际上也没有高度。

    千万不要给 pb 高度,因为pb的作用就是用来获取父元素宽度变化的。(如果你头铁硬要给,你会发现陷入了奇怪的场景)

    pb设置 height:100% 后

    怎么解释,这是什么情况?让我们先分析第一个box

    从img开始看:

  • 宽度100%,相对于父元素 pb 宽度默认100%,再相对于它的父元素 box 的 25% = 600px
  • 高度100%,相对于父元素 pb 高度 100%,在相对于它的父元素 box 的 auto ,算起来高度还是自己给的 = 200px
  • 宽度100%,相对于父元素 box 的宽度25% = 600px
  • 高度100%,相对于父元素 box 的 高度 auto = 0
  • padding-bottom:100%,相对于父元素 box 的宽度 25% = 600px
  • 宽度25%,相对于当前视口宽度 = 600px
  • 高度auto,被 pb 的子元素撑起来 = 0
  • 边框 10px(会应用到计算)
  • 容器宽度 = box宽度、边框 = 620px

    容器高度 = img的高度 + pb的padding + box的border = 820px

    经过上面复杂的计算,相信你已经头晕眼花的勉强搞懂了刚刚为什么会出现这种情况。也明白了给 pb height:100% 是不可取的!让我们去掉它,又恢复到了白色内容正方形边框的场景。

    既然 img 的宽高相对于 pb 没有用,为何我们不直接让它脱离文本流,去相对于 box ?没错,就是定位!

    给 img 的套一层容器 ab,让它带着我们的 img 飞起来

        <style>
            .box { width: 25%; height: auto;border: 10px solid #000; float: left; margin:10px; }
            .pb { padding-bottom: 100%; }
            .ab { width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 2 }
            img { width: 100%; height: 100%;}
        </style>
            <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/3000_1000.jpg" alt="">
                    </div>
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/350a8f0c766f5460.png" alt="">
                    </div>
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/350a8f0c766f5460.png" alt="">
                    </div>
                </div>
            </div>
        </body>
    

    完美自适应宽高变化!可是我们这张图片的比例好像不是1:1的正方形哎,如何计算出高度的比例的呢?

    图片高度 / 图片宽度 = 高度比例(取百分比)

    以第一张图片的比例为准,3000px * 1000px

    1000/3000=0.3333333333333333(取百分比)=33.331000 / 3000 = 0.3333333333333333(取百分比) = 33.33%

    由此得知高度百分比是 33.33%,但是我们不能直接给高度,前文也提到高度几乎没什么变化。(当然应该给 padding-bottom 呀)

    顺便给img标签加一个 object-fit: cover; 防止变形

        <style>
            .box { width: 25%; height: auto; border: 10px solid #000; float: left; margin:10px; }
            .pb { padding-bottom: 33.33%; }
            .ab { width: 100%; height: 100%; position: absolute; left: 0; top: 0; z-index: 2; }
            img { width: 100%; height: 100%; object-fit: cover; }
        </style>
            <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/3000_1000.jpg" alt="">
                    </div>
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/350a8f0c766f5460.png" alt="">
                    </div>
                </div>
            </div>
             <div class="box">
                <div class="pb">
                    <div class="ab">
                        <img src="images/350a8f0c766f5460.png" alt="">
                    </div>
                </div>
            </div>
        </body>
           
    粉丝