结一

7个月前
  • 4817

    浏览
  • 0

    评论
  • 0

    收藏

H5活动宣传页通用布局技术解决方案

本文作者:imweb 结一 原文出处:imweb社区 未经同意,禁止转载

一般来说,活动宣传页都是全屏的滑动,而移动端的视窗大小确实是有点零碎化,于是将内容在不同的手机上良好展示出现就显得有点挑战了。本文旨在通过对一个个疑难点进行攻克而形成一种通用解决方案。

活动宣传页面分析

以imweb conf的第一屏为例,如下图:

imweb conf

现在对里面的元素布局进行一个分析:

  • 一个全屏的背景图
  • ”往届回顾“定位在左上(left, top),IMWeb.io 文字及向上箭头定位为中下(center bottom)
  • 发光的地球水平铺满,垂直方向定位为bottom
  • 中间的其他内容定位参考就是中间了
  • 内容一屏显示,不论手机的宽高如何变化

除此之外,元素进入还有一个动画效果(考虑使用现有得动画库animate.css),这就构成了我们所有的技术攻克点,这里先把最简单的第二条头部及底部的定位给剔除掉(相信这个都不是问题),下面对其余几条进行逐条分析。

全屏背景图解决方案

第一个念想肯定是background-size。而能沾上边的无非100%, contain, cover这三种取值。

根据caniuse的兼容报告,有以下两点需要注意:

  • 安卓4.3- 不支持将background-size缩写进background,所以必须单独申明这个样式
  • 安卓4.3-不支持background-size使用百分比单位,所以最后只剩下contain, cover这两个取值

至于contain, cover这两个的区别可具体参考相关文档。简单来说contain是缩放以使宽高全部容下,所以除非是图片比例与视窗比例正好合适,否则肯定出现空白;而cover是缩放到只要有宽高一个满足要求了,另一个就会将多余的进行裁剪,它跟contain正好相反,结果只会正好合适或超过裁剪,这里就不细说,最后的结论就是使用cover

毕竟是要将图片按比例进行缩放,为了表现效果更好点,手机的视窗宽高比还是要知道下,不然给你个正方形的图片做背景图,那效果就差得远了。

目前手机视窗的宽高比一般为9:16 ( 0.5625),小尺寸手机为320*480(比例为0.666)

  • iphone 4 320 ÷ 480 = 0.666
  • iPhone 5 320 ÷ 568 = 0.563
  • iPhone 6 375 ÷ 667 = 0.562
  • iPhone 6 Plus 414 ÷ 736 = 0.5625
  • 安卓:360 ÷ 640 = 0.5625

所以背景图的设计宽高比最好是9:16,当然可能还是有些瑕疵,因为可能会有地址栏或工具栏,所以如果使用top定位,则底部不要放一些重要的视觉,因为可能会被裁剪掉,而如果是center定位,则顶部和底部都不要放重要的视觉,还是因为可能会被裁剪掉。

发光地球水平铺满

这里将采用图片宽高比的方法来解决这个问题,可以参考我之前的文章:

核心思想还是利用padding的百分比单位计算是基于元素的宽度,所以高度由padding-top来撑开,而实际的height设置为0,封装的scss代码为:

// object wrap
// $child 参数请使用单引号,因为用于子元素选择器
@mixin object-wrap($percent: 100%, $child: 'img') {
    position: relative;
    padding-top: $percent;
    height: 0;

    #{unquote($child)} {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
    }
}

中间其他内容

对于内容的处理方式,可以先采用一个元素把所有中间元素包裹起来,然后对包裹元素定位在垂直中间,那样就可以避免单个元素的一个个定位布局了,也直接减少了对transform的使用,以方便元素进行动画。

这里先根据实际内容分两种情况,第一种是固定宽度的内容,内容宽度小于320px的;还有一种是内容大于320px甚至是大于360px的,所以就需要考虑窄屏时候的缩放。

固定宽度的内容

先把所有元素放在一个容器中,对这个容器进行垂直居中定位,水平全屏。里面实际元素的定位,则根据这个容器进行。

.center-wrap{
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    transform: translate(0, -50%);
}

对于我们案例中全是水平居中的logo,大会名称及大会时间三个元素,我们既可以在wrap使用flex布局实现水平居中,也可以设置各个元素的width,然后margin左右为auto居中。

而元素的动画,因为我们元素的样式没有使用到transform,所以可以放心使用animate.css动画库

可变宽度的内容

如果元素宽度为可变的,则有如下办法可使用:

  • 通过media queries来对某个范围设置一个固定宽度,于是又回到了上面的固定宽度
  • 通过计算得到其宽度与视窗宽度的百分比,设置该元素的宽度为百分比单位,如果内容是img引入的图片,则高度自动变化,如果是bg图片,则高度则采用上面的容器宽高比的方式来设置,且设置background-size: cover

最后建议可以把主要内容设计都控制在320px之内,那样处理起来就比较方面了。

至于最后一个一屏显示,其实把上面的都处理好了,这个一般也就没问题了,实在碰到一些特殊的,我们还可以使用media queries来解决

其他特殊情况

当然上面的通用解决方案并不能适用所有情况,对于某些特殊的情况我们还是需要另外单独考虑。下面继续再抛出两个特例:

元素使用了transform定位,怎么进行动画

我们的animate.css动画库采用的就是transform的一些动画,如果我们元素本身的布局定位就采用了transform,那肯定是会有冲突的。

所以首先建议我们的布局定位坚决杜绝使用transform,找各种办法就是别用transform。

其次万一你真的用了transform来布局定位,那你只好自己手动在你需要动画的keyframes里面的每一帧都加上你的transform布局定位且为第一个值(transform可以设置多个值)。

视窗高度的百分比

如果你的某个元素的定位或大小是基于视窗的高度来计算的,这就有点麻烦了,尤其是嵌套了好几层的情况。

css3提供了一个v系列的单位,其中vh就表示视窗的高度,但是安卓4.3-不支持。这里我们从rem入手,来个黑科技解决这个问题:

通过js设置html的font-size为视窗高度的十分之一,于是1rem就成了视窗高度的10%

document.addEventListener("DOMContentLoaded", function(event) {
    document.documentElement.style.fontSize = window.innerHeight/10 + "px";
  });

总结

活动宣传页的布局说到底就是要解决如下几个问题:

  • 全屏
  • 元素的定位布局
  • 定位与动画
  • 不定宽高的处理
  • 特殊情况处理

解决好了这些,搞定这类页面都不再是问题。

0 条评论