网站首页 > 技术文章 正文
对于在CSS中实现容器的长宽比最初的创意是来自于在Web中如何实现纵横比。主要是用于响应式设计中的iframe、img和video之类的元素。随之扩展为适用于任何容器的长宽比。那在CSS中到底有多少种方案可以实现呢?我一向喜欢做这样的事情,到处搜集多种解决方案。
如果你看到前面的两篇文章,或许你知道一些方法,或者说所有的方案你都想到了。如果是这样的话,你可以停止阅读这篇。如果没有的话,你可以继续往下阅读。
长宽比故事
长宽比在影视制作中又被称之为宽高比,指的是一个视频的宽度除以它的高度所得到的比例,通常表示为x:y或x×y,其中的冒号和叉号表示中文的“比”之意。目前,在电影工业中最常被使用的是anamorphic比例(即2.39:1)。传统的4:3仍然被使用于现今的许多电视画面上,而它成功的后继规格16:9则被用于高清晰度电视或数字电视上。常见的比例:
HTML结构
使用CSS实现容器长宽比,常见的HTML模板结构有两种:
<div class="aspectration" data-ratio="16:9">
<div class="content"></div>
</div>
另外一种结构是:
<div class="aspectration" data-ratio="16:9"> </div>
具体使用的时候,根据自己的使用场景采用不同的结构。
CSS实现长宽比例方案
前面也提到过了,使用CSS实现长宽比方案有多种,下面简单的罗列一下这些方案。不过每种方案都不会详细介绍,因为代码非常简单,看一眼代码就能明白其中原理。
垂直方向的padding
这是最早提出的一种实现方案,主要借助的原理是利用padding-top或者padding-bottom的百分比值,实现容器长宽比。在CSS中padding-top或padding-bottom的百分比值是根据容器的width来计算的。如此一来就很好地实现了容器的长宽比。采用这种方法,需要把容器的height设置为0。而容器内容的所有元素都需要采用position:absolute,不然子元素内容都将被padding挤出容器(造成内容溢出)。
比如我们容器的长宽比是16:9,那么根据比例计算:100% * 9 / 16可以得到56.25%。如果你希望的是4:3,那么对应的就是100% * 3 / 4。
具体的CSS代码如下:
.aspectration {
position: relative; /*因为容器所有子元素需要绝对定位*/
height: 0; /*容器高度是由padding来控制,盒模型原理告诉你一切*/
width: 100%;
}
.aspectration[data-ratio="16:9"] {
padding-top: 56.25%;
}
.aspectration[data-ratio="4:3"]{
padding-top: 75%;
}
通过通配符*选择器,让其子元素的宽高和容器.aspectration一样大小:
.aspectration > * {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
padding & calc()
这个方案采用的是padding和calc()配合在一起使用。其实原理和第一个方案是一样的。只不过在第一个方案中,我们每次都需要对padding的值进行计算,如果使用calc()可以通过浏览器直接计算出padding的百分比值。
.aspectration[data-ratio="16:9"] {
padding-top: calc(100% * 9 / 16);
}
padding & CSS变量
对于变量而言,以前是其他计算器语言和CSS处理器的特性,不过值得特性的是,现在也是CSS的特性。接下来的这个方案也是基于padding原理,只不过是借助于CSS变量特性,让前面的方案变得更为灵活一些。使用CSS的变量时,可以把HTML中data-ratio去掉了。换成style="--aspect-ratio:16/9",也可以是style="--aspect-ratio:1.4;"。同时也可以借助于第二个方案中的calc()。因为CSS的变量和calc()函数的结合是一种完美的结合。
.aspectration[style*="--aspect-ratio"] {
padding-top: calc(100% / (var(--aspect-ratio)));
}
padding & 伪元素
前面的方案都是在.aspectration元素上使用padding值。但在CSS中,还可以使用CSS的伪元素::before或::after来撑开容器。
.aspectration {
position: relative;
}
.aspectration:after {
content: "";
display: block;
width: 1px;
margin-left: -1px;
background-color: orange;
}
.aspectration[data-ratio="16:9"]:after {
padding-top: 56.25%;
}
.content {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
视窗单位
CSS新特性中提供了一种新的单位vw。了解过这个单位的同学都知道,浏览器100vw表示的就是浏览器的视窗宽度(Viewport)。打个比方说,如果你的浏览器是1334px,那么对就的100vw = 1334px。这个时候也就是说1vw = 13.34px。这里的100vw也对应前面方案中的100%。这样我们就可以把前面的%单位换成vw的单位。打个比方说,16:9对应的就是100vw * 9 / 16 = 56.25vw。这个值可以用在padding-top或者padding-bottom中。但这里演示的不再是padding了,而是把这个值给height。
.aspectration[data-ratio="16:9"] {
width: 100vw;
height: 56.25vw;
}
上面的示例中width的值是30vw,那么对应的height值就是30vw * 9 / 16 = 16.875vw。
视窗单位 & CSS Grid
这是一个很有创意的解决方案,使用的都是CSS新特性:视窗单位和CSS Grid Layout。简单说一下其中的实现原理:将容器.aspectration通过display:grid声明为一个网格容器,并且利用repeat()将容器划分为横向比例,比如16,那么每一格的宽度对应的就是100vw * 9 / 16 = 6.25vw。同样使用grid-auto-rows,将其设置的值和横向的值一样。在子元素上通过grid-column和grid-row按比例合并单元格。
.aspectration {
display: grid;
grid-template-columns: repeat(16, 6.25vw);
grid-auto-rows: 6.25vw;
}
.aspectration[data-ratio="16:9"] .content {
grid-column: span 16;
grid-row: span 9;
}
未来原生方案 aspect-ratio
在WICG的讨论上,有人提出来了原生的长宽比属性aspect-ratio。例如,给定一个容器元素它的width和height都设置为auto,并且aspect-ratio的值为2/1,max-height:200px。一个容器宽度为500px时,元素首先会设置width:500px,然后根据aspect-ratio比例将height设置为250px。这个时候其实违反了max-height的约束。相反,容器大小会变成height: 200px和width:400px。另外,如果元素的max-width是450px时,长宽比将会完全被忽视,因为无法满足。
如果把width设置为一个百分比,高度不设置一个固定值:
.aspectration[data-ratio="16:9"] {
width: 100%;
height: aspect-ratio(16/9);
}
现在讨论讨论趋势是把aspect-ratio属性值变成属性,比如:
.aspectration[data-ratio="16:9"] {
width: 100%;
aspect-ratio: calc(16/9);
}
到目前为止,还没有任何浏览器支持该属性,但我们可以借助PostCSS Aspect Ratio插件来实现上述的功能:
/* Input. */
.aspect-box {
position: relative;
aspect-ratio: '16:9';
}
/* Output. */
.aspect-box {
position: relative;
box-sizing: border-box;
}
.aspect-box > * /* This targets .aspect-box__content */ {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
box-sizing: border-box;
}
.aspect-box:before /* This pseudo element uses the padding trick to set the height. */ {
position: relative;
display: block;
content: "";
padding-top: 56.25%;
box-sizing: border-box;
}
- 上一篇: 8、你知道什么是CSS 的盒模型吗?(必会)
- 下一篇: Web前端开发-CSS布局-盒子模型入门干货
猜你喜欢
- 2024-11-24 六种设计难题的CSS实用技巧
- 2024-11-24 前端入门教程:CSS标准盒模型和怪异盒模型区别
- 2024-11-24 WEB前端-CSS盒子
- 2024-11-24 手把手教你css 中多种边框的实现小窍门【实践】
- 2024-11-24 纯CSS实现轮播图
- 2024-11-24 「干货」移动端Web页面适配
- 2024-11-24 《Web前端技术H5+CSS3》笔记--第六章 盒子模型「云图智联」
- 2024-11-24 深入浅出超好用的 CSS 阴影技巧
- 2024-11-24 掌握Flex布局的这几个常用属性,搞定弹性布局不在话下
- 2024-11-24 用 CSS Grid 布局制作一个响应式柱状图
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-