基础HTML
先写最基本的HTML代码,后面为了实现
无缝切换
,还会在前后再加两幅图
。另外,简单起见,这里就不用真正的图片了,而是用背景色代替
,原理都是相同的,只是把背景色换成图片即可。
<div class="slide">
<ul class="list">
<li class="item">
1
</li>
<li class="item">
2
</li>
<li class="item">
3
</li>
</ul>
</div>
基本样式
清除一下默认样式,在
root
中定义两个变量宽
和高
,即为轮播图区域的宽高
,将轮播图区域水平垂直居中
。
:root {
--width: 20rem;
--height: 10rem;
}
* {
margin: 0;
padding: 0;
list-style: none;
}
body {
display: flex;
justify-content: center;
height: 100vh;
align-items: center;
}
div.slide {
width: var(--width);
height: var(--height);
border: .2rem dashed purple;
}
给所有图片
加背景色
、加边框
,调整文字大小
、颜色
、文字水平垂直居中
。
li.item {
width: var(--width);
height: inherit;
box-sizing: border-box;
border: .2rem solid pink;
background-color: maroon;
color: #fff;
font-size: 4rem;
text-align: center;
line-height: var(--height);
}
到目前为止的效果:
将图片排成一排
所有图片左浮动,调整
ul.list
宽度可以放下三张图片
li.item {
width: var(--width);
height: inherit;
box-sizing: border-box;
border: .2rem solid pink;
background-color: wheat;
color: #fff;
font-size: 4rem;
text-align: center;
line-height: var(--height);
/* 新增 */
float: left;
}
ul.list {
width: calc(var(--width) * 3);
height: inherit;
/* 加边框看下ul.list的宽度 */
border: .5rem dashed blue;
}
实现轮播效果
接下来要做的就是通过动画让
ul.list
水平左移,而外部的div.slide
的宽度是固定不变的,再将超出div.slide
部分隐藏即可
将
div.slide
置于最上
ul.list {
width: calc(var(--width) * 3);
height: inherit;
/* 新增 */
/* 以下两行代码是为了让div.slide的边框置于最上,以看到真实的移动效果 */
position: relative;
z-index: -1;
}
给
ul.list
加左移动画,每个关键帧移动整数倍图片宽度。
ul.list {
width: calc(var(--width) * 3);
height: inherit;
position: relative;
z-index: -1;
/* 新增 */
/* 为了看到完整效果,延时1s */
animation: move 5s ease 1s infinite;
}
@keyframes move {
0% {
transform: translate(calc(0 * var(--width)));
}
50% {
transform: translate(calc(-1 * var(--width)));
}
100% {
transform: translate(calc(-2 * var(--width)));
}
}
在
div.slide
设置超出部分隐藏
div.slide {
width: var(--width);
height: var(--height);
border: .2rem dashed purple;
/* 新增 */
overflow: hidden;
}
实现无缝切换
首先在HTML代码中再多增一张编号为1的图片
<div class="slide">
<ul class="list">
<li class="item">
1
</li>
<li class="item">
2
</li>
<li class="item">
3
</li>
<!-- 新增 -->
<li class="item">
1
</li>
</ul>
</div>
增加
ul.list
为4
倍图片宽度
ul.list {
/* 修改 */
width: calc(var(--width) * 4);
height: inherit;
position: relative;
z-index: -1;
animation: move 5s ease 1s infinite;
}
将动画再添加一个关键帧实现从
3
过渡到1
的效果,从而实现无缝切换效果
@keyframes move {
0% {
transform: translate(calc(0 * var(--width)));
}
33% {
transform: translate(calc(-1 * var(--width)));
}
66% {
transform: translate(calc(-2 * var(--width)));
}
100% {
transform: translate(calc(-3 * var(--width)));
}
}
由于是循环播放的动图,请看清动画的开始和结束点。
再注释掉div.slide的超出隐藏样式,看下真正的位移过程
原理:因为最后一帧在完成完全展示
图1
动画后,就是下个动画的开始,将图1
左移,又因为动画的开始和结束之间没有时间间隔,正好形成了完美的无缝切换的效果。相反方向的同理可得。
小原点切换
设置鼠标经过轮播图区域时暂停动画。
.slide:hover .list{
animation-play-state: paused;
}
在HTML代码中添加
单选按钮
,通过单选按钮的选中切换图片,又因为单选按钮无法设置样式,所以使用label标签配合生成圆点样式。
注意:label一定要在ul.list
前面,等下需要通过兄弟元素选择ul.list
标签内的图片
<div class="slide">
<!-- 新增 -->
<input type="radio" name='pic' id='pic1' checked>
<input type="radio" name='pic' id='pic2'>
<input type="radio" name='pic' id='pic3'>
<div class="labels">
<label for="pic1"></label>
<label for="pic2"></label>
<label for="pic3"></label>
</div>
<ul class="list">
<li class="item">
1
</li>
<li class="item">
2
</li>
<li class="item">
3
</li>
<li class="item">
1
</li>
</ul>
</div>
将单选按钮隐藏,再把制作好的
小圆点
定位到图片区域,以及添加选中
效果。
div.slide {
width: var(--width);
height: var(--height);
border: .2rem dashed purple;
overflow: hidden;
/* 新增 */
/* 给input做定位参考 */
position: relative;
}
input {
display: none;
}
.labels {
position: absolute;
bottom: .5rem;
/* 注意层级 */
z-index: 1;
width: inherit;
justify-content: center;
display: flex;
}
.labels label {
width: .5rem;
height: .5rem;
border-radius: 50%;
margin: 0 .3rem;
border: .1rem solid #fff;
background-color: transparent;
box-sizing: border-box;
cursor: pointer;
}
input[id=pic1]:checked ~ .labels label[for=pic1],
input[id=pic2]:checked ~ .labels label[for=pic2],
input[id=pic3]:checked ~ .labels label[for=pic3] {
background-color: #fff;
border: .1rem solid #fff;
}
通过单选按钮和图片对应选中当前要显示的图片
input[id=pic1]:checked ~ ul.list{
transform: translate(calc(0 * var(--width)));
}
input[id=pic2]:checked ~ ul.list {
transform: translate(calc(-1 * var(--width)));
}
input[id=pic3]:checked ~ ul.list {
transform: translate(calc(-2 * var(--width)));
}
此时发现之前的
暂停动画
是不行的,会影响这里的单选选中对应图片的效果,所以要把之前的暂停动画改为完全清除掉动画
。
.slide:hover .list{
/* animation-play-state: paused; */
/* 修改为完全清除动画 */
animation: none;
}
这时会发现
自动
和手动
互不影响,当鼠标离开
的时候,又从第一张图开始轮播,而鼠标再次经过
轮播图区域的时候,会展示当前单选按钮选中的图片
,也就是之前选中的图片展示状态会被保留
。
但是目前仔细看的话,会发现一个奇怪的问题,就是自动轮播的时候,
小圆点
不能跟随图片的切换相应的选中
,原因可想而知,由于没有用js
,所以不可能通过图片的切换
来改变单选框的选中
。为了解决这个问题,可以默认让小圆点隐藏
,鼠标经过的时候再显示出来
。
.slide:hover {
/* 鼠标经过手型 */
cursor: pointer;
}
.slide:hover .labels {
/* 鼠标经过才展示小圆点 */
display: flex;
}
.labels {
position: absolute;
bottom: .5rem;
z-index: 1;
width: inherit;
justify-content: center;
/* 修改 */
display: none;
}
最终效果
总结
这里用CSS实现的轮播图是不能真正在生产环境中使用的,只作为学习和研究CSS特性使用,当然也可以期待着有一天真的可以用CSS完美实现轮播图的到来呀!如果您有更好的创意的话,欢迎评论留言哦!