整合营销服务商

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

免费咨询热线:

纯CSS实现轮播图效果,你不知道的CSS3黑科技


轮播图已经是一个很常见的东西,尤其是在各大App的首页顶部栏,经常会轮番显示不同的图片。

一提到轮播图如何实现时,很多人的第一反应就是使用Javascript的定时器,当然这种方法是可以实现的。不过就是有些繁琐,今天这篇文章我们来看看如何不用Javascript,而使用纯CSS代码去实现轮播图吧。

这篇文章的所有代码我都放在了github上,感兴趣的同学可以去看看。

https://github.com/zhouxiongking/article-pages/blob/master/articles/carousel/carousel.html

CSS

实现效果

首先我们来看看只使用CSS实现的轮播图效果。

实现效果图

具体分析

看到上述的实现效果后,我们来具体分析下页面的构成。

  • 页面在布局上首先要有5张图片,图片固定宽度。

  • 每张图片对应一个标题,标题通过ul>li实现,事先算好宽度,跟随图片一起滚动。

  • 下边有个1,2,3,4,5表示图片顺序的索引,鼠标放上去后会显示对应的图片。

HTML页面

接下来我们通过代码层面去看看整个效果是如何实现的。

首先来看看HTML页面的实现,代码中都有每个区域的描述。

HTML页面

CSS部分

实现这个效果主要是通过CSS代码的,其代码量比较大,我们分开来看。

  • 外层容器

对于最外层容器我们设置绝对定位,方便图片标题子元素的定位。

外层容器

  • 图片标题

对于图片的标题我们也采用绝对定位,并且让标题横向一行展示,方便在动画的时候直接横向滚动。

得到的代码如下所示。

图片标题

  • 图片与图片容器

接下来是设置图片容器属性以及图片的基本大小。

图片容器也采用绝对定位,宽度可以动态设置,根据图片数量计算。每张图片设置宽度与高度,得到的代码如下。

图片与图片容器

  • 图片动画效果

然后设置图片的动画效果,对于任意的图片都有进入和静止两个状态,中间的效果可以任意定制。

在这里,中间效果设置成5%的间隔,其他时间在进行位置的切换,因为图片是处于水平分布,通过设置margin-left的值为负数进行偏移即可。

图片动画效果

  • 数字索引的基本属性

对于下面的数字图标也是通过基本的CSS属性进行设置的,包括宽高,行高,透明度等等。

在鼠标移动到对应的数字上后,数字会显示不同的颜色。而且在鼠标停留在数字上后,动画效果会暂停。

数字索引基本属性

  • 数字索引的偏移量

因为数字是水平方向展示的,因此要设定每个数字的水平偏移量。

数字水平偏移量

  • 鼠标停在数字上的动画效果

然后就是处理鼠标停留在数字上的动画效果,因为每张图片对应特定的数字,需要计算出每次的动画开始位置和结束位置。

鼠标停在数字上的动画效果

  • 动画效果赋予指定的数字

最后一步就是将定义的动画效果赋予指定的数字上,每个数字都有特定的id。得到的代码如下。

动画效果赋予指定的数字

至此所有步骤完成了,就可以得到文章开始的动画效果了。

结束语

这篇文章完全通过CSS实现了一个轮播图的效果,相比于使用JS来说减少页面阻塞程度,效果更好。

者:忽如寄

链接:https://www.jianshu.com/p/28643f36011e

一、随便说几句####

css3动画效果的强大不言而喻,自它出现一直热度不减,它与js动画的优劣也一直成为前端界争论的话题,不可置疑的是css3动画的出现在一定程度上降低了动画效果的实现难度,利于前端的学习,其精简的代码量把我们从烦人的js调试中解放出来,当然css的动画效果有其局限性,我们不能只用css3模拟出全部的就是动画,另外就是浏览器的兼容性问题。我们这次用css3实现一个轮播图效果,体验一下css3的强大。

首先说明我们可次只实现了自动轮播,效果也是最常见的淡入淡出,并未实现点击轮换效果,至少在我目前水平来看,自动轮播与点击轮换两者纯css3只能选其一,如果可以同时实现两种效果的方法,请告诉我。

二、布局###

<section class="slider-contaner">
 <ul class="slider">
 <li class="slider-item slider-item1"></li>
 <li class="slider-item slider-item2"></li>
 <li class="slider-item slider-item3"></li>
 <li class="slider-item slider-item4"></li>
 <li class="slider-item slider-item5"></li>
 </ul>
</section>

html代码没有什么可说的,样式的话首先必定slider的大盒子必定是相对定位,另外我们采用在li标签中添加background-image,因为这样才有可能用纯的css实现响应式,另外背景图为了在响应式中看清全貌,必然使用background-size:100%,另外就是高度问题了,显然slider-container必需是和li的高度一致,因为响应式中必然这个高度不能固定死,所以使用height属性显然不行,padding属性可以解决这个问题,一是background-image可以显示在padding中,二是padding中以%为单位是以父元素宽度为基准的。

*{
 margin:0;
 padding:0;
}
ul,li{
 list-style: none;
}
.floatfix {
 *zoom: 1;
}
.floatfix:after {
 content: "";
 display: table;
 clear: both;
}
.slider-contaner{
 width:100%;
 position:relative;
}
.slider,.slider-item{
 padding-bottom:40%;
}
.slider-item{
 width:100%;
 position:absolute;
 background-size:100%;
}
.slider-item1{
 background-image:url(imgs/1.jpg);
}
.slider-item2{
 background-image:url(imgs/2.jpg);
}
.slider-item3{
 background-image:url(imgs/3.jpg);
}
.slider-item4{
 background-image:url(imgs/4.jpg);
}
.slider-item5{
 background-image:url(imgs/5.jpg);
}

三、设计动画####

淡入淡出效果肯定是使用opacity,首先整体来看所有图片的淡入淡出都是同一个动画,只是时间不一样而已,这肯定是利用animation-delay来控制,动画无限轮换肯定使用animation-iteration-count: infinite,我们这次5张图片,整个动画分为图片停留和淡入淡出两个效果,用下图表示,箭头表示淡入淡出过程。

因为css3中没有一个属性是规定两次动画播放的时间间隔,所以我们必须把其他图片淡入淡出时该图片的效果写进动画里,显然这时候是opacity:0;

我们为了写动画的方便,动画使用线性函数,也就是animation-timing-function:linear;整个过程使用20s,一次停留使用3秒,一次淡入淡出使用1s,折合成百分比也就是15%和5%;

@keyframes fade{
0%{
 opacity:0;
 z-index:2;
}
5%{
 opacity:1;
 z-index: 1;
}
20%{
 opacity:1;
 z-index:1;
}
25%{
 opacity:0;
 z-index:0;
}
100%{
 opacity:0;
 z-index:0;
}
}

接下来就是为每张图片添加animation-delay了,因为第一张图片必须显示在最前,所以其他通过相邻兄弟选择器使用opacity:0,第一张图片开始不需要淡入淡出,直接跳至停留也就是5%,所以animation-delay为-1s,第二章图片和第一张相隔20%,也就是4s,animation-delay为3s,以此类推

.slider-item + .slider-item{
 opacity:0;
}
.slider-item1{
 animation-delay: -1s;
}
.slider-item2{
 animation-delay: 3s;
}
.slider-item3{
 animation-delay: 7s;
}
.slider-item4{
 animation-delay: 11s;
}
.slider-item5{
 animation-delay: 15s;
}

这个时候我们的轮播图可以动了

四、添加轮播焦点####

添加轮播焦点当然不是为了点击,而是告诉访问者这里有几张图片和目前图片的位置,至少以我个人而言,轮播焦点很重要,因为如果我不知道轮播的图片有几张,我又没有办法点击,我就会非常不安,感觉自己没有看到整个网页的全貌。所以我们还是添加一下轮播焦点。首先非常明确的这个仍然可以使用上面的动画,另外布局肯定使用position:absolute,另外很明显焦点我们必须写两次,一次是当前图片的样式,一次是非当前图片的样式

<div class="focus-container">
<ul class="floatfix"> 
<li><div class="focus-item focus-item1"></div></li>
<li><div class="focus-item focus-item2"></div></li>
<li><div class="focus-item focus-item3"></div></li>
<li><div class="focus-item focus-item4"></div></li>
<li><div class="focus-item focus-item5"></div></li>
</ul>
</div>
.focus-container{
 position:absolute;
 bottom:2%;
 z-index:7;
 margin:0 auto;
 left:0;
 right:0;
}
.focus-container ul{
 margin-left:46%;
}
.focus-container li{
 width:10px;
 height:10px;
 border-radius:50%;
 float:left;
 margin-right:10px;
 background:#fff;
}
.focus-item{
 width:100%;
 height:100%;
 background:#51B1D9;
 border-radius:inherit;
 animation-duration: 20s;
 animation-timing-function: linear;
 animation-name:fade;
 animation-iteration-count: infinite;
}
.focus-item1{
 animation-delay: -1s;
}
.focus-item2{
 animation-delay: 3s;
}
.focus-item3{
 animation-delay: 7s;
}
.focus-item4{
 animation-delay: 11s;
}
.focus-item5{
 animation-delay: 15s;
}

五、梳理代码####

如果你维护过别人的代码你就会知道,代码梳理对于后期维护的重要性了,没有经过梳理的css代码,随心所欲写到哪里就是哪里,对于后期维护来说简直就是一场灾难,css代码梳理个人认为首先必须添加必要的注释,将css代码分区,另外就是尽量减少后期修改需要修改的地方,这个主要是代码重构的问题,这个问题我已经在编写代码的时候考虑到了,所以主要任务就是添加注释和告诉维护者代码最常修改的地方,我们遵循最常修改的代码放到最后的原则。

我们来分析一下我们的代码如果给别人用可能需要修改的地方,首先肯定是图片路径,所以我们把这个样式放在最后,然后是图片高度,轮播焦点的颜色,动画时间的设置(这里还涉及图片个数),轮播焦点的位置,当然轮播焦点大小也可能修改。重构后代码如下:

<section class="slider-contaner">
<ul class="slider">
<li class="slider-item slider-item1"></li>
<li class="slider-item slider-item2"></li>
<li class="slider-item slider-item3"></li>
<li class="slider-item slider-item4"></li>
<li class="slider-item slider-item5"></li>
</ul>
<div class="focus-container">
<ul class="floatfix"> 
<li><div class="focus-item focus-item1"></div></li>
<li><div class="focus-item focus-item2"></div></li>
<li><div class="focus-item focus-item3"></div></li>
<li><div class="focus-item focus-item4"></div></li>
<li><div class="focus-item focus-item5"></div></li>
</ul>
</div>
</section>
/*css reset start*/
*{
margin:0;
padding:0;
}
ul,li{
list-style: none;
}
/*css reset end*/
/*css public start*/
.floatfix {
*zoom: 1;
}
.floatfix:after {
content: "";
display: table;
clear: both;
}
/*css public end*/
/*slider start*/
.slider-contaner{
width:100%;
position:relative;
}
.slider-item + .slider-item{
opacity:0;
}
.slider-item{
width:100%;
position:absolute;
animation-timing-function: linear;
animation-name:fade;
animation-iteration-count: infinite;
background-size:100%;
}
.focus-container{
position:absolute;
z-index:7;
margin:0 auto;
left:0;
right:0;
}
.focus-container li{
width:10px;
height:10px;
border-radius:50%;
float:left;
margin-right:10px;
background:#fff;
}
.focus-item{
width:100%;
height:100%;
border-radius:inherit;
animation-timing-function: linear;
animation-name:fade;
animation-iteration-count: infinite;
}
.focus-item2,.focus-item3,.focus-item4,.focus-item5{
opacity:0;
}
.focus-container ul{
margin-left:46%;
}
/*设置轮播焦点的位置*/
.focus-container{
bottom:2%;
}
/*设置当前图片焦点的颜色*/
.focus-item{
background:#51B1D9;
}
/*设置动画,请根据实际需要修改秒数*/
.slider-item,.focus-item{
animation-duration: 20s;
}
.slider-item1,.focus-item1{
animation-delay: -1s;
}
.slider-item2,.focus-item2{
animation-delay: 3s;
}
.slider-item3,.focus-item3{
animation-delay: 7s;
}
.slider-item4,.focus-item4{
animation-delay: 11s;
}
.slider-item5,.focus-item5{
animation-delay: 15s;
}
@keyframes fade{
0%{
opacity:0;
z-index:2;
}
5%{
opacity:1;
z-index: 1;
}
20%{
opacity:1;
z-index:1;
}
25%{
opacity:0;
z-index:0;
}
100%{
opacity:0;
z-index:0;
}
}
/*设置背景,响应式请利用媒体查询根据断点修改路径*/
.slider-item1{
background-image:url(imgs/1.jpg);
}
.slider-item2{
background-image:url(imgs/2.jpg);
}
.slider-item3{
background-image:url(imgs/3.jpg);
}
.slider-item4{
background-image:url(imgs/4.jpg);
}
.slider-item5{
background-image:url(imgs/5.jpg);
}
/*设置图片的高度,请根据具体需要修改百分比,响应式及时修改此值*/
.slider,.slider-item{
padding-bottom:40%;
}

六、最后扯两句####

这种css3实现的轮播图,缺点也是不言而喻,点击轮换和自动轮换两者只能选其一,不过自动轮换可以用在手机端,这是一个不错的选择,另外,现在的网站大都是通栏设计,网页文字很少,尤其是网站首页更是如此,有时候比的不是网站设计的优劣,反而是谁选的图片好看,谁就有可能受到青睐,这种情况我们其实可以考虑将轮播图变为背景的轮换,这时候轮播焦点也就可以不使用了,相信你的博客首页或者产品首页使用背景轮换,效果会非常不错的

体代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{margin: 0;
			padding: 0;}
#box {
	width: 100%;
	height: 502px;
	overflow: hidden;/*溢出的部分:隐藏*/
}

#box .menu {
	width: 607%;
	position: relative;
	margin-left: -40px;/*左外边距*/
	bottom: 0px;/*低边距离*/

}

#box .menu ul li {
	float: left;/*浮动:左,就是要把图片往左浮动*/
	list-style: none;
}




		</style>
	</head>
	<body>
		<div id="box"><!--最外的大盒子-->
			<div class="menu"><!--这里是写入我们要播放的图片-->
				<ul><!--无序列表-->
					<li><img src="image/01.jpg" width="1546px;" height="500px"></li>
					<li><img src="image/02.jpg" width="1546px;" height="500px"></li>
                    <li><img src="image/03.jpg" width="1546px;" height="500px"></li>
                    <li><img src="image/04.jpg" width="1546px;" height="500px"></li>
                    <li><img src="image/05.jpg" width="1546px;" height="500px"></li>
                    <li><img src="image/06.jpg" width="1546px;" height="500px"></li>
				</ul>
			</div>
			
		</div>
		<!--在这里导入javascript文件也就是js代码,如果没有这个就没有动画-->
		<script src="jquery-3.4.1.min.js" type="text/javascript"></script>
		<!--写代码-->
        <script>
//      	function就是函数执行
        	$(function(){
        		//一般获取元素用var,从第一张图片开始
        		var _index=0,  
//        		 窗口宽度,就是把所有图片放在水平线上的总宽度
        		window_width=1546, 
        		//时间循环
        		timer=null,  
        		//图片内容一共六张
        		images_count=6;
        		//获取下一个
        		function nextPlay(){
        			if(_index>images_count-1){//_index指的是每一张图片
        				_index=0;//从第一张开始
        				              //stop() 停留,animate自定义动画往左运动,
        				$("#box .menu").stop().animate({left:-window_width*_index},500);
        			}else{
        				$("#box .menu").stop().animate({left:-window_width*_index},500);
        			} 
        			//每一个图片加一就是自动按顺序出来
        			_index++;
        		}
        		timer=setInterval(nextPlay,2000);
        	})
        </script>
	</body>
</html>

javascript文件也就是js文件:链接:https://pan.baidu.com/s/1_RUihF6SdA4-NJcqHGqm1g

提取码:mnfg