轮播-简洁优雅版

A simple, elegant, scalable and responsive carousel design using pure jQuery. Elements of different size in the slideshow can agree to the same aspect ratio thanks to responsive height of the carousel container.

问题描述

我们需要这样的轮播:

  • 响应式设计:自适应宽度和高度,并保持恒定长宽比;
  • 动画切换效果:自动在不同元素间来回切换,并具有基本的动画效果,如淡入淡出等;
  • 元素布局自由:允许元素在容器内具有个性化布局,如完全填充,绝对居中等。

动画效果,采用jQuery是最好不过的选择。有人说,jQuery挺大,影响网页加载速度,然而,一方面有CDN加速助力,另一方面jQuery的应用已经渗透到各个角落,大概率已经缓存过了,因此,为了实现代码的简洁通用,何乐而不为呢?

元素布局自由看起来并不困难,一旦容器实现了响应式设计,只需规定各元素的CSS样式即可。但有一个布局,即绝对居中centered both horizontally and vertically in a given container),值得探讨学习,参见下文

难点在于恒定长宽比。锁定长宽比很好理解,因为这样比较美观,不会让各元素,尤其是图片,放缩变形。恒定长宽比的关键在于 宽度、高度都能自适应,并且它们有一个共同的长度参照。宽度自适应的方法深入人心,最简单的莫过于width: x %; margin: auto;。如何实现高度自适应呢,用height: y %,抑或加一个硬性高度限制如height: 100px吗?前者达到的效果:不同size的元素可以正常显示,但容器高度随元素高度不停上下闪烁;后者达到的效果:若高度足够,会留下一大段空白,若高度不足,元素依然我行我素逃出容器。这些都不是 高度自适应 的正确途径!

高度自适应

最简单的方法: 用margin/padding占位 。思路简单,一图以明之:

1
2
3
4
5
6
7
8
9
10
11
12
width
|<------->|
----------- ———
^
|
Main container | margin-top
|
v
----------- —— #beginning of helper container whose content is empty
helper container #it has a margin distance from the top edge of main container
(child)
-----------

前面说到,宽度和高度需要有一个共同的长度参照,才能计算长宽比。我们正是利用margin-top的百分比参照为父元素宽度来实现固定长宽比。依上图,自定义容器的长宽比为width : margin-top

Note that in a horizontal flow, percentages on margin-top and margin-bottom are relative to the width of the containing block, not the height (and in vertical flow, margin-left and margin-right are relative to the height, not the width).
—-by W3C

因此,若将设计的容器命名为myBox,则不难写出它的样式表:

1
2
3
4
5
6
7
8
9
10
11
12
.myBox {
width: 100%; /*容器宽度百分比*/
margin: auto;
position: relative;
overflow: hidden;
}
.myBox:after {
content: '';
display: block;
margin-top: 60%; /*容器高度百分比*/
}
/* 上面容器的长宽比为 100% : (100% * 60%) = 5 : 3 */

淡入淡出

jQuery提供了很多经典特效,也可以通过animate函数自定义个性化动画。下面的代码中,我们首先将若干元素(这里是四张图片)完全填充 在上面的myBox容器中,然后间隔固定时间循环引用每张图片,让当前图片淡出,让下一张图片淡入。

因此,每张图片的样式表为:

1
2
3
4
5
6
7
8
9
/*图片布局格式*/
.imgInBox {
position: absolute;
top: 0; width: 100%; height: 100%;
}
/*非封面图片默认不可见*/
.notCoverImg{
visibility: hidden;
}

特效动作执行的JavaScript代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
$(document).ready(function(){
var myIndex = 0;
var x = $(".imgInBox").get(myIndex); //初始化:选取封面图片
setInterval(function (){ //动画循环,每张图片生存时间为4s
$(x).animate({opacity: 0}, 'slow', function(){ //缓慢淡出当前图片,之后调用callback()函数
$(x).css("visibility", "hidden"); //令淡出图片不可见
myIndex++;
if (myIndex == 4) {myIndex = 0;}
x = $(".imgInBox").get(myIndex); //准备淡入下一张图片
$(x).css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, 'normal');
});
}, 4000);
});

实际效果,请见本博客留言簿上的照片墙,欢迎留言哦~~

绝对居中

留言簿上的四张照片之所以选择 完全填充,是因为它们的原始长宽比相近(都是集体合照),小幅放缩以适应容器大小不存在美观的问题,而且这样容器中没有留白,一举两得。但如果想保持各元素原始大小比例,并将其置于容器内绝对居中的位置上呢?

问题看起来很简单,然而只用样式表实现 垂直居中 仍然需要不少技巧。一个流行有效的做法是top:50%/left:50%translateX(-50%)/translateY(-50%)结合的用法,通过改变数值可以实现任意形式的居中布局。该方法易于理解掌握,且支持绝大多数浏览器

因此,只需更改前面的图片布局格式imgInBox

1
2
3
4
5
6
7
8
.imgInBox {
position: absolute;
top: 50%;
left: 50%;
-moz-transform: translateX(-50%) translateY(-50%);
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}

这样,我们实现了 自适应设备、长宽比恒定的容器中淡入淡出循环播放图片,各图片绝对居中 的最终效果!如果需要添加按钮等交互元素,均可以在此基础上自由扩展,非常简单!

参考文献

How to center an element horizontally and vertically
巧用margin/padding的百分比值实现高度自适应
CSS basic box model - The margin properties
jQuery 参考手册

鲍煜坤 wechat
扫一扫,更多精彩等你哦(^_−)☆
帮我买杯奶茶,鼓励我继续创作吧ヾ(◍°∇°◍)ノ゙