CSSのみでAndroid4.4 Kitkatのイースターエッグを再現する
以前作成したHTMLとCSSのみでiOS7を作るの反響が良かったため、CSSプログラミング第二弾を行ってみました。
今回はAndroid 4.4(Kitkat)のイースターエッグを再現してみました。前回がiOSだったので今回はAndroidです。
※本ページは広告・アフィリエイトプログラムにより収益を得ています。
デモ
まずはデモページをご覧下さい。
CSS3を使用しているため、古いIEだとレイアウトが崩れます。Safari、Google Chrome、Firefoxでどうぞ!スマホだとちょっと動作が重いです。。
画像は以下の記事からお借りしています。
Android 4.4のイースターエッグに登場するレアキャラ一覧! – ちむどろいど
動作説明
動作をスクリーンショットで説明していきます。
ページにアクセスするとイースターエッグの最初の画面に遷移します。大きくKと書かれた文字が画面中央に表示されています。この文字をクリックして下さい。
クリックすると文字が回転しながら消えて、背景が左右にスライドしていきます。
その後すぐにKitkatのロゴがバウンドして表示されます。
Kitkatのロゴをタップすると、ズームインしながら黒い背景が表示されます。
そこからフェードインしながらドロイドくんたちが表示されて、いくつかパネルが回転します。
実際はスワイプでパネルを移動したりすることが出来ますが、CSSのみでは再現できませんでした。jQueryなどを使用すればもっと近づけることが出来たかもしれないです。
ソースの解説
HTML
HTMLはそこまで複雑な構造ではないです。
<input type="checkbox" id="easterEgg1" name="easterEgg1" autocomplete="off">
<div id="wrap">
<input type="checkbox" id="easterEgg2" name="easterEgg2" autocomplete="off">
<div id="display">
<div id="k">
<p><label for="easterEgg1">K</label></p>
<!-- / #k --></div>
<div id="Kitkat">
<div id="inner">
<p>
<label for="easterEgg2"><span title="A">A</span><span title="n">n</span><span title="d">d</span><span title="r">r</span><span title="o">o</span><span title="i">i</span><span title="d">d</span></label>
</p>
<!-- / #inner --></div>
<footer>
<p>ANDROID 4.4</p>
</footer>
<!-- / #Kitkat --></div>
<div id="droid">
<ul class="clearfix">
<li>
<ul>
<li><img src="img/dessert_android.png" width="512" height="512"></li>
<li><img src="img/dessert_cupcake.png" width="512" height="512"></li>
</ul>
</li>
<li><img src="img/dessert_dandroid.png" width="512" height="512"></li>
<li><img src="img/dessert_donut.png" width="512" height="512"></li>
<li><img src="img/dessert_donutburger.png" width="512" height="512"></li>
<li>
<ul>
<li><img src="img/dessert_flan.png" width="512" height="512"></li>
<li><img src="img/dessert_froyo.png" width="512" height="512"></li>
</ul>
</li>
<li><img src="img/dessert_eclair.png" width="512" height="512"></li>
<li><img src="img/dessert_honeycomb.png" width="512" height="512"></li>
<li><img src="img/dessert_gingerbread.png" width="512" height="512"></li>
<li><img src="img/dessert_ics.png" width="512" height="512"></li>
<li><img src="img/dessert_jandycane.png" width="512" height="512"></li>
<li>
<ul>
<li><img src="img/dessert_jellybean.png" width="512" height="512"></li>
<li><img src="img/dessert_keylimepie.png" width="512" height="512"></li>
</ul>
</li>
<li><img src="img/dessert_kitkat.png" width="512" height="512"></li>
<li>
<ul>
<li><img src="img/dessert_zombiegingerbread.png" width="512" height="512"></li>
<li><img src="img/dessert_dandroid.png" width="512" height="512"></li>
</ul>
</li>
<li><img src="img/dessert_petitfour.png" width="512" height="512"></li>
<li><img src="img/dessert_flan.png" width="512" height="512"></li>
<li><img src="img/dessert_cupcake.png" width="512" height="512"></li>
<li><img src="img/dessert_android.png" width="512" height="512"></li>
<li>
<ul>
<li><img src="img/dessert_eclair.png" width="512" height="512"></li>
<li><img src="img/dessert_donutburger.png" width="512" height="512"></li>
</ul>
</li>
<li>
<ul>
<li><img src="img/dessert_flan.png" width="512" height="512"></li>
<li><img src="img/dessert_froyo.png" width="512" height="512"></li>
</ul>
</li>
<li><img src="img/dessert_eclair.png" width="512" height="512"></li>
<li><img src="img/dessert_gingerbread.png" width="512" height="512"></li>
<li><img src="img/dessert_honeycomb.png" width="512" height="512"></li>
<li><img src="img/dessert_ics.png" width="512" height="512"></li>
<li><img src="img/dessert_jellybean.png" width="512" height="512"></li>
<li>
<ul>
<li><img src="img/dessert_dandroid.png" width="512" height="512"></li>
<li><img src="img/dessert_keylimepie.png" width="512" height="512"></li>
</ul>
</li>
<li>
<ul>
<li><img src="img/dessert_kitkat.png" width="512" height="512"></li>
<li><img src="img/dessert_zombiegingerbread.png" width="512" height="512"></li>
</ul>
</li>
</ul>
<!-- / #droid --></div>
<!-- / #display --></div>
<!-- / #wrap --></div>
CSS
CSSのソースを全部乗せると恐ろしく長いのでポイントだけ解説します。
最初のKが回転するアニメーションはCSS3アニメーションで行っております。
#k{
position:absolute;
top:0;
left:0;
overflow:hidden;
display:table;
width:100%;
height:100%;
z-index:999;
}
/* 背景 */
#k:before, #k:after{
content:"";
position:absolute;
top:0;
left:0;
display:block;
width:50%;
height:100%;
background:rgba(0,0,0,0.7);
z-index:-1;
-webkit-transform:translate3d(0, 0px, 0px);
transform:translate3d(0, 0px, 0px);
}
#k:after{
-webkit-transform:translate3d(100%, 0px, 0px);
transform:translate3d(100%, 0px, 0px);
}
/* kロゴ */
#k p{
display:table-cell;
color:#fff;
font-size:250px;
line-height:1;
font-family:'Francois One', 'sans-serif';
text-align:center;
text-decoration:none;
text-shadow:0 0 5px #000;
vertical-align:middle;
z-index:9999;
}
#k p label{
cursor:pointer;
}
#kに「display:table;」を指定し、「vertical-align:middle;」と「text-align:center;」でウィンドウの中央にKのロゴを配置します。
背景はクリックした時に左右に分割するので、#kの擬似要素で左右50%ずつ半透明のフィルターを作成しておきます。
/* チェックボックスを非表示 */
#easterEgg1, #easterEgg2 {
display:none;
}
/* 左半分背景スライド */
#easterEgg1:checked ~ #wrap #display #k:before {
-webkit-animation:bgcolor1 1s linear both;
animation:bgcolor1 1s linear both;
}
@-webkit-keyframes bgcolor1{
0%{
opacity:1;
-webkit-transform:translate3d(0%, 0px, 0px);
transform:translate3d(0%, 0px, 0px);
}
100%{
opacity:0;
-webkit-transform:translate3d(-200%, 0px, 0px);
transform:translate3d(-200%, 0px, 0px);
}
}
@keyframes bgcolor1{
0%{
opacity:1;
-webkit-transform:translate3d(0%, 0px, 0px);
transform:translate3d(0%, 0px, 0px);
}
100%{
opacity:0;
-webkit-transform:translate3d(-200%, 0px, 0px);
transform:translate3d(-200%, 0px, 0px);
}
}
/* 右半分背景スライド */
#easterEgg1:checked ~ #wrap #display #k:after{
-webkit-animation:bgcolor2 1s linear both;
animation:bgcolor2 1s linear both;
}
@-webkit-keyframes bgcolor2{
0%{
opacity:1;
-webkit-transform:translate3d(100%, 0px, 0px);
transform:translate3d(100%, 0px, 0px);
}
100%{
opacity:0;
-webkit-transform:translate3d(300%, 0px, 0px);
transform:translate3d(300%, 0px, 0px);
}
}
@keyframes bgcolor2{
0%{ opacity:1; }
0%{
opacity:1;
-webkit-transform:translate3d(100%, 0px, 0px);
transform:translate3d(100%, 0px, 0px);
}
100%{
opacity:0;
-webkit-transform:translate3d(300%, 0px, 0px);
transform:translate3d(300%, 0px, 0px);
}
}
最初に動作のトリガーとなるチェックボックスを非表示にし、Kのロゴに付いたラベルでチェックをON/OFF出来るようにしておきます。
#easterEgg1(Kのロゴ)がクリックされると、それがトリガーとなりbgcolor1とbgcolor2のアニメーションが実行される仕組みです。背景のスライドに「translate3d」を使用することでスマートフォンでもスムーズにアニメーションするようにしております。
続いてKが回転するアニメーションのCSSです。
/* ページロード時(反時計回りに回転) */
#display #k p{
-webkit-animation:spin1 0.6s ease-in-out both;
animation:spin1 0.6s ease-in-out both;
}
@-webkit-keyframes spin1{
0%{
-webkit-transform:rotate(0deg);
}
100%{
-webkit-transform:rotate(-360deg);
}
}
@keyframes spin1{
0%{
transform:rotate(0deg);
}
100%{
transform:rotate(-360deg);
}
}
/* Kを押した後(時計回りに回転) */
#easterEgg1:checked ~ #wrap #display #k p{
-webkit-animation:spin2 1s linear both;
animation:spin2 1s linear both;
}
@-webkit-keyframes spin2{
0%{
-webkit-transform:rotate(0deg);
}
100%{
-webkit-transform:rotate(360deg);
font-size:0;
}
}
@keyframes spin2{
0%{
transform:rotate(0deg);
}
100%{
transform:rotate(360deg);
font-size:0;
}
}
こちらはロードした時にspin1のアニメーションを実行し、背景と同様に#easterEgg1がチェックされた時にspin2のアニメーションが実行されます。
spin2の100%のところに「font-size:0;」を入れることで、まるで吸い込まれるようなアニメーションが再現できます。
Kitkatロゴのバウンドは以下のCSSでアニメーションを指定しています。
/* 前後の切り替え */
#easterEgg1:checked ~ #wrap #display #Kitkat{
-webkit-animation:z-index 0.5s ease-in-out both;
animation:z-index 0.5s ease-in-out both;
-webkit-animation-delay:1s;animation-delay:1s;
}
@keyframes z-index{
0%{z-index:-1;}
100%{z-index:9999;}
}
@-webkit-keyframes z-index{
0%{z-index:-1;}
100%{z-index:9999;}
}
/* ロゴをバウンド */
#easterEgg1:checked ~ #wrap #display #Kitkat #inner p{
-webkit-animation:bound 0.5s ease-in-out both;
animation:bound 0.5s ease-in-out both;
/* アニメーションを1秒遅らせる */
-webkit-animation-delay:1s;
animation-delay:1s;
z-index:999;
}
@keyframes bound{
0%{
transform:scale(0) rotate(-10deg);
opacity:0;
}
60%{
transform:scale(1.1) rotate(-10deg);
}
80%{
transform:scale(0.9) rotate(-10deg);
opacity:1;
}
100%{
transform:scale(1) rotate(-10deg);
opacity:1;
}
}
@-webkit-keyframes bound{
0%{
-webkit-transform:scale(0) rotate(-10deg);
opacity:0;
}
60%{
-webkit-transform:scale(1.1) rotate(-10deg);
}
80%{
-webkit-transform:scale(0.9) rotate(-10deg);
opacity:1;
}
100%{
-webkit-transform:scale(1) rotate(-10deg);
opacity:1;
}
}
/* テキストをフェードイン */
#easterEgg1:checked ~ #wrap #display #Kitkat footer{
-webkit-animation:fadeIn 1s ease-in-out both;
animation:fadeIn 1s ease-in-out both;
/* アニメーションを1秒遅らせる */
-webkit-animation-delay:1s;
animation-delay:1s;
z-index:9999;
}
@keyframes fadeIn{
0%{opacity:0;}
80%, 100%{opacity:1;}
}
@-webkit-keyframes fadeIn{
0%{opacity:0;}
80%, 100%{opacity:1;}
}
ポイントは「animation-delay:1s;」でCSSアニメーションを1秒遅らせていることです。この1秒はKのロゴをクリックした時のアニメーションが終わるまでの時間に干渉しないように間を空けています。
アニメーションが終わったらKitkatロゴのバウンドとAndroid4.4のフェードインを同時に発動します。
本家Kitkatのロゴに近づけるために角度を付けたり1文字ごとにカーニングを行ったりと工夫しましたが、実物と比べるとやはり色々と違ってますね(;´∀`)
#inner p span{
position:relative;
top:0;
left:8px;
display:inline-block;
-webkit-transform:rotate(8deg);
-moz-transform:rotate(8deg);
-ms-transform:rotate(8deg);
-o-transform:rotate(8deg);
transform:rotate(8deg);
}
#inner p span:first-child{
font-size:150%;
left:-30px;
vertical-align:middle;
}
#inner p span:nth-child(2){
margin:0 2px 0 -50px;
}
#inner p span:nth-child(6){
margin:0 3px;
}
#inner p span:nth-child(7){
font-size:108%;
}
ちなみにKitkat風のロゴはWebkitで確認するとハイライトが付いています。これは一文字ずつを<span>で囲み、titleタグに同じ文字を入れておき、擬似要素に「background-clip:text;」でグラデーションのマスクを掛けています。
#inner p span:after{
position:absolute;
content:attr(title);
overflow:hidden;
display:block;
top:0;
left:0;
opacity:0.7;
width:100%;
color:#f87877;
text-align:center;
z-index:9999;
-webkit-text-fill-color:transparent;
-moz-text-fill-color:transparent;
text-fill-color:transparent;
-webkit-background-clip:text;
-moz-background-clip:text;
background-clip:text;
background:linear-gradient(115deg, rgba(248,120,119,1) 0%,rgba(248,120,119,1) 40%,rgba(237,29,36,1) 41%,rgba(237,29,36,1) 100%);
-webkit-text-fill-color:transparent;
text-fill-color:transparent;
-webkit-background-clip:text;
background-clip:text;
}
ドロイドくんがアニメーションするところも今までの手法と同じで、Kitkatロゴに付いたラベルをトリガーとしてアニメーションを作動させています。
/* displayの左上に絶対配置 */
#droid{
position:absolute;
top:0;
left:0;
display:table;
width:100%;
height:100%;
z-index:-999;
}
/* 黒背景 */
#droid:before{
content:"";
position:absolute;
top:50%;
left:50%;
display:table;
width:0;
height:0;
background:#333;
z-index:1;
}
/* Kitkatロゴをクリックしたら全面に持ってくる */
#easterEgg2:checked ~ #display #droid{
z-index:9999;
}
/* 黒背景を中央から画面いっぱいに広げる */
#easterEgg2:checked ~ #display #droid:before {
-webkit-animation:zoom1 0.3s ease-in-out both;
animation:zoom1 0.3s ease-in-out both;
}
@keyframes zoom1{
0%{
top:50%;
left:50%;
width:0;
height:0;
}
100% {
top:0;
left:0;
width:100%;
height:100%;
z-index:99;
}
}
@-webkit-keyframes zoom1{
0%{
top:50%;
left:50%;
width:0;
height:0;
}
100%{
top:0;
left:0;
width:100%;
height:100%;
z-index:99;
}
}
#droidの擬似要素に背景を指定して画面中央に絶対配置します。このとき要素の幅と高さを0にしておき、Kitkatロゴのクリックをトリガーにしてpositionや幅と高さを変更することで、黒い背景が画面中央からズームインするようになります。
黒い背景が表示された後に2個目のイースターエッグが表示されます。
#easterEgg2:checked ~ #display #droid ul li{
-webkit-animation:zoom2 1s ease-in-out both;
animation:zoom2 1s ease-in-out both;
/* アニメーションを1秒遅らせる */
-webkit-animation-delay:1s;
animation-delay:1s;
}
@keyframes zoom2{
0%{
-webkit-transform:scale(0.7);
transform:scale(0.7);
}
100%{
-webkit-transform:scale(1);
transform:scale(1);
}
}
@-webkit-keyframes zoom2{
0%{
-webkit-transform:scale(0.7);
transform:scale(0.7);
}
100%{
-webkit-transform:scale(1);
transform:scale(1);
}
}
パネルのサイズを少し小さくしておき、1秒間掛けて元のサイズに拡大します。数が多すぎると動作が重くなったり目がチカチカしてしまいます。使いすぎに注意!
最後はパネル部分のCSSです。
#droid ul li{
overflow:hidden;
list-style:none;
height:auto;
text-align:center;
}
#droid > ul > li{
float:left;
width:25%;
}
/* 画像を半透明にして背景を透過させる */
#droid ul li img{
display:inline-block;
opacity:0.5;
vertical-align:bottom;
}
/* パネルの色や幅の調整 */
#droid > ul > li:nth-child(1){
background:#00d96d;
width:12.5%;
}
#droid > ul > li:nth-child(1) ul li:nth-child(2){
background:#d9d900;
}
#droid > ul > li:nth-child(2){
background:#d900d9;
}
#droid > ul > li:nth-child(3){
background:#00d9d9;
}
#droid > ul > li:nth-child(4){
background:#6dd900;
}
#droid > ul > li:nth-child(5){
background:#d90000;
width:12.5%;
}
#droid > ul > li:nth-child(5) ul li:nth-child(1){
background:#00d9d9;
}
#droid > ul > li:nth-child(6){
background:#6dd900;
clear:both;
}
#droid > ul > li:nth-child(7){
background:#d9d900;
}
#droid > ul > li:nth-child(8){
background:#006dd9;
}
#droid > ul > li:nth-child(9){
background:#d96d00;
}
#droid > ul > li:nth-child(10){
background:#006dd9;
clear:both;
}
#droid > ul > li:nth-child(11){
background:#d90000;
width:12.5%;
}
#droid > ul > li:nth-child(11) ul li:nth-child(1){
background:#00d9d9;
}
#droid > ul > li:nth-child(12){
background:#6dd900;
}
#droid > ul > li:nth-child(13){
background:#d900d9;
width:12.5%;
}
#droid > ul > li:nth-child(13) ul li:nth-child(1){
background:#00d96d;
}
#droid > ul > li:nth-child(14){
background:#00d9d9;
}
#droid > ul > li:nth-child(15){
background:#d96d00;
clear:both;
}
#droid > ul > li:nth-child(16){
background:#6d00d9;
}
#droid > ul > li:nth-child(17){
background:#6dd900;
}
#droid > ul > li:nth-child(18){
background:#006dd9;
width:12.5%;
}
#droid > ul > li:nth-child(18) ul li:nth-child(1){
background:#d96d00;
}
#droid > ul > li:nth-child(19){
background:#d9d900;
width:12.5%;
}
#droid > ul > li:nth-child(19) ul li:nth-child(2){
background:#d90000;
}
#droid > ul > li:nth-child(20){
background:#d900d9;
clear:both;
}
#droid > ul > li:nth-child(21){
background:#d9d900;
}
#droid > ul > li:nth-child(22){
background:#00d9d9;
}
#droid > ul > li:nth-child(23){
background:#6dd900;
}
#droid > ul > li:nth-child(24){
background:#d90000;
width:50%;
}
#droid > ul > li:nth-child(25){
background:#6dd900;
}
#droid > ul > li:nth-child(25) ul li:nth-child(1){
background:#006dd9;
}
#droid > ul > li:nth-child(26){
background:#d96d00;
}
#droid > ul > li:nth-child(26) ul li:nth-child(2){
background:#d900d9;
}
nth-child(n)で<li>タグの背景色を1つずつ変えているため異常に長いです。小さいパネルはリストを入れ子にして幅を小さくしています。
回転のアニメーションはパネル1枚ごとに指定して回転の向きを変更しています。
/* ドロイドくん時計回り回転 */
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(1) ul li:nth-child(1) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(8) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(13) ul li:nth-child(2) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(18) ul li:nth-child(2) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(22) img{
-webkit-animation:droidAnimate1 4s ease-in-out both infinite;
animation:droidAnimate1 4s ease-in-out both infinite;
/* アニメーションを2秒遅らせる */
-webkit-animation-delay:2s;
animation-delay:2s;
}
@keyframes droidAnimate1{
/* 1秒に付き90度ずつ回転させる */
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg);
}
25%{
-webkit-transform:rotate(90deg);
transform:rotate(90deg);
}
50%{
-webkit-transform:rotate(180deg);
transform:rotate(180deg);
}
75%{
-webkit-transform:rotate(270deg);
transform:rotate(270deg);
}
100%{
-webkit-transform:rotate(360deg);
transform:rotate(360deg);
}
}
@-webkit-keyframes droidAnimate1{
/* 1秒に付き90度ずつ回転させる */
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg);
}
25%{
-webkit-transform:rotate(90deg);
transform:rotate(90deg);
}
50%{
-webkit-transform:rotate(180deg);
transform:rotate(180deg);
}
75%{
-webkit-transform:rotate(270deg);
transform:rotate(270deg);
}
100%{
-webkit-transform:rotate(360deg);
transform:rotate(360deg);
}
}
/* ドロイドくん反時計回り回転 */
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(5) ul li:nth-child(2) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(11) ul li:nth-child(1) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(15) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(19) ul li:nth-child(1) img,
#easterEgg2:checked ~ #display #droid > ul > li:nth-child(24) img{
-webkit-animation:droidAnimate2 4s ease-in-out both infinite;
animation:droidAnimate2 4s ease-in-out both infinite;
/* アニメーションを4秒遅らせる*/
-webkit-animation-delay:4s;
animation-delay:4s;
}
@keyframes droidAnimate2{
/* 1秒に付き逆方向に90度ずつ回転させる */
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg);
}
25%{
-webkit-transform:rotate(-90deg);
transform:rotate(-90deg);
}
50%{
-webkit-transform:rotate(-180deg);
transform:rotate-(180deg);
}
75%{
-webkit-transform:rotate(-270deg);
transform:rotate(-270deg);
}
100%{
-webkit-transform:rotate(-360deg);
transform:rotate(-360deg);
}
}
@-webkit-keyframes droidAnimate2{
/* 1秒に付き逆方向に90度ずつ回転させる */
0%{
-webkit-transform:rotate(0deg);
transform:rotate(0deg);
}
25%{
-webkit-transform:rotate(-90deg);
transform:rotate(-90deg);
}
50%{
-webkit-transform:rotate(-180deg);
transform:rotate-(180deg);
}
75%{
-webkit-transform:rotate(-270deg);
transform:rotate(-270deg);
}
100%{
-webkit-transform:rotate(-360deg);
transform:rotate(-360deg);
}
}
タイムラインを25%に区切り、90度ずつ回転していくアニメーションが出来ました。
これで完成です。お疲れ様でした!
まとめ
CSSプログラミングはやっぱり難しいですが、やってみると新しいタグを発見したりすることが出来て楽しいです!
実際の案件では未だにIE6対応案件に追われていたりするので、使うことはまずないと思いますが、自分のブログで試すなら好き勝手出来るのでやっぱりブログやってて良かったーw
これからももっと面白いことが出来ないか探求し、チャレンジしてみようと思います。