最近接到一个需求,是开发一个业务组件——适配一行多列的商品布局,就是那种经典的上面是商品图片,下面是商品详情的布局格式,如下图:
这是一行两列,还要适配一行三列,一行多列(可左右滚动),如下图:
由图中可以看出,不同列的时候,商品容器的宽高是不一样的,既然是组件,不可能针对每一个布局设置一种样式,更坑的是,就算是同一种商品,尺寸比例也是不一样的,简单来说,这里的商品图片,有可能是正方形,有可能是长方形,产品的需求是:图片容器比例固定,里面的图片,按中心点显示,多余的部分截掉。而容器的比例,是按照长方形的图片设置的,意味着正方形的宽度和容器一致,高度上下各截掉一部分。
padding Hack写法 这里我们分析一下:商品容器宽度不固定,所以图片容器宽度也是不固定的,但是有一点是确定的,就是图片的宽度是商品容器的100%,所以只要图片容器和图片的宽度设置为100%,剩下的就是高度的问题,而要高度跟随宽度比例的变化,第一个想到的是calc计算,但是宽度不固定,calc也计算不了高度。仔细想一想,宽度根据高度比例变化的,好像还真有一个——padding,w3c规范的说明:当使用百分比值指定填充时,百分比始终从包含块的宽度导出。也就是padding的值用百分比设置的时候,始终是以设置padding元素的父元素的宽度为基数的。在这个需求里,图片的容器和商品容器的宽度是一样的,所以设置图片容器的padding-top为百分比,在设置图片宽高都是100%,那图片宽度就会一直跟商品容器宽度一致,而高度是设置的比例,代码如下:
.product-image-wrap { margin-bottom: 20px; position: relative; display: flex; width: 100%; height: 0; padding-top: 70%; font-size: 0; .product-image-1 { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; margin: 0 auto; border-radius: 16px 16px 0 0; } } product-image-wrap是图片容器的类名,将其height设置为0,用padding-top设置高度70%,就是宽度是高度的1.4倍(可根据比例设置百分比的值)。再把图片设置成object-fit:cover,并且使用相对定位处理,就能实现不同尺寸的图片,同等比例的展示,并且图片不变形。
padding设置百分比,平时用的比较少,也没有注意到,在这里记录一下。至于padding设置百分比为什么是以父元素的宽度为基数,看了网上大佬的言论,可能是因为,横向容器是有边界的,比如文字不设置强制不换行的话,到达边界之后会自动换行,但是纵向却没有边界,可以一直往下延伸。听起来也很有道理。
新方案:aspect-ratio纵横比 这是一个css的新特性,支持的浏览器版本有Chromium 88、 Firefox 87和 Safari Technology Preview 118
aspect-ratio一些重要的使用场景如下:
创建响应式窗口,其宽度为父窗口宽度的100% ,高度应该保持为特定的视窗比例;
创建图片或者video内部占位符容器;
为交互式数据可视化或 SVG 动画创建统一的响应空间
为多幅不同尺寸的图像创建统一的响应空间(与object-fit配合使用),如本文的需求例子。
与padding的hack写法的对比如下:
1:1 aspect ratio = 1 / 1 = 1 = 1:1纵横比 = 1/1 = 1 =padding-top: 100% 4:3 aspect ratio = 3 / 4 = 0.75 = 4:3纵横比 = 3/4 = 0.75 =padding-top: 75% 3:2 aspect ratio = 2 / 3 = 0.66666 = 3:2纵横比 = 2/3 = 0.66666 =padding-top: 66.67% 16:9 aspect ratio = 9 / 16 = 0.5625 = 16:9纵横比 = 9/16 = 0.5625 =padding-top: 56.25%