IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Web中如何实现纵横比

    Airen发表于 2017-05-12 13:36:06
    love 0

    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%;
        }
    }
    

    上面看到的方案,其实已是老方案。在前面的教程中也有介绍过:

    • Flexible Images
    • Web中内嵌内容实现响应式效果

    纵横比例新方案

    有关于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,但碍于一些传统浏览器,使用在实际项目中还是需要考虑其兼容性。虽然这里介绍了几种方案实现纵横比例,但是你要有较好的方案,欢迎在下面的评论中与我们一起共享。

    大漠

    常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

    如需转载,烦请注明出处:http://www.w3cplus.com/css/experiments-in-fixed-aspect-ratios.html

    CSS3
    CSS3


沪ICP备19023445号-2号
友情链接