整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端学习教程:移动web必会技能-图片居中处理

们在日常使用移动APP的时候,特别是一些资讯类的APP,都会有图片展示的相关UI,例如APP的单大图和三图模式,如下图:单图:

三图:

或者是类似微博或者朋友圈这种9宫格的图片展示效果,如下图:

对于这些图片,如果你单纯的以为直接用几个<img>,配置一下src地址,然后渲染在页面上,那就大错特错了

对于这种类型的UI展示,我们需要明确下面几点:

  1. 图片在上传后,会有不同的大小,有的是长图(长大于宽),有的是宽图(宽大于长),或者是一些接近正方形的图片。
  2. 在保证图片原本长宽比的情况下,要想将图片显示在一个正方形的区域内,或者是固定长宽的区域内,是必须要截取一部分图片展示的。
  3. 采用CSS或者JavaScript都可以实现这种效果。

大家可以看下面这几张图,红色的是图片本身,虚线框就是展示出来的区域,便于理解:宽图:

长图:

CSS的background-size:

单独使用CSS的话,我们可以轻松的实现上面这个效果,主要利用到的属性就是background-size这个属性,可以先从概念上了解一下这个属性:

background-size: length|percentage|cover|contain
  • length:设置背景图像的高度和宽度。第一个值设置宽度,第二个值设置高度。如果只设置一个值,则第二个值会被设置为 “auto”。
  • percentage:以父元素的百分比来设置背景图像的宽度和高度。第一个值设置宽度,第二个值设置高度。如果只设置一个值,则第二个值会被设置为 “auto”。
  • cover:在保持图像的纵横比的前提下,以适合铺满整个容器并将图像缩放成将完全覆盖背景定位区域的最小大小。优点是背景图片全部覆盖所属元素区域;缺点是超出的部分会被隐藏。
  • contain:与cover相反,在保持图像的纵横比的情况下,以适合铺满整个容器,并将图像缩放成将适合背景定位区域的最大大小。优点是图片不会出现变形,同时背景图片被完全展示出来;缺点是当所属元素的宽高比与背景图片的宽高比不同时,会出现背景留白。

我们可以采用background-size:cover;比较合适,在保证纵横比的情况下,如果图片超过背景区域,将多余部分隐藏即可,同时设置background-position: center center;将主要内容居中显示。

CSS的object-fit:

HTML5新增的<img />标签的属性object-fit也可满足需求,但是要注意兼容性。

object-fit: fill|contain|cover|scale-down|none|initial|inherit;

主要用到以下属性:

  • fill:默认,不保证保持原有的比例,内容拉伸整个内容容器。
  • contain:保持原有尺寸比例,内容被缩放,参考background-size:contain。
  • cover:保持原有尺寸比例,但部分内容可能被剪切,参考background-size:cover。
  • scale-down:保持原有尺寸比例。内容的尺寸与 none 或 contain 中的一个相同,取决于它们两个之间谁得到的对象尺寸会更小一些,更加智能。

代码效果demo:

如果是一个单大图,我们可以直接给一个div设置background-image,然后设置background-image即可,代码如下:

<div class="one-img"></div>
    .one-img {
      width: 100%;
      padding-top: 50%;
      background-image: url('https://gpic.qpic.cn/gbar_pic/osL7w6JTehzgKuaKrPEJ8V3lia1zoLaPShY05MdBofOpBye0yNpRXYA/');
      background-size: cover;
      background-position: center center;
    }

效果如下图:

代码中图片来源于网络

这里有一个知识点,我们如果想要实现屏幕的适配,div的长宽是绝不可以写成固定值px的,所以宽度可以设置成100%,这样如果在大屏幕下,图片自身会变大,但是高度我们是无法设置一个合适的百分比的,这里我们借助了padding-top属性,将padding-top设置成百分比,可以让一个div的高度被撑开,具体的值依据宽度的值,即50%表示是宽度(width:100%)的50%。

三张连续图,代码如下:

    <div class="three-img-other-wrap">
     <div class="three-img-other-1 img-1"></div>
     <div class="three-img-other-2 img-2"></div>
     <div class="three-img-other-3 img-3"></div>
   </div>
.three-img-wrap {
     margin-top: 5px;
     width: 100%;
     overflow: hidden;
   }
.three-img {
     float: left;
     width: 33.3333%;
     padding-top: 33.3333%;
     border-right: 1px solid #fff;
     background-size: cover;
     background-position: center center;
     box-sizing: border-box;
   }

效果如下:

每个div,设置float:left来实现横向平铺,注意一下这里不建议使用display:inline-block,会出现都得空隙,如果想要实现9宫格,将这3个复制2份即可。

或者是另外一种3+2+1显示方式图,代码如下:

.three-img-other-wrap {
      margin-top: 5px;
      width: 100%;
      overflow: hidden;
}

.three-img-other-1 {
      width: 66.6666%;
      padding-top: 66.6666%;
      float: left;
      border-right: 1px solid #fff;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;
    }
.three-img-other-2 {
      width: 33.3333%;
      padding-top: 33.3333%;
      float: left;
      border-bottom: 1px solid #fff;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;

}
.three-img-other-3 {
      width: 33.3333%;
      padding-top: 33.3333%;
      float: left;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;
}
<div class="three-img-other-wrap">
   <div class="three-img-other-1 img-1"></div>
   <div class="three-img-other-2 img-2"></div>
   <div class="three-img-other-3 img-3"></div>
</div>

效果如下:

图片之间的缝问题:

从上面的效果图来看,每张图片之间都有一定的间距(一般是1px-3px之间),在这里我们如果使用margin来实现的话,我们是无法设置一个具体的数值的,因为我们的长宽都是采用百分比,margin也必须采用百分比,否则会出现错乱,但是在此场景下margin不适合采用百分比,所以我们采用border边框来模拟这个间距:

border-right: 1px solid #fff;
box-sizing: border-box;

需要注意box-sizing: border-box;,这样border将的长度将会计算在整个宽度里面,即border+width等于具体的设置的百分比。

采用JavaScript来实现:

其实从代码的优雅程度上来说,采用我们上面讲解的纯Css的方法是比较好的一种方法,但是也有弊端:1. 无法监听图片的加载成功和失败事件,例如onerror或者onload。这会导致我们无法给加载失败的图片一个默认的显示图。2. 我们在实现图片懒加载的逻辑时,div+background-image这种方式相交于<img>方式需要写更多的逻辑。

在这里给大家介绍一下div+background-image和<img>之间的区别:

在网页加载的过程中,以css背景图存在的图片background-image会等到结构加载完成(网页的内容全部显示以后)才开始加载,而html中的标签img是网页结构(内容)的一部分会在加载结构的过程中加载,换句话讲,网页会先加载标签<img>的内容,再加载背景图片background-image,如果你用引入了一个很大的图片,那么在这个图片下载完成之前,<img>后的内容都不会显示。而如果用css来引入同样的图片,网页结构和内容加载完成之后,才开始加载背景图片,不会影响你浏览网页内容。

如果我们想要用JavaScript加<img>,来实现这种效果,基本逻辑是:

  1. 首先需要知道图片的宽高。
  2. 给每个<img>设置src之后,需要同时设置一个父div用来包裹这个<img>。
  3. 同时父div需要设置overflow:hidden,然后根据外框的大小,和图片的宽高,动态设置<img>的margin或者left,top来产生位移。

这里的核心是如何根据外框的宽高来动态计算出图片的位移,我们可以封装一个方法来计算,具体的逻辑可以看注释:

getImagePosition(img, cW, cH) {
    // cW为外框宽度,// cW为外框高度,
    img.marginTop = img.marginLeft = 0;

    // img.h表示图片本身高度,img.height表示计算设置之后的高度
    // img.w表示图片本身高度,img.width表示计算设置之后的高度

    img.width = cW;
    img.height = cH;

    // 长图 优先设置宽度,然后长图居中
    if (img.h * cW / img.w > cH) {
        img.height = img.h * cW / img.w;
        img.marginTop = (cH - img.height) * 0.5 // 0.5表示居中
    } else {// 宽图 优先设置高度度,然后宽图居中
        img.width = img.w * cH / img.h;
        img.marginLeft = (cW - img.width) * 0.5 // 0.5表示居中
    }

    return img;
}

在计算出图片位移后,外框的宽高也可以使用JavaScript来动态设置,例如屏幕宽度的三分之一或者是图片宽度的三分之二,代码如下:

document.body.clientWidth * 0.5
document.body.clientWidth * 2 / 3

在众多的移动web技能中,图片居中处理是一个非常重要的技能,也是用的比较多的一种技能,当然还有一些极端情况例如遇到面条图,或者是长宽小于10px的这种非常小的图片,可能需要单独特殊逻辑处理了。

白郁闷的找到老朱说道:“朱哥,我想让一个块容器在一个容器里面垂直居中怎么这么难啊!”

老朱:“你是怎么实现的?”

小白说:“比如一个容器的高度是400px,子容器的高度是300px,我就把子容器CSS上边距设置成50px。”

“那要是父容器高度发生变化你的子容器岂不是很麻烦”

小白郁闷的说道:“你可说吧!头疼的很!怎么才能轻松的设置垂直居中啊?”

老朱说:“如果一个容器只有一行文字和图片,我们可以设置容器的高度和line-height一致就可以保证文字和图片居中,但是多行图片,或者容器里面嵌套了其他块元素就很麻烦了。还有一种情况就像你刚刚两个div嵌套,子容器也是个块元素,垂直居中直接用CSS会很麻烦,正好今天想跟你说说怎么给jQuery添加扩展方法,索性咱就以这个为例子进行讨论吧!”

小白高兴的说道:“又有新知识学了,什么事给jQuery添加扩展方法呢?”

“我们使用$(选择器)生成的对象有很多默认jQuery方法,你应该知道吧?”

小白说道:“知道啊!获取和修改容器html内容的html()方法、获取和修改属性的attr()方法、修改元素css样式的css()方法、获取元素高度的height()方法、还有控制容器显示的show()方法……”

“停~!差不多了,这些都是jQuery自带的方法,假如我们想自己增加一个方法可以用$.fn添加。我现在给你写一个能够输出当前容器高度和父容器高度的方法你看看!”

“子容器和父容器的高度在CSS中都有过设定,因此我通过$.fn添加mid方法以后,再通过选择器找到sun容器就可以直接使用mid方法了。”

小白突然灵光一现,说道:“朱哥我知道怎么设置一个让块容器基于父容器垂直居中了,你稍等我一会,我再你的代码基础上改一下!”

也就两分钟的时间,小白就把代码拿到了老朱面前,“你看,我写好了!”

“现在我想让sun容器基于main垂直居中只需要使用一下$("#sun").mid()就可以实现了,以后父容器不管怎么变化,它都是基于父容器居中的。”

老朱说道:“如果有多行块容器,或者多行文本、图片怎么办?”

小白说道:“那就给他们外面再嵌套一个块容器就可以了么!对不对啊?”

“不错,通过给他们嵌套一个块容器,然后再让这个块容器基于父容器垂直居中就可以了!小白我相信你还能再写一个基于底部对齐的方法吧?”

小白自信的说道:“再这个方法上改一下就可以了,稍等~”

“嗯,不错,如果你发现以后经常会用到这两种居中方式,可以把他们放到一个js文件里面,以后用的时候把这个js文件引入,就可以直接使用mid和bottom方法了。”

“$.fn确实是个好东西!看来我以后得经常添加自己的方法了,哈哈,我去练习了~”


想学H5的朋友可以关注老炉,您的关注是我持续更新《小白HTML5成长之路》的动力!

平居中方案:

水平居中设置

1、行内元素

设置 text-align:center

2、定宽块状元素

设置 左右 margin 值为 auto

3、不定宽块状元素

a:在元素外加入 table 标签(完整的,包括 table、tbody、tr、td),该元素写在 td 内,然后设置 margin 的值为 auto

b:给该元素设置 displa:inine 方法

c:父元素设置 position:relative 和 left:50%,子元素设置 position:relative 和 left:50%

垂直居中设置

1、父元素高度确定的单行文本

设置 height = line-height

2、父元素高度确定的多行文本

a:插入 table (插入方法和水平居中一样),然后设置 vertical-align:middle

b:先设置 display:table-cell 再设置 vertical-align:middle

在前端面试中,大都会问你div居中的方法:

文笔不好,就随便寥寥几句话概括了,希望大家能够轻拍

不过以后文笔肯定会变得更好一些的。

开始这些东西之前也可以测试一下你对html了解多少,让我们测试一下吧,小测验:你对HTML5了解有多少?

今天我们就细数一下几种方法:

1,使用position:absolute,设置left、top、margin-left、margin-top的属性

.one{

position:absolute;

width:200px;

height:200px;

top:50%;

left:50%;

margin-top:-100px;

margin-left:-100px;

background:red;

}

这种方法基本浏览器都能够兼容,不足之处就是需要固定宽高。

2,使用position:fixed,同样设置left、top、margin-left、margin-top的属性

.two{

position:fixed;

width:180px;

height:180px;

margin-top:-90px;

margin-left:-90px;

background:orange;

}

大家都知道的position:fixed,IE是不支持这个属性的

3,利用position:fixed属性,margin:auto这个必须不要忘记了。

.three{

position:fixed;

width:160px;

height:160px;

top:0;

right:0;

bottom:0;

left:0;

margin:auto;

background:pink;

}

4,利用position:absolute属性,设置top/bottom/right/left

.four{

position:absolute;

width:140px;

height:140px;

background:black;

}

5,利用display:table-cell属性使内容垂直居中

.five{

display:table-cell;

vertical-align:middle;

text-align:center;

width:120px;

height:120px;

background:purple;

}

6,最简单的一种使行内元素居中的方法,使用line-height属性

.six{

width:100px;

height:100px;

line-height:100px;

text-align:center;

background:gray;

}

这种方法也很实用,比如使文字垂直居中对齐

7,使用css3的display:-webkit-box属性,再设置-webkit-box-pack:center/-webkit-box-align:center

.seven{

width:90px;

height:90px;

display:-webkit-box;

-webkit-box-pack:center;

-webkit-box-align:center;

background:yellow;

color:black;

}

8,使用css3的新属性transform:translate(x,y)属性

.eight{

position:absolute;

width:80px;

height:80px;

transform:translate(-50%,-50%);

-webkit-transform:translate(-50%,-50%);

-moz-transform:translate(-50%,-50%);

-ms-transform:translate(-50%,-50%);

background:green;

}

这个方法可以不需要设定固定的宽高,在移动端用的会比较多,在移动端css3兼容的比较好

9、最高大上的一种,使用:before元素

.nine{

position:fixed;

display:block;

background:rgba(0,0,0,.5);

}

.nine:before{

content:'';

display:inline-block;

vertical-align:middle;

height:100%;

}

.nine .content{

width:60px;

height:60px;

line-height:60px;

color:red;

总而言之所有的居中的方法就是你必须要掌握css属性的这个概念HTML DIV+CSS,你掌握了就可以好好的运用这些居中的东西了

限时!!免费送Dreamweaver、js等前端教程

↓↓↓