今回のお題は、タブにより表示要素を切り替える。ただし、例によってこけおどしの3次元の回転を採り入れよう(サンプル1 ) 。コンテンツの画像と背景は、3面の直方体で組み立てた。タブをクリックすると、対応するコンテンツが垂直に回って正面に向く。「 3D Cube for tabbed content 」の3次元表現とCSSを参考に、コードは絞り込み、わかりやすく組み立て直した。
サンプル1 CSS3: 3D Cube for tabbed content
スタイルを与える前の素のHTMLコード
まず、HTMLドキュメントの<body>
要素には、つぎのようなHTMLのコードを加えた。CSSを与える前のHTMLドキュメントの表示と照らし合わせてもらうとよい(図1 ) 。タブのクリックで表示するコンテンツの<div>
要素(class
属性"tab-content")は、ラジオボタンの<input>
要素(type
属性"radio")で切り替える。もっとも、CSSでラジオボタンそのものは表示しない。<label>
要素にfor
属性でラジオボタンのid
属性を与えれば、ラベルもラジオボタンと同じクリックの対象になる。
<div class="container">
<label class="tab" for="tab-top">Child</label>
<label class="tab" for="tab-front">Adult</label>
<label class="tab" for="tab-bottom">Family</label>
<input type="radio" name="tabs" id="tab-top">
<input type="radio" name="tabs" id="tab-front">
<input type="radio" name="tabs" id="tab-bottom">
<div class="cube">
<div class="tab-content">
<div class="tab-image"><img src="images/pen01.png" alt=""></div>
<h1>Child</h1>
</div>
<div class="tab-content">
<div class="tab-image"><img src="images/pen02.png" alt=""></div>
<h1>Adult</h1>
</div>
<div class="tab-content">
<div class="tab-image"><img src="images/pen03.png" alt=""></div>
<h1>Family</h1>
</div>
</div>
</div>
図1 CSSを与える前のHTMLドキュメントの表示
タブとコンテンツのテキストのフォントには、Google FontsのRoboto を用いた。また例によって、ベンダープレフィックスを省くため、<script>
要素で-prefix-free を読み込んである(第1回の「ベンダープレフィックスと-prefix-free 」の項参照) 。
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,500" rel="stylesheet">
<style>
</style>
<script src="lib/prefixfree.min.js"></script>
コンテンツの直方体を静的に組み立てる
前掲のHTMLコードには、つぎのコード1 のスタイルを与える。アニメーションや3次元表現はまだ加えていない。文字と画像や背景、それらの色と大きさ、および配置を定めた。とくに3次元表現を加えると、試行錯誤で細かな位置調整をしなければならない。perspective
プロパティ(第4回の「要素にポインタを重ねたら水平軸で回す 」参照)は、ここで定めておかないと位置決めがしにくいため先に適切な値を与えている。
コード1 <style>要素に定めたコンテンツの静的なスタイル
.container {
perspective : 1200px;
width: 400px;
margin: 0 auto;
font-family: 'Roboto', sans-serif;
font-weight: 100;
color: white;
text-align: center;
}
input {
display: none;
}
.tab {
position: absolute;
width: 80px;
height: 70px;
left: 325px;
line-height: 70px;
font-weight: 300;
}
.tab:nth-child(1) {
background: mediumturquoise;
}
.tab:nth-child(2) {
top: 74px;
background: steelblue;
}
.tab:nth-child(3) {
top: 148px;
background: deeppink;
}
.cube {
margin: 60px 10px auto;
width: 300px;
}
.tab-content {
width: 300px;
height: 200px;
position: absolute;
}
.tab-content h1 {
font-size: 30px;
margin: 75px 115px;
text-align: center;
font-weight: 500;
}
.tab-content:nth-child(1) {
background: mediumturquoise;
}
.tab-content:nth-child(2) {
background: steelblue;
}
.tab-content:nth-child(3) {
background: deeppink;
}
.tab-image {
margin: 20px 30px;
position: absolute;
}
タブとコンテンツの位置は、アニメーションと3次元表現をおいてひとまず決まった。ただ、コンテンツとその中の画像が少し小さい(図2 ) 。これは3次元でコンテンツを直方体に組み立てるとき、正面を少し手前にもってくるので、その分余裕をとっているからだ。あとのふたつのコンテンツは、まだその裏に重なっている。
図2 タブとコンテンツの静的なスタイル
3つのコンテンツを直方体に組み上げてタブで垂直に回す
それでは、まだアニメーションはさせないまま、3次元でコンテンツの3つの<div>
要素(class
属性"tab-content")を直方体に組み上げよう。以下のようにtransform
プロパティの3次元変換で、上面は上に90度回して持ち上げる。底面は下に90度回して下ろす。そのため、transform-origin
プロパティで変形の原点は、それぞれ上端中央と下端中央に定めた。正面は奥行きを手前に定めたので、少し大きさが増した(図3 ) 。この段階での見え方は、OSやブラウザなどの環境によって少し違うかもしれない。なお、タイトルの<h1>
要素と画像の<div>
要素(class
属性"tab-image")にz-index
プロパティを与えたのは、画像の前にタイトルを出すためだ。
.tab-content h1 {
z-index: 1;
}
.tab-content:nth-child(1) {
transform : rotateX (90deg) translateY (-100px);
transform-origin : top center;
}
.tab-content:nth-child(2) {
transform : translateZ (100px);
}
.tab-content:nth-child(3) {
transform : rotateX (-90deg) translateY (100px);
transform-origin : bottom center;
}
.tab-image {
z-index: -1;
}
図3 コンテンツを3次元の直方体に組み上げた
これでコンテンツの3つの<div>
要素(class
属性"tab-content")は直方体に組み上がった。といっても、回してみなければ確かめられない。タブのクリックに対するインタラクションには、つぎのように~
結合子 を用いる。前述のとおり、タブの<label>
要素にfor
属性でラジオボタン(<input>
要素)のid
属性を与えたことにより、タブのクリックでラジオボタンが選ばれる。そのラジオボタンに応じて、直方体の<div>
要素(class
属性"")をx軸でそれぞれ異なる角度垂直に回した。あとは、直方体の<div>
要素にtransition
プロパティを加えればアニメーションになる。なお、transform-origin
プロパティで変形の原点を決め、transform-style
で3次元の変形を定めている。でき上がったCSSの記述は、以下のコード2 にまとめた。
.cube {
transform-origin : center 100px;
transform-style : preserve-3d;
transition : transform 0.5s ease-in;
}
#tab-top:checked ~ .cube {
transform : rotateX (-90deg);
}
#tab-front:checked ~ .cube {
transform : rotateX (0deg);
}
#tab-bottom:checked ~ .cube {
transform : rotateX (90deg);
}
コード2 タブのクリックで直方体のコンテンツを回す
.container {
perspective : 1200px;
width: 400px;
margin: 0 auto;
font-family: 'Roboto', sans-serif;
font-weight: 100;
color: white;
text-align: center;
}
input {
display: none;
}
.tab {
position: absolute;
width: 80px;
height: 70px;
left: 325px;
line-height: 70px;
font-weight: 300;
}
.tab:nth-child(1) {
background: mediumturquoise;
}
.tab:nth-child(2) {
top: 74px;
background: steelblue;
}
.tab:nth-child(3) {
top: 148px;
background: deeppink;
}
.cube {
margin: 60px 10px auto;
width: 300px;
transform-origin : center 100px;
transform-style : preserve-3d;
transition : transform 0.5s ease-in;
}
.tab-content {
width: 300px;
height: 200px;
position: absolute;
}
.tab-content h1 {
font-size: 30px;
margin: 75px 115px;
text-align: center;
font-weight: 500;
z-index: 1;
}
.tab-content:nth-child(1) {
transform : rotateX (90deg) translateY (-100px);
transform-origin : top center;
background: mediumturquoise;
}
.tab-content:nth-child(2) {
transform : translateZ (100px);
background: steelblue;
}
.tab-content:nth-child(3) {
transform : rotateX (-90deg) translateY (100px);
transform-origin : bottom center;
background: deeppink;
}
#tab-top:checked ~ .cube {
transform : rotateX (-90deg);
}
#tab-front:checked ~ .cube {
transform : rotateX (0deg);
}
#tab-bottom:checked ~ .cube {
transform : rotateX (90deg);
}
.tab-image {
margin: 20px 30px;
position: absolute;
z-index: -1;
}