深入剖析object-fit与object-position属性的用法
图片居中大家再熟悉不过了,老生常谈的问题,之前虽然有总结过 N 种方法解决居中问题,最近在学习中发现 css3 有两个更好的属性方法,即 object-fit 和 object-position 两个 CSS 属性,他们可以让我们操作 img 或 video 中的内容,类似于我们可以用 background-position 和 background-size 操作背景内容一样。
object-fit 理解
object-fit 只能用于『可替换元素』(replaced element)。所谓可替换元素,是指元素的内容和表现不是由 CSS 控制的,独立渲染的外部元素,比如:img、object、video 和表单元素,如 textarea、input,audio 和 canvas 在一些特殊情况下,也可以作为可替换元素。
在使用 object-fit 时,一定要设定元素的 size,也就是 width 和 height
直入正题,object-fit 有五个可选值,分别是:
object-fit: fill; object-fit: contain; object-fit: cover; object-fit: none; object-fit: scale-down;
每个属性值的具体含义如下:
fill 默认值。填充,可替换元素填满整个内容区域,可能会改变长宽比。
contain 包含,保持长宽比,保证可替换元素完整显示,长宽比和内容区域的长宽比不一致时,内容区域会出现空白。
cover 覆盖,保持长宽比,保证内容区域被填满,所以可替换元素可能会被切掉一部分,从而不能完整展示。
none 顾名思义,就是什么都没有啦,当然不是什么都没有啦,而且千万不要以为和 fill 是一样的!实际效果是,保持可替换元素原尺寸和比例。
scale-down 等比缩小。效果类似 contain 或 none
每个属性值对应的效果图:
大家可以对照示意感受下,什么是内容拉伸(fill),什么是内容全部都显示(contain),什么是容器没有留白(cover),什么是该多大就多大(none)。
scale-down 由于具有动态特性,所以要专门展示下。实际的替换内容表现是 none 和 contain 最终尺寸小的那个属性值的表现。
例如,假设我们的容器可以 resize 拉伸,改变其尺寸,则当容器尺寸比 256*191 小的时候,也就是容器比替换内容(这里的图片)实际尺寸小的时候,效果跟 contain 一致,因为此时 contain 的实际展示尺寸比 none 小。如下截图示意:
但是,当容器尺寸拉伸到比图片实际尺寸还大的时候,则效果跟 none 一致,因为此时 none 的实际展示尺寸比 contain 小。如下截图:
至此,我们大致了解了 object-fit 各个属性值的表现,你以为事情就结束了吗?不是,这只是个开始。
难道大家没有对图片的表现表示疑惑吗?
我明明图片设置了宽高都是 100%,为何貌似实际效果除了(fill),似乎都无视了这些声明呢?图片的实际尺寸变小或变大了,而不是根据容器实际尺寸走呢?
.box>img{width:100%;height:100%;}
你有没有这样的疑惑?有木有!!
如果有,恭喜你,来对地方了,这表明你还没有对一些概念认识清楚。
img 是个元素,且是个替换元素,这个通过上面的学习应该都知道;
一个图片,如果没有 src,它依然是个替换元素,它在浏览器中的解析依然是正确的;
<img>
src 指向的图片属于替换内容,注意,这个替换内容和这个 img 替换元素是壳子与内容的关系,两者是独立的。在 CSS2.1 时代,壳子的实际尺寸(如果没有 CSS 或 HTML 设置),则是跟随内容的实际尺寸,因此,网页加载的时候,我们会看到图片占据的高度从 0 到图片实际高度跳动的过程;如果壳子,也就是 img 有尺寸限制,则替换内容 fill 拉伸适应于 img 替换元素的设定尺寸。总而言之,壳子与内容的尺寸永远是一样的。于是,我们就会误认为图片就是那个图片,唯一的存在,导致我们理解 object-fit 的特性表现出现了障碍。
在 CSS3 时代,object-fit 的世界里,object-fit 控制的永远是替换内容的尺寸表现,注意,是替换内容的尺寸表现,不是 img 替换元素。或者这么讲吧,我们对 img 设置:
.box>img{width:100%;height:100%;}
实际上是控制 img 这个元素的,这个壳子的尺寸是 100%撑满容器。上面截图的 5 个示例的图片实际上都是 100%拉伸与容器的;之所以实际的图片内容没有拉伸,是因为受 object-fit 控制,object-fit 控制了 src 对应的替换内容的尺寸,或者包含,或者覆盖。
之所以 object-fit:contain 会透明留白,是因为我们没有对壳子 img 设置背景色,假设我们给壳子 img 增加个红色背景,大家就会明白我说的意思了:
.box>img{width:100%;height:100%;background-color:#cd0000;}
效果如下截图,会发现,原来的透明留白现在是红色背景,说明了什么?说明 img 替换元素和 src 替换内容是两个独立体。img 替换元素受到了 CSS 100%拉伸控制(所以红色背景充满容器),src 替换内容也受到了 object-fit 展示控制。大家各司其职,没有什么覆盖冲突!
目前,IE 浏览器并不支持 object-fit:
如何让 object-fit 兼容 IE 浏览器呢?
有个 Github 上有个 polyfill,https://github.com/anselmh/object-fit 大家有兴趣可以围观下。
object-position 理解
object-position 要比 object-fit 单纯的多,就是控制替换内容位置的。默认值是 50%50%,也就是居中效果,所以,无论上一节 object-fit 值为那般,图片都是水平垂直居中的。因此,下次要实现尺寸大小不固定图片的垂直居中效果,可以试试 object-fit.
与 background-position 类似,object-position 的值类型为<position>类型值。也就是说,CSS3 的相对坐标设定样式支持的。
例如替换内容一直定位在容器的右下角:
object-position: 100% 100%;
例如替换元素相对于右下角 20px 10px 地方定位:
object-position: right 20px bottom 10px;
上面的表现在 FireFox 36 浏览器下符合预期,Chrome 没看明白:
因此,建议还是使用 calc 实现相对右下角定位:
object-position: calc(100% - 20px) calc(100% - 10px);
此时,Chrome 浏览器的表现符合预期了:
同样的,object-position 也支持负值,特征表现与 background-position 一致。
实例展示
通过上面所学的知识,我们利用 object-position 来实现一个任意数字翻转效果:
素材图片:
CSS 代码:
.num { width: 40px; height: 40px; object-fit: none; object-position: 0 0; -webkit-transition: object-position .25s; transition: object-position .25s;}.num0 { }.num1 { object-position: 0 -40px; }.num2 { object-position: 0 -80px; }.num3 { object-position: 0 -120px; }.num4 { object-position: 0 -160px; }.num5 { object-position: 0 -200px; }.num6 { object-position: 0 -240px; }.num7 { object-position: 0 -280px; }.num8 { object-position: 0 -320px; }.num9 { object-position: 0 -360px; }
HTML 代码:
<p><strong>显示的数字是(100~999):<input type="number" value="283" min="100" max="999"></strong></p><img src="icons-ol.png" class="num num2"><img src="icons-ol.png" class="num num8"><img src="icons-ol.png" class="num num3">
Javascript 代码:
if (window.addEventListener) { var eleNums = document.querySelectorAll(".num"); document.querySelector(".demo input").addEventListener("change", function() { var value = this.value.trim() * 1; if (!value || value < 100 || value > 999) { value = 283; } this.value = value; this.value.split("").forEach(function(num, index) { eleNums[index].className = "num num" + num; }); });}
img sprites 和 background sprites 就功能和能耗上而言,基本上是一致的。不过一个 img 图片,一个是 img 背景图片。前者兼容性有待提高。所以,目前来看,优势不明显。
以上就是码云笔记为大家带来的关于 object-fit 与 object-position 属性的用法,希望对前端开发的小伙伴有用,更多精彩敬请关注码云笔记。
码云笔记 » 深入剖析object-fit与object-position属性的用法
这两个属性不错,博主总结的也很详细,学习了 :oops:
谢谢和支持