Web发展到现在,已经有很大的变化,特别在当前这样的时代,我们面对的设备种类繁多。言外之意,这样的环境之下,Web的页面布局时常会碰到一些缩放比例的控制,特别是针对img
、iframe
、object
、video
和embed
等元素的比例缩放。当然,就img
元素而言,要实现纵横比例的布局已有多种方案,而且实战性也特别的强,并且在Responsive设计中已使用广泛。
既然img
可以实现,那其他元素iframe
、video
等元素也可以借鉴其中的一些实现原理。今天我们就来说说一些这方面的实现方案。
纵横比
在具体介绍如何实现纵横比之前,先来了解一下纵横比相关的概念。纵横比分为固定纵横比和自适应纵横比。
基于width
的百分比来设置padding
百分比值,把这种方式称之为固定纵横比。一般我们通过width
的百分比来计算padding-top
或padding-bottom
的百分比值,其计算公式如下:
padding-top = (元素高度 / 元素宽度) * 100%
padding-bottom = (元素高度 / 元素宽度) * 100%
比如下图:
上图展示的是一个9 / 16
的固定纵横比例,计算出来就是56.25%
。根据这个原理,我们可以在CSS处理器做相关处理:
@mixin fixed-aspect-rations($height, $width) {
padding-bottom: $height / $width * 100%;
// 或者
padding-top: $height / $width * 100%;
}
当然还可以写一个@function
。
@function aspect-ratio($height, $width) {
$aspect-ratio: $height / $width * 100%;
@return $aspect-ratio;
}
在固定纵横比例的基础之上,做进一步的调整。假设我们在宽屏的PC上显示大的图片,而在移动设备上,我们不想使用相同的纵横比例让图像等元素变得太小。当然我们也不想使用完全相同的高度让图像变得太高。希望看到的效果是当宽度变小时,其高度也变得更小。我们就把这种方案称为流体纵横比例。
这种方案可以给元素设置一个高度,来减少padding-top
或者padding-bottom
的百分比值。假设我们的大图尺寸是700px
的宽度和267px
的高度,而我们决定显示的图片尺寸是在300px
的宽度和167px
的高度。现在我们需要计算height
和padding-bottom
(或者padding-top
)的值:
同样可以写一个混合宏:
@mixin fluid-ratio($large-size,$small-size) {
$width-large: nth($large-size,1); //背景图片大尺寸的宽度
$width-small: nth($small-size,1); //背景图片小尺寸的宽度
$height-large: nth($large-size,2); //背景图片大尺寸的高度
$height-small: nth($small-size,2); //背景图片小尺寸的高度
//计算slope => slope = (h2 - h1) / (w2 - w1)
//h1:背景图片大尺寸的高度 => $height-large
//w1:背景图片大尺寸的宽度 => $width-large
//h2:背景图片小尺寸的高度 => $height-small
//w2:背景图片小尺寸的宽度 => $width-small
$slope: ($height-large - $height-small) / ($width-large - $width-small);
//计算元素的初始高度start Height => Start height = h1 - w1 * slope
$start-height: $height-small - $width-small * $slope;
padding-top: $slope * 100%; //你也可以将padding-top换成padding-bottom
height: $start-height;
}
来看一个简单的示例,就拿固定纵横比例来说吧。
<div class="container">
<iframe class="embed"></iframe>
</div>
根据上面的介绍,容器.container
的height
设置为0
,而padding-bottom
或者padding-top
设置为height / width * 100%
。而这里的height
和width
指的是元素iframe
的。假设希望iframe
的固定纵横比例是9 : 16
:
.container {
position: relative;
width: 100%;
height: 0;
padding-top: 56.25% // 9 / 16 * 100%
}
.embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
最终效果如下:
拖动浏览器大小,视频可以按对应的比例进行缩放:
上面的方案,可以进行改良,使用::after
或者::before
来控制容器比例:
.container {
position: relative;
width: 75%;
&:before {
content: "";
display: block;
width: 100%;
padding-top: 56.25%;
}
}
上面看到的方案,其实已是老方案。在前面的教程中也有介绍过:
纵横比例新方案
有关于Web的布局,今年讲得最多的应该是CSS的Grid布局,这也是未来Web布局特性之一,它将改变以前的Web布局方式。那接下来的方案就是采用CSS Grid的方式来处理固定纵横比例。
如果你没有接触过CSS Grid布局相关的知识,建议你先阅读一些相关文章,这样有助于你后面的内容理解。
接下来的方案,除了使用到了CSS Grid还使用了CSS的Viewport单位以及CSS的自定义属性。别的先不多说,开始回到我们今天的主题。
我们采取的方法是创建一个网格容器的列数和宽高比的。在下面的示例中,使用16:9
的宽高比,所以创建网格容器的列数为16
列。
我们给每个列的宽度采用vw
单位,并且其宽度是纵横比例。这样做的好处是可以调整窗口的宽度来控制容器的大小,同时还能根据纵横比例来进行调整。同时要控制网格行的大小,其大小根据列的计算来设置,控制每个单元格的比例是1:1
。这里采用grid-auto-rows
来控制网格行。
.container {
display: grid;
grid-template-columns: repeat(16, 5.625vw);
grid-auto-rows: 5.625vw;
}
和以前的方案类似,上面采用grid
和vw
实现了容器的纵横比例,接下来要控制元素。上面的代码通过grid-template-columns
和grid-auto-rows
已设定了网格。接下来通过span
和grid-column
和grid-row
进行网格合并,这里有一个重点:grid-column
合并的横向比例,示例中是span 16
;grid-row
合并的是纵向比例,示例中是span 9
。同时把嵌入的元素,比如img
、iframe
、video
这些元素的width
和height
都设置为100%
,用来足以填补整个网格区域。
.embed {
grid-column: span 16;
grid-row: span 9;
width: 100%;
height: 100%;
}
原理清楚了,把上面的示例使用Grid方案来改造一下:
同样拖动浏览器大小查看效果:
总结
文章简单介绍了如何在Web中实现纵横比例。除了以前的老方案之外,我们可以采用最新的CSS Grid布局,使用最新的布局方案,以前天生具备浏览器视窗缩放比例的视窗单位vw
来控制网格网格的列数和行高。这个方案虽然灵便,但对于不同的纵横比例,需要创建不同的网格以及指定网格列的宽度。还有一点,就目前为止,虽然有些浏览器可以支持CSS Grid,但碍于一些传统浏览器,使用在实际项目中还是需要考虑其兼容性。虽然这里介绍了几种方案实现纵横比例,但是你要有较好的方案,欢迎在下面的评论中与我们一起共享。
如需转载,烦请注明出处:http://www.w3cplus.com/css/experiments-in-fixed-aspect-ratios.html