今回のお題は、3つの立方体のマウスインタラクションだ。マウスポインタを重ねた立方体の色が変わり、手前にスライドする(サンプル1 ) 。実のところ、3次元の操作は加えていない。2次元の変換で立体風に見せているだけだ。「 3D cubes built and animated with CSS 」のデザインと表現をもとに、HTMLとCSSの組み立てはわかりやすく改めた。
サンプル1 CSS3: 3D Cubes
インタラクションを加える前の立方体の表現
まずは、インタラクションを加える前の静的な組み立てだ。<body>
要素にはつぎのように3つの立方体の<div>
要素(class
属性"cube")を加える。立方体は3つとも同じように上(class
属性"face-top")と左右(class
属性"face-left"と"face-right")の3面をもつ。ただ、上面(class
属性"face-top")だけ<div>
要素を入れ子にしている。左右の面は傾斜の変換だけ加えれば済むのに対し、上面はさらに回転しなければならないからだ。
<body>要素
<div class="container">
<div class="cube">
<div class="face-top"><div> <!-- 入れ子要素 -->
<h2>Top face</h2>
<p>The top face is nested in an extra div tag to give correct rotation</p>
</div></div>
<div class="face-left">
<h2>Left face</h2>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</p>
</div>
<div class="face-right">
<h2>Right face</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</p>
</div>
</div>
<div class="cube two">
<!-- 同上 -->
</div>
<div class="cube three">
<!-- 同上 -->
</div>
</div>
transform
プロパティによる変換を加える前、3つの立方体の面の要素はつぎの図1 のように位置や大きさ、色などが決めてある(後掲コード1 参照) 。
図1 変形を加える前の3つの立方体の面
立方体それぞれの3つの面は、つぎのようにtransform
プロパティで変換する。基本は傾斜のskewY()
関数 だ。さらに、上面はscaleY()
関数 により縦横比を整えたうえで、前述のとおりrotate()
関数 で親要素(class
属性"face-top")を回転した。これで、2次元の変換により、3つの面が立方体として表現できる(図2 ) 。回転や傾斜が組み合わさる上面のような場合は、こうして要素を入れ子にすると、分けて調整がしやすい。
<style>要素
.face-left {
transform : skewY (30deg);
}
.face-right {
transform : skewY (-30deg);
}
.face-top div {
transform : skewY (-30deg) scaleY (1.16);
}
.face-top {
transform : rotate (60deg);
}
図2 3面の要素を変換して組み上がった3つの立方体
インタラクションを加える前の<body>
要素とCSSの定めは、つぎのコード1 にまとめた。実際につくってみると、細かく位置や大きさを合わせるのに少しばかり手間がかかる。面は左から、立方体は右奥から決めていった。コードそのものはとくにむずかしいところはないだろう。なお、いつものように-prefix-freeをCDN から読み込んである(第16回の「水平に並べた要素に静的なスタイルを割り当てる 」参照)。
コード1 インタラクションを加える前の立方体のHTMLコードとスタイル
<body>要素
<div class="container">
<div class="cube">
<div class="face-top"><div>
<h2>Top face</h2>
<p>The top face is nested in an extra div tag to give correct rotation</p>
</div></div>
<div class="face-left">
<h2>Left face</h2>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</p>
</div>
<div class="face-right">
<h2>Right face</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</p>
</div>
</div>
<div class="cube two">
<div class="face-top"><div>
<h2>Top face</h2>
<p>The top face is nested in an extra div tag to give correct rotation</p>
</div></div>
<div class="face-left">
<h2>Left face</h2>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</p>
</div>
<div class="face-right">
<h2>Right face</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</p>
</div>
</div>
<div class="cube three">
<div class="face-top"><div>
<h2>Top face</h2>
<p>The top face is nested in an extra div tag to give correct rotation</p>
</div></div>
<div class="face-left">
<h2>Left face</h2>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum</p>
</div>
<div class="face-right">
<h2>Right face</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod</p>
</div>
</div>
</div>
<style>要素
body {
line-height: 1.5em;
color: #666;
background: #f1ebe2;
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-weight: 200;
}
p, h2 {
margin: 0;
font-size: 100%;
}
.container {
min-height: 500px;
}
.cube {
position: absolute;
left: 50%;
top: 150px;
}
.cube p {
line-height: 14px;
font-size: 12px;
margin-bottom: 24px;
}
.cube h2 {
font-weight: bold;
}
.cube.two {
top: 213px;
left: 48%;
margin-left: -100px;
}
.cube.three {
top: 276px;
left: 46%;
margin-left: -200px;
}
.face-right,
.face-left,
.face-top div {
padding: 10px;
width: 90px;
height: 90px;
}
.face-right,
.face-left,
.face-top {
position: absolute;
}
.face-left {
transform : skewY (30deg);
background-color: #ccc;
}
.face-right {
transform : skewY (-30deg);
background-color: #ddd;
left: 109px;
}
.face-top div {
transform : skewY (-30deg) scaleY (1.16);
background-color: #eee;
font-size: 0.862em;
}
.face-top {
transform : rotate (60deg);
top: -86px;
left: 55px;
}
マウスポインタが重なった立方体の色を変える
立方体にマウスポインタが重なったら(:hover
擬似クラス) 、3つの面の色をつぎのように変える。さらに、ポインタの乗った面は色を濃くしている(図3 ) 。
<style>要素
.cube:hover .face-right,
.cube:hover .face-left,
.cube:hover .face-top div {
background-color: #ffc;
}
.cube:hover .face-right:hover,
.cube:hover .face-left:hover,
.cube:hover .face-top:hover div {
background-color: #ffa;
}
図3 立方体にマウスポインタを重ねると色が変わる
マウスポインタが重なった立方体をスライドさせる
マウスポインタが重なった立方体はスライドさせよう。CSSは、つぎのようにtransform
プロパティにtranslate()
関数 を定めるだけだ。とはいえ、これもピクセル単位で細かく調整しなければならない。transition
プロパティ には、パラメータとして変化させたいプロパティ(transform
)を加えた。いつものように省けば、デフォルトはすべて(all
)とされるので、それでも差し支えはない。タイミング関数は、機械的な線形のlinear
を選んだ。
<style>要素
.cube {
transition : transform 1s linear;
}
.cube:hover {
transform : translate (108px, 64px);
}
これで3つの立方体が組み立てられ、マウスポインタを重ねると色が変わってスライドする(図4 ) 。CSSの定めは、以下のコード2 にまとめた。はじめの見た目より簡単に感じたのではないだろうか。3次元でなく2次元の変換を使ったためだ。だが、大きさや角度を変えたりすると、ピクセル単位の調整に少し手間どるかもしれない。さて、昨年1月からはじまった本連載は、今回で幕を閉じる。JavaScriptは使わず、CSSだけでさまざまなインターフェイス表現をつくってきた。その可能性を少しでも感じていただけたなら幸いである。
図4 立方体にマウスポインタを重ねた立方体の色が変わってスライドする
コード2 ポインタを重ねた立方体の色が変わってスライドする
<style>要素
body {
line-height: 1.5em;
color: #666;
background: #f1ebe2;
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-weight: 200;
}
p, h2 {
margin: 0;
font-size: 100%;
}
.container {
min-height: 500px;
}
.cube {
position: absolute;
left: 50%;
top: 150px;
}
.cube p {
line-height: 14px;
font-size: 12px;
margin-bottom: 24px;
}
.cube h2 {
font-weight: bold;
}
.cube.two {
top: 213px;
left: 48%;
margin-left: -100px;
}
.cube.three {
top: 276px;
left: 46%;
margin-left: -200px;
}
.face-right,
.face-left,
.face-top div {
padding: 10px;
width: 90px;
height: 90px;
}
.face-right,
.face-left,
.face-top {
position: absolute;
}
.cube:hover .face-right,
.cube:hover .face-left,
.cube:hover .face-top div {
background-color: #ffc;
}
.cube:hover .face-right:hover,
.cube:hover .face-left:hover,
.cube:hover .face-top:hover div {
background-color: #ffa;
}
.face-left {
transform : skewY (30deg);
background-color: #ccc;
}
.face-right {
transform : skewY (-30deg);
background-color: #ddd;
left: 109px;
}
.face-top div {
transform : skewY (-30deg) scaleY (1.16);
background-color: #eee;
font-size: 0.862em;
}
.face-top {
transform : rotate (60deg);
top: -86px;
left: 55px;
}
.cube {
transition : transform 1s linear;
}
.cube:hover {
transform : translate (108px, 64px);
}