每個(gè)制作出來(lái)的css3動(dòng)畫(huà)都凝結(jié)了設(shè)計(jì)者和創(chuàng)作者智慧的結(jié)晶,以此,我們要向前輩致敬;動(dòng)畫(huà)的出現(xiàn)給單調(diào)的網(wǎng)頁(yè)平添了活性,是單純的展示頁(yè)面變得不再那么枯燥,所以,作為一個(gè)web前端的開(kāi)發(fā)者能夠創(chuàng)作出屬于自己的特有的動(dòng)畫(huà),我感到很高興。
今天,我向大家介紹實(shí)現(xiàn)css下拉菜單的動(dòng)畫(huà)制作的不同方法,希望能給大家有所幫助和啟示。首先,先來(lái)個(gè)效果圖給大家看一看:


那么接下來(lái)我就給大家介紹一下這個(gè)動(dòng)畫(huà)的組成,它主要包括三個(gè)小動(dòng)畫(huà)組成。第一部分就是鼠標(biāo)的滑過(guò)的漸變動(dòng)畫(huà);第二部分,就是右邊的三角小箭頭的動(dòng)畫(huà),這個(gè)說(shuō)起來(lái)也很簡(jiǎn)單,這個(gè)三角形是使用css樣式寫(xiě)的控制元素的四條邊的顏色和各邊的顯隱來(lái)形成;第三部分,就是展開(kāi)的下拉框。
根據(jù)我之前寫(xiě)過(guò)的一篇文章《transform,transition,animation的混合使用——進(jìn)階》中對(duì)動(dòng)畫(huà)的組合形式的分類,將動(dòng)畫(huà)的實(shí)現(xiàn)分類有transform和transition組合,transform和animation組合,再結(jié)合動(dòng)畫(huà)的觸發(fā)形式,pc端常見(jiàn)的鼠標(biāo)滑過(guò)、鼠標(biāo)單擊,wap端的觸摸形式,該動(dòng)畫(huà)的最終的呈現(xiàn)形式將以下四種常見(jiàn)形式:
第一種,實(shí)現(xiàn)方案用transition(鼠標(biāo)滑過(guò))
第二種,實(shí)現(xiàn)方案用animation(鼠標(biāo)滑過(guò))
第三種,實(shí)現(xiàn)方案用transition(鼠標(biāo)單擊或觸摸)
第四種,實(shí)現(xiàn)方案用animation(鼠標(biāo)單擊或觸摸)
我將詳細(xì)講解前兩種的實(shí)現(xiàn),后兩種的實(shí)現(xiàn)(略講),由于是觸發(fā)方式的改變,所以對(duì)于javascript有一定使用經(jīng)驗(yàn)的同學(xué)將會(huì)根據(jù)自己的使用習(xí)慣很容易的形成自己所需要的代碼,進(jìn)而形成自己的css動(dòng)畫(huà)下拉菜單的解決方案。
鼠標(biāo)滑過(guò)--下拉菜單動(dòng)畫(huà)
transition和transform組合
html代碼:
<div class="l-drop-menu l-menu-1">
<span>下拉菜單</span>
<ul class="l-list">
<li class="l-list-item"><a >百度一下</a></li>
<li class="l-list-item"><a >bing搜索</a></li>
<li class="l-list-item"><a >iconfont</a></li>
</ul>
</div>
css代碼:
.l-list {
position: absolute;
top: 100%;
z-index: -1;
width: 100%;
padding: 4px 0;
background-color: #fff;
border: 1px solid #cecece;
box-sizing: border-box;
opacity: 0;
}
.l-list-item {
list-style: none;
padding: 4px 8px;
}
.l-list-item a {
display: block;
padding: 4px 0;
font-size: 16px;
color: #000;
text-align: center;
text-decoration: none;
transition: all 0.2s linear;
}
.l-list-item a:hover {
color: #fff;
background-color: #cecece;
}
.l-drop-menu {
position: relative;
width: 142px;
height: auto;
margin: 0 auto;
}
.l-drop-menu>span {
position: relative;
display: block;
padding: 8px 20px;
text-align: center;
color: #58a;
background-color: #fff;
cursor: pointer;
}
.l-drop-menu>span::after {
position: absolute;
top: 8px;
right: 16px;
content: '';
width: 0;
height: 0;
overflow: hidden;
border-width: 8px;
border-style: dashed dashed solid;
border-color: transparent transparent #c2c2c2;
transition: all 0.3s linear;
}
.l-drop-menu>span:hover {
color: #fff;
background-color: #cecece;
}
.l-drop-menu>span:hover::after {
top: 16px;
border-style: solid dashed dashed;
border-color: #ffffff transparent transparent;
}
以上是animation和transition兩種不同實(shí)現(xiàn)形式的公用代碼。
transiton實(shí)現(xiàn)形式的代碼
.l-menu-1 .l-list {
transform: translate3d(0, 10px, 0);
backface-visibility: hidden;
transition: all 0.3s linear;
}
.l-menu-1:hover .l-list {
z-index: 2;
overflow: auto;
opacity: 1;
transform: translate3d(0, 0, 0);
}
animation實(shí)現(xiàn)形式的css代碼
.l-menu-2 .l-list{
animation: l-animation-up 0.5s;
}
.l-menu-2:hover .l-list{
z-index: 2;
opacity: 1;
animation: l-animation-down 0.5s;
}
@-webkit-keyframes l-animation-down {
from {
-webkit-transform: translate3d(0, 10px, 0);
opacity: .1
}
to {
-webkit-transform: translate3d(0, 0, 0);
opacity: 1
}
}
@keyframes l-animation-down {
from {
transform: translate3d(0, 10px, 0);
opacity: .1
}
to {
transform: translate3d(0, 0, 0);
opacity: 1
}
}
@-webkit-keyframes l-animation-up {
from {
-webkit-transform: translate3d(0, 0, 0);
opacity: 1
}
to {
-webkit-transform: translate3d(0, 10px, 0);
opacity: .1
}
}
@keyframes l-animation-up {
from {
transform: translate3d(0, 0, 0);
opacity: 1
}
to {
transform: translate3d(0, 10px, 0);
opacity: .1
}
}
代碼曬完了,我們就來(lái)說(shuō)一說(shuō)做這個(gè)動(dòng)畫(huà)的注意點(diǎn)吧!
1.第一種用transition和transform的形式,下拉框我們通常的實(shí)現(xiàn)形式通過(guò)定位來(lái)實(shí)現(xiàn),本案例的實(shí)現(xiàn)形式和傳統(tǒng)的實(shí)現(xiàn)形式并無(wú)二樣;
2.第一種用transition和transform的形式,我們傳統(tǒng)的控制顯隱我們使用的是display:none,display:block;但明顯這種方案用在這里不合適,使用這種解決方案的結(jié)果就是沒(méi)用過(guò)渡效果,也即是沒(méi)有了動(dòng)畫(huà)效果,我采用了opacity和z-index來(lái)解決這種問(wèn)題(詳情查看和分析代碼);
3.第二種用animation和transform的形式,這種實(shí)現(xiàn)形式我相信大家在學(xué)習(xí)和工作中都看過(guò),但這種形式要實(shí)現(xiàn)的動(dòng)畫(huà)效果和第一種之間,我覺(jué)得地址用實(shí)現(xiàn)形式更好,因?yàn)檫@個(gè)第二種,只有展開(kāi)時(shí)的過(guò)渡效果,而沒(méi)有閉合時(shí)的過(guò)渡效果,對(duì)于要求并不高的同學(xué)來(lái)說(shuō),或許這樣的效果還不錯(cuò),但是對(duì)于我這種追求極客的來(lái)說(shuō),我還是不滿足,所以,我就試著有加入了一個(gè)移開(kāi)時(shí)的動(dòng)畫(huà),實(shí)現(xiàn)了跟第一種一樣的動(dòng)畫(huà)效果(有一個(gè)刷新頁(yè)面的問(wèn)題),但我要接著說(shuō)的是在第二點(diǎn)中我有提過(guò)有opacity和z-index解決transition形式動(dòng)畫(huà)沒(méi)有過(guò)渡的情況,在第二種形式,display:none,display:block這種控制顯隱的方式也可用。

綜上,下拉菜單動(dòng)畫(huà)最優(yōu)選擇第一種,其次,選擇第二種。
演示地址:https://lvzhenbang.github.io/css3-animate/drop-menu-anim.html
單擊--下拉菜單動(dòng)畫(huà)
單擊的動(dòng)畫(huà)和鼠標(biāo)滑過(guò)的動(dòng)畫(huà)效果區(qū)別就是觸發(fā)形式的不同,從而造成了css代碼的相應(yīng)差異,transition通過(guò)單擊實(shí)現(xiàn)就是通過(guò)改變?cè)谠刂刑砑?l-menu-active來(lái)實(shí)現(xiàn);animation通過(guò)單擊實(shí)現(xiàn)就是通過(guò)在元素中添加.l-menu-in, .l-menu-out來(lái)實(shí)現(xiàn)的。
html代碼同上
css代碼 公用和上面兩個(gè)例子重合的代碼如下:
.l-list {
position: absolute;
top: 100%;
display: none;
width: 100%;
background-color: #fff;
box-sizing: border-box;
}
.l-list-item {
list-style: none;
padding: 4px 8px;
border-top: 1px solid #cecece;
}
.l-list-item a {
display: block;
padding: 4px 0;
font-size: 16px;
color: #000;
text-align: center;
text-decoration: none;
-webkit-transition: all 0.2s linear;
}
.l-list-item a:hover {
color: #fff;
background-color: #cecece;
}
.l-drop-menu {
position: relative;
width: 142px;
height: auto;
margin: 0 auto;
}
.l-drop-menu>span {
position: relative;
display: block;
padding: 10px 20px;
text-align: center;
color: #58a;
background-color: #fff;
cursor: pointer;
}
.l-drop-menu>span::after {
position: absolute;
top: 16px;
right: 16px;
content: '';
width: 0;
height: 0;
overflow: hidden;
border-width: 8px;
border-style: solid dashed dashed;
border-color: #58a transparent transparent;
-webkit-transition: all 0.3s linear;
transition: all 0.3s linear;
}
transition實(shí)現(xiàn)的代碼:
.l-drop-menu.l-menu-active>span, .l-drop-menu.l-menu-in>span {
color: #fff;
background-color: #cecece;
}
.l-drop-menu.l-menu-active>span::after, .l-drop-menu.l-menu-in>span::after {
top: 8px;
border-style: dashed dashed solid;
border-color: transparent transparent #58a;
}
.l-menu-1.l-menu-active .l-list {
display: block;
-webki-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.l-menu-1 .l-list {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
-webkit-transition: all 0.3s linear;
transition: all 0.3s linear;
}
animation的代碼:
.l-menu-2.l-menu-out .l-list {
display: none;
-webkit-animation: l-animation-up 0.5s;
animation: l-animation-up 0.5s;
}
.l-menu-2.l-menu-in .l-list {
display: block;
-webkit-animation: l-animation-down 0.5s;
animation: l-animation-down 0.5s;
}
@-webkit-keyframes l-animation-down {
from {
-webkit-transform: translate3d(0, 10px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
}
}
@keyframes l-animation-down {
from {
transform: translate3d(0, 10px, 0);
}
to {
transform: translate3d(0, 0, 0);
}
}
@-webkit-keyframes l-animation-up {
from {
-webkit-transform: translate3d(0, 0, 0);
}
to {
-webkit-transform: translate3d(0, 10px, 0);
}
}
@keyframes l-animation-up {
from {
transform: translate3d(0, 0, 0);
}
to {
transform: translate3d(0, 10px, 0);
}
}
綜上,你會(huì)發(fā)現(xiàn)transition實(shí)現(xiàn)的動(dòng)畫(huà),當(dāng)你單擊時(shí)發(fā)現(xiàn)動(dòng)畫(huà)用display:none,display:block;這種方式依然不能達(dá)到預(yù)期的效果,所以還是應(yīng)該采用opacity和z-index的方案;但是使用animation測(cè)沒(méi)有任何問(wèn)題,與此同時(shí)當(dāng)你刷新網(wǎng)頁(yè)時(shí),不會(huì)出現(xiàn)問(wèn)題。
所以,當(dāng)單擊實(shí)現(xiàn)下拉菜單這兩種方案都不錯(cuò),但是理解起來(lái)相對(duì)簡(jiǎn)單的是animation的形式。

關(guān)于如何改transition的單擊實(shí)現(xiàn)方案,各位同學(xué)可以當(dāng)作一個(gè)小例子來(lái)實(shí)踐一下。
transition的js代碼:
var menu1 = document.getElementsByClassName('l-menu-1')[0];
menu1.onclick = function() {
var className = menu1.className;
if (~className.indexOf('l-menu-active')) {
menu1.className = className.replace(' l-menu-active', '');
} else {
menu1.className += ' l-menu-active';
}
}
animation的js代碼:
var menu2 = document.getElementsByClassName('l-menu-2')[0];
menu2.onclick = function() {
var className = menu2.className;
if (~className.indexOf('l-menu-in')) {
menu2.className = className.replace('l-menu-in', 'l-menu-out');
} else {
menu2.className += ' l-menu-in';
}
}
演示地址:https://lvzhenbang.github.io/css3-animate/drop-menu-anim2.html
源代碼下載地址:github地址:https://github.com/lvzhenbang/css3-animate/tree/gh-pages