一、项目介绍
小项目主要是实现鼠标经过不同按钮时呈现出不同的动画效果,比如:按钮背景颜色改变、按钮背景旋转、按钮背景颜色由左向右或由上向下被其它颜色覆盖、按钮边框线以某个中心点向两边扩散等动画效果,其按钮颜色多姿多彩。有趣的按钮
二、思路总结
(1)页面总结
首先分析页面的结构,整个页面背景颜色固定,然后从上到下依次是标题栏、副标题栏、不同颜色的按钮区域以及底部结束语区域。
根据上述的介绍,因此将整个页面分为四个区域单独进行css样式书写,其HTML结构如下:
<header>
<link href="https://fonts.googleapis.com/css2?family=Lato&display=swap" rel="stylesheet">
</header>
<!-- 标题栏区域 -->
<h1>Animation Buttons</h1>
<!-- 副标题栏区域 -->
<p>Hover us and enjoy the satisfying neumorphic animation designs!</p>
<!-- 按钮区域 -->
<ul class='container'>
<li><button class='btnCommon btn1'>Read More</button></li>
<li><button class='btnCommon btn2'>Read More</button></li>
<li><button class='btnCommon btn3'><span>Read More</span></button></li>
<li><button class='btnCommon btn4'>Read More</button></li>
<li><button class='btnCommon btn5'>Read More</button></li>
<li><button class='btnCommon btn6'><span>Read More</span></button></li>
<li><button class='btnCommon btn7'><span>Read More</span></button></li>
<li><button class='btnCommon btn8'><span>Read More</span></button></li>
<li><button class='btnCommon btn9'>Read More</button></li>
<li><button class='btnCommon btn10'>Read More</button></li>
<li><button class='btnCommon btn11'>Read More</button></li>
<li><button class='btnCommon btn12'>
<span>Click!</span>
<span>Read More</span>
</button></li>
<li><button class='btnCommon btn13'>Read More</button></li>
<li><button class='btnCommon btn14'>Read More</button></li>
<li><button class='btnCommon btn15'>Read More</button></li>
<li><button class='btnCommon btn16'>Read More</button></li>
</ul>
<!-- 结束区域 -->
<div class='footer'>DEERBUCKS DESIGNING</div>
注意点:
①为了实现鼠标经过button按钮时出现背景颜色旋转、边框线向两边扩散以及颜色覆盖等效果,使用的是伪类选择器(:before,:after)实现,详情参考第二小节css介绍。
②随着屏幕的大小变化整个页面元素的布局会发生变化,比如按钮在屏幕较大时会一行显示多个,屏幕较小时会显示几个,即呈现出自适应的布局,且所有元素均水平居中,因此采用百分比布局能够满足要求。
(2)CSS样式实现
首先确定几个点:
1、根据对页面元素结构分析,所有元素水平居中且能够实现自适应布局,因此明确整个布局采用百分比布局,随着页面大小变化而自动更改元素位置。
2、按钮区域每个按钮的大小相同且在一行上显示多个,此处采用中包裹的方式布局按钮,源项目中采用的是的形式进行布局的。
3、按钮的背景颜色或者鼠标经过按钮时背景颜色呈现出渐变,因此整个css中所有按钮使用设置颜色的渐变。
4、每个按钮初始均有阴影,采用在公共类名中给所有按钮设置阴影,避免代码冗余。
5、鼠标经过按钮时会呈现出一系列的动画,为使动画看起来更加自然和流畅,在公共类名中使用过渡的方式给每个按钮设置动画的时间和运动曲线。
6、鼠标经过按钮时出现以按钮某角为中心边框线向两边扩散的动画,这需要借助实现。给button添加或两个元素,并且分别设置高度和宽度,且同一元素的高度和宽度不能同时存在值,利用定位将两个元素分别定位到button不同的角,并且需要给伪类元素添加过渡以实现动画效果。此类动画效果是否添加几个伪类元素取决于button动画的边框线是否需要全部显示。
下面分别介绍两种情况:
第一种:若button按钮需要两个边框线分别向两边扩散的效果,则button按钮本身的两个伪类选择器就已经足够实现,利用上述描述的方法实现即可。对应的css代码如下:
.btn5{
background: linear-gradient(0deg, rgba(255,27,0,1) 0%, rgba(251,75,2,1) 100%);
position:relative;
}
.btn5:before,
.btn5:after{
content:'';
position:absolute;
width:0;
height:1px;
background:rgba(255,27,0,1);
transition: all 0.4s ease;
}
.btn5:before{
right:0;
top:0;
}
.btn5:after{
bottom:0;
left:0;
}
.btn5:hover{
background:transparent;
color:#f0094a;
box-shadow:none;
}
.btn5:hover:before,
.btn5:hover:after{
width:100%;
}
如图中动画效果所示:
第二种:若button按钮需要四条边框线向不同方向扩散的动画效果,除了button按钮本身的两个伪类元素之外,还需要借助额外的标签将button按钮的内容进行包裹,源项目中使用的是标签进行包裹,并将span标签的属性设置为,将其宽度和高度设置为100%,再利用span标签的两个伪类元素按照上述button处理伪类元素的方式进行样式的设置,最终实现动画效果。css代码如下:
.btn3{
background: linear-gradient(0deg, rgba(0,172,238,1) 0%, rgba(2,126,251,1) 100%);
position:relative;
}
/* 为添加以左下角为中心点出发的边框线做准备 */
.btn3 span{
width:100%;
height:100%;
position:relative;
/* 让span标签的宽度和高度生效 */
display:block;
}
.btn3:before,
.btn3:after{
content: '';
position: absolute;
top: 0;
right: 0;
background: rgba(2, 126, 251, 1);
/* 给这两个伪类元素设置过渡 */
transition: all 0.4s ease;
}
/* 给伪类元素分别设置高度和宽度 */
.btn3:before{
width:2px;
height:0;
}
.btn3:after{
width:0;
height:2px;
}
.btn3 span:before,
.btn3 span:after{
content:'';
position:absolute;
bottom:0;
left:0;
background: rgba(2, 126, 251, 1);
/* 给这两个伪类元素设置过渡 */
transition: all 0.4s ease;
}
/* 开始这里把span写成.span,导致以左下角为出发点的边框线动态显示不出来*/
.btn3 span:before{
width:2px;
height:0;
}
.btn3 span:after{
width:0;
height:2px;
}
.btn3:hover{
background:transparent;
box-shadow:none;
}
.btn3:hover:before{
/* 开始这里显示不出来是因为设置的是width:100%,即同名属性,是不会发生变化的 */
height:100%;
}
.btn3:hover:after{
width:100%;
}
.btn3 span:hover{
color:rgba(2,126,251,1);
}
.btn3 span:hover:before{
height:100%;
}
.btn3 span:hover:after{
width:100%;
}
如图中动画效果所示:
其余类似动画效果按照该方式稍加改动即可实现。对应样式按钮为3~8。
8、鼠标经过button按钮时出现背景颜色旋转,主要是借助和两个属性实现。首先给父级元素添加相对定位,给当前按钮添加伪类选择器,同时设置和为100%,且使用定位并设置相关的偏移属性将其固定,同时添加,父级元素添加,目的是让层叠的子级不会遮挡住父级的内容,鼠标经过时给伪类选择器设置且达到效果,即让其在旋转时并放大,且父级添加属性,隐藏背景色旋转时超出button按钮范围外的颜色。对应相关样式按钮为9~12。
9、鼠标经过按钮时出现背景颜色被其它颜色覆盖的效果,首先给父级元素添加相对定位,为当前button元素的伪类选择器添加绝对定位以及设置相应的宽度和高度实现,且宽度和高度不能同时有值(例如:height:0,width:100%或height:100%,width:0),定位选择哪两种偏移量依据于当前元素需要呈现的效果,鼠标经过时再将其伪类元素的高度或宽度设置为100%,且改变定位偏移量(left、top、right、bottom)中某一个或某两个的值。此处动画中涉及在绝对定位中,水平方向或者垂直方向上给、、、的初始值设置为时,浏览器如何分配偏移距离的问题,详情请参照这篇文章:关于元素绝对定位时的auto问题。对应样式按钮为13~16。
整个页面css代码如下:
body{
background:#e0e5ec;
}
/* 对ul、li的默认样式进行清空 */
ul,li,button{
padding:0;
margin:0;
}
li{
list-style:none;
}
h1{
color:#353535;
font-size:50px;
/* 仅对行内、行内块元素设置水平居中 */
text-align:center;
/* 通常允许给定一个有先后顺序的,由字体名或者字体族组成的列表来为选定的元素设置字体 */
font-family:"Cormorant Garamond", serif;
}
p{
text-align:center;
font-size:18px;
color:#676767;
/* 设置字体加粗,设置400等同于属性normal(即不加粗)的效果,500即表示加粗一点点 */
font-weight:500;
font-family:'Lato', sans-serif;
}
/* 内容主体区域 */
.container{
/* 百分比布局,随着页面大小的改变样式自适应的改变,高度不设置,由盒子里面的内容撑开,同时也是便于后续继续向该盒子添加内容 */
width:90%;
margin:40px auto;
/* 解决外边距合并的问题 */
overflow:hidden;
/* 设置里面的li元素水平居中(li的display已经修改为行内块) */
text-align:center;
}
.container li{
width:130px;
height:40px;
margin:20px;
display:inline-block;
border-radius:5px;
}
.btnCommon{
/* 继承父级元素的宽度和高度 */
width:100%;
height:100%;
border-radius:5px;
/* 去掉默认的边框 */
outline:none;
border:none;
color:#fff;
text-align:center;
line-height:40px;
font-weight:500;
font-family:'Lato', sans-serif;
/* 设置鼠标点击样式 */
cursor:pointer;
/* 设置过渡,基于鼠标触发
transition:需要过渡的属性 过渡的持续时间 过渡的速度曲线 过渡的开始时间
*/
transition: all 0.3s ease;
/* 设置盒子阴影box-shadow四个属性值分别表示:阴影的X轴偏移量、y轴偏移量、模糊半径、扩散半径以及颜色
rgba用于定义颜色且可以指定颜色的不透明度,最后的参数值越小透明度越强,参数值越大透明度越小
*/
box-shadow: 2px 2px 10px 0 rgba(27, 26, 26, 0.3);
}
.btn1{
/* linear-gradient() 函数用于创建一个表示两种或多种颜色线性渐变的图片 */
background:linear-gradient(0deg, rgba(6,14,131,1) 0%, rgba(12,25,180,1) 100%);
}
/* 鼠标经过时触发 */
.btn1:hover{
/* 背景颜色渐变设置后,鼠标经过时使用backgroun-color改变背景颜色没有反应 */
/* background-color:orange; */
background:linear-gradient(0deg, rgba(0,3,255,1) 0%, rgba(2,126,251,1) 100%);
}
.btn2{
background:linear-gradient(0deg, rgba(96,9,240,1) 0%, rgba(129,5,240,1) 100%);
}
.btn2:hover {
/* 设置负值就可设置与默认方向相反的阴影 */
box-shadow: -4px -4px 10px rgba(42, 25, 25, 0.4);
}
.btn3{
background: linear-gradient(0deg, rgba(0,172,238,1) 0%, rgba(2,126,251,1) 100%);
position:relative;
}
/* 为添加以左下角为中心点出发的边框线做准备 */
.btn3 span{
width:100%;
height:100%;
position:relative;
/* 让span标签的宽度和高度生效 */
display:block;
}
.btn3:before,
.btn3:after{
content: '';
position: absolute;
top: 0;
right: 0;
background: rgba(2, 126, 251, 1);
/* 给这两个伪类元素设置过渡 */
transition: all 0.4s ease;
}
/* 给伪类元素分别设置高度和宽度 */
.btn3:before{
width:2px;
height:0;
}
.btn3:after{
width:0;
height:2px;
}
.btn3 span:before,
.btn3 span:after{
content:'';
position:absolute;
bottom:0;
left:0;
background: rgba(2, 126, 251, 1);
/* 给这两个伪类元素设置过渡 */
transition: all 0.4s ease;
}
/* 开始这里把span写成.span,导致以左下角为出发点的边框线动态显示不出来*/
.btn3 span:before{
width:2px;
height:0;
}
.btn3 span:after{
width:0;
height:2px;
}
.btn3:hover{
background:transparent;
box-shadow:none;
}
.btn3:hover:before{
/* 开始这里显示不出来是因为设置的是width:100%,即同名属性,是不会发生变化的 */
height:100%;
}
.btn3:hover:after{
width:100%;
}
.btn3 span:hover{
color:rgba(2,126,251,1);
}
.btn3 span:hover:before{
height:100%;
}
.btn3 span:hover:after{
width:100%;
}
.btn4{
background:linear-gradient(315deg, #4dccc6 0%, #96e4df 74%);
position:relative;
}
.btn4:before{
content:'';
position:absolute;
bottom:0;
left:0;
background-color:#96e4df;
transition: all 0.4s ease;
}
.btn4:before{
width:0;
height:2px;
}
.btn4:hover{
background:linear-gradient(315deg, #89d8d3 0%, #03c8a8 74%);
}
.btn4:hover:before{
width:100%;
}
.btn5{
background: linear-gradient(0deg, rgba(255,27,0,1) 0%, rgba(251,75,2,1) 100%);
position:relative;
}
.btn5:before,
.btn5:after{
content:'';
position:absolute;
width:0;
height:1px;
background:rgba(255,27,0,1);
transition: all 0.4s ease;
}
.btn5:before{
right:0;
top:0;
}
.btn5:after{
bottom:0;
left:0;
}
.btn5:hover{
background:transparent;
color:#f0094a;
box-shadow:none;
}
.btn5:hover:before,
.btn5:hover:after{
width:100%;
}
.btn6{
background:radial-gradient(circle, rgba(247,150,192,1) 0%, rgba(118,174,241,1) 100%);
position:relative;
}
.btn6 span{
position:relative;
width:100%;
height:100%;
display:block;
}
.btn6:before,
.btn6:after{
content:'';
position:absolute;
width:0;
height:2px;
box-shadow:
-1px -1px 20px 0px rgba(255,255,255,1),
-4px -4px 5px 0px rgba(255,255,255,1),
7px 7px 20px 0px rgba(0,0,0,.4),
4px 4px 5px 0px rgba(0,0,0,.3);
transition: all 0.4s ease;
}
.btn6 span:before,
.btn6 span:after{
content:'';
position:absolute;
width:1px;
height:0;
box-shadow:
-1px -1px 20px 0px rgba(255,255,255,1),
-4px -4px 5px 0px rgba(255,255,255,1),
7px 7px 20px 0px rgba(0,0,0,.4),
4px 4px 5px 0px rgba(0,0,0,.3);
transition: all 0.4s ease;
}
.btn6:before{
top:0;
left:0;
}
.btn6:after{
bottom:0;
right:0;
}
.btn6:hover{
background:transparent;
color:#76aef1;
box-shadow:none;
}
.btn6:hover:before{
width:100%;
}
.btn6:hover:after{
width:100%;
}
.btn6 span:before{
left:0;
bottom:0;
}
.btn6 span:after{
right:0;
top:0;
}
.btn6 span:hover:before{
height:100%;
}
.btn6 span:hover:after{
height:100%;
}
.btn7{
background:linear-gradient(0deg, rgba(255,151,0,1) 0%, rgba(251,75,2,1) 100%);
position:relative;
}
.btn7 span{
position:relative;
width:100%;
height:100%;
display:block;
}
.btn7:after,
.btn7:before{
content:'';
position:absolute;
top:0;
left:0;
background:linear-gradient(0deg, rgba(255,151,0,1) 0%, rgba(251,75,2,1) 100%);
transition:all 0.4s ease;
}
.btn7:before{
width:0;
height:2px;
}
.btn7:after{
width:2px;
height:0;
}
.btn7:hover{
background:transparent;
color:rgba(251,75,2,1);
}
.btn7:hover:before{
width:100%;
}
.btn7:hover:after{
height:100%
}
.btn7 span:before,
.btn7 span:after{
content:'';
position:absolute;
right:0;
bottom:0;
background:linear-gradient(0deg, rgba(255,151,0,1) 0%, rgba(251,75,2,1) 100%);
transition: all 0.4s ease;
}
.btn7 span:before{
width:2px;
height:0;
}
.btn7 span:after{
width:0;
height:2px;
}
.btn7 span:hover:before{
height:100%;
}
.btn7 span:hover:after{
width:100%;
}
.btn8{
background:linear-gradient(315deg, #f0ecfc 0%, #c797eb 74%);
position:relative;
}
.btn8 span{
position:relative;
width:100%;
height:100%;
display:block;
}
.btn8:after,
.btn8:before{
content:'';
position:absolute;
top:0;
left:0;
background:#c797eb;
transition:all 0.4s ease;
}
.btn8:before{
width:0;
height:2px;
}
.btn8:after{
width:2px;
height:0;
}
.btn8:hover{
background:transparent;
color:#c797eb;
}
.btn8:hover:before{
width:100%;
}
.btn8:hover:after{
height:100%
}
.btn8 span:before,
.btn8 span:after{
content:'';
position:absolute;
right:0;
bottom:0;
background:#c797eb;
transition: all 0.4s ease;
}
.btn8 span:before{
width:2px;
height:0;
}
.btn8 span:after{
width:0;
height:2px;
}
.btn8 span:hover:before{
height:100%;
}
.btn8 span:hover:after{
width:100%;
}
.btn9{
/* 给button添加背景颜色会导致效果呈现不出来,因为鼠标离开之后会马上变回自己的颜色,导致不会出现旋转的效果 */
/* background:linear-gradient(315deg, #1fd1f9 0%, #b621fe 74%); */
position:relative;
/* 将溢出部分进行隐藏 */
overflow:hidden;
/* z-index主要用于在堆叠的盒子中改变盒子的堆叠层级,值越大盒子就越在上层显示(一般用于定位元素中且position值不为static) */
z-index:1;
}
.btn9:after{
position:absolute;
content:'';
top:0;
left:0;
width:100%;
height:100%;
/* 将当前after这个盒子放在button盒子下面,不然会覆盖到button的内容 */
z-index:-1;
background:linear-gradient(315deg, #1fd1f9 0%, #b621fe 74%);
transition:all 0.4s ease;
}
.btn9:hover{
background:transparent;
box-shadow: -3px -3px 5px rgba(42, 25, 25, 0.3);
}
.btn9:hover:after{
/* 实现浏览器兼容 */
-webkit-transform: scale(1) rotate(180deg);
/* 旋转+放大 */
transform: scale(1) rotate(180deg);
}
.btn10{
background:linear-gradient(0deg, rgba(22,9,240,1) 0%, rgba(49,110,244,1) 100%);
position:relative;
}
.btn10:before{
content:'';
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
transform:scale(0.1);
z-index:-1;
background:linear-gradient(0deg, rgba(2,126,251,1) 0%, rgba(0,3,255,1)100%);
transition:all 0.4s ease;
}
.btn10:hover{
background:transparent;
}
.btn10:hover:before{
-webkit-transform: scale(1);
transform:scale(1);
}
.btn11{
background:linear-gradient(0deg, rgba(251,33,117,1) 0%, rgba(234,76,137,1) 100%);
position:relative;
overflow:hidden;
}
.btn11:after{
content:'';
display:inline-block;
position:absolute;
top:-19px;
left:-10px;
width:30px;
height:100%;
/* transform:rotate(45deg); */
background-color:#fff;
/* 添加动画:动画名称 动画持续时间 动画的运动曲线 动画开始时间 动画执行次数 */
animation:move 1s ease-in-out infinite;
}
.btn11:hover{
/* 设置透明度 */
opacity:0.7;
}
/* 鼠标点击时出现的样式 */
.btn11:active{
/* box-shadow第一个属性为inset表示可以改变阴影的方向,即让阴影在内部呈现,而不是在盒子的外部 */
box-shadow: inset 4px 4px 5px rgba(42, 25, 25, 0.3);
}
/* @keyframes表示定义一个动画,后面跟着动画名称 */
@keyframes move{
0%{transform:scale(0) rotate(45deg);
opacity:0;
};
50%{
transform:scale(0) rotate(45deg);
opacity:0.3;
}
81%{
transform:scale(4) rotate(45deg);
opacity:0.8;
}
100%{
transform:scale(50) rotate(45deg);
opacity:0;
}
}
.btn12{
position:relative;
}
.btn12 span{
background: linear-gradient(0deg, rgba(0,172,238,1) 0%, rgba(2,126,251,1) 100%);
display:block;
width:100%;
height:100%;
border-radius:5px;
position:absolute;
top:0;
left:0;
transition:all 0.3s ease;
}
.btn12 span:first-child{
transform:rotateX(90deg);
/* transform-origin更改元素旋转的中心,默认是center,属性值有三个时,第三个值代表Z轴的偏移量 */
transform-origin: 50% 50% -20px;
}
.btn12 span:last-child{
transform:rotateX(0deg);
transform-origin: 50% 50% -20px;
}
.btn12:hover span:first-child{
transform:rotateX(0deg);
}
.btn12:hover span:last-child{
transform:rotateX(-90deg);
}
.btn13{
background: linear-gradient(315deg, #89d8d3 0%, #03c8a8 74%);
position:relative;
}
.btn13:before{
content:'';
position:absolute;
bottom:0;
left:0;
width:100%;
height:0;
z-index:-1;
background-color:#fff ;
border-radius:5px;
/* 因为这个单词少写了一个r,导致样式效果一直出不来,一直以为自己写的有问题,排查了很久 */
transition:all 0.3s ease;
}
.btn13:hover:before{
top:0;
height:100%;
z-index:1;
opacity:0.5;
}
.btn13:active{
transform:translateY(4px);
}
.btn14{
background:rgb(255,151,0);
position:relative;
z-index:1;
}
.btn14:before{
content:'';
position:absolute;
top:0;
left:0;
width:100%;
height:0;
z-index:-1;
background:#eaf818;
border-radius:5px;
transition:all 0.3s ease;
}
.btn14:hover{
color: #000;
}
.btn14:hover:before{
/* auto是top的初始值,其作用依据于所采用的的定位方式 */
top:auto;
bottom:0;
height:100%;
}
.btn14:active{
transform:translateY(4px);
}
.btn15{
background:#b621fe;
position:relative;
z-index:1;
}
.btn15:before{
content:'';
position:absolute;
top:0;
right:0;
width:0;
height:100%;
z-index:-1;
background:#663dff;
border-radius:5px;
transition:all 0.3s ease;
}
.btn15:hover:before{
left:0;
width:100%;
}
.btn15:active{
transform:translateY(4px);
}
.btn16 {
background: #e0e5ec;
color: #000;
box-shadow: inset 2px 2px 2px 0 rgba(255, 255, 255, 0.5), 4px 4px 10px 0 rgba(28, 27, 27, 0.2);
position:relative;
z-index:1;
}
.btn16:before{
content:'';
position:absolute;
top:0;
left:0;
width:0;
height:100%;
z-index:-1;
box-shadow: -7px -7px 20px 0px #fff9, -4px -4px 5px 0px #fff9, 7px 7px 20px 0px #0002, 4px 4px 5px 0px #0001;
transition:all 0.3s ease;
}
.btn16:hover:before {
left: auto;
right: 0;
width: 100%;
}
.btn16:active{
transform:translateY(4px);
}
.footer {
width: 90%;
margin: 18px auto;
text-align: center;
font-weight: 300px;
font-family: Andale Mono, monospace;
font-size: 18px;
color: #676767;
}
下面为整个项目的全部代码运行