Lopan.jp

動くCSSのためのメモ。

動くCSSのためのメモ

なんだかCSSでできる事がどんどん増えてきましたね。以前はJavaScriptを使って実装していた動くコンテンツも、CSSだけで表現されてるのをよく見ます。そんなわけで、ここいらで、CSSで動かすエフェクトについて、まとめてみたいと思います:)。

※この記事を書いてる時点の最新ブラウザは以下の通り。また、記事の内容は、PCでの閲覧を想定してます。

  • Microsoft Internet Explorer 11.0
  • Mozilla Firefox 28.0
  • Google Chrome 34.0
  • Apple Safari 7.0

マウスオーバー(ホバー)エフェクト

ボタンや画像にカーソルを乗せた時の反応って大事ですよね。
リンクするエリアにカーソルを合わせた時に、カーソルが指のアイコンに変わったり、テキストの色が変わったりすれば、カーソルが乗ったという事が認識しやすくなります:)。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - マウスオーバーエフェクト</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="txt">こちらは<a href="">テキストリンク</a>です。</p>
</div>
</body>
</html>
body {
  background: url(../img/bg.png);
  font-family: "Heiti SC";
}

a {
  color: lightSeaGreen;
}

a:hover {
  color: indianRed;
  text-decoration: none;
}

.txt {
  margin: 50px 0 0;
  text-align: center;
}

:hoverを使ってスタイルを指定しておけば、カーソルが乗った時には、そのスタイルが適用されます。
けどそれだけだと、カチッと切り替わるだけ。

フェードでふわっと切り替わる

サイトの雰囲気にもよるけれど、もちょっとだけ柔らかい印象にしたいなって時には、ふわっとするとよいかもです。文字の色が切り替わるスピードと、下線が消えてくスピードを調整することで、ふわっとした感じになります:)。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - フェードでふわっと切り替わる</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="txt">こちらは<a href="">ふわっとリンク</a>です。</p>
</div>
</body>
</html>
/* 略 */

.txt a {
  border-bottom: 1px solid rgba(32,178,170,1);
  text-decoration: none;
  transition: border-color 0.3s, color 0.3s;
}

.txt a:hover {
  border-color: rgba(205,92,92,0);
}

切り替わるスピードを調整するにはtransitionプロパティを使います!
下記のように書くと、a要素でのcolorプロパティの値の変化の仕方を指定することができます。下記は「0.3秒かけていい感じで切り替わる」という指定。

a {
  transition: color 0.3s ease 0s;
}

transitionの値は左から順に、propertydurationtiming-functiondelayを表してて、上の例を個別に指定するなら、下記のようにも書けます。

a {
  transition-property: color;
  transition-duration: 0.3s;
  transition-timing-function: ease;
  transition-delay: 0s;
}

初期値を省略して、下記だけでもよいです:)。

.txt a {
  transition: color 0.3s;
}

transitionの4つのプロパティは、それぞれ以下の役割と、初期値を持ってます。


transition-property
効果を適用したいプロパティ名を指定します。初期値は「all」すべてのプロパティに適用します。

transitionを適用できるプロパティは、プロパティの値を数値で表現できるものすべて。colorの値に使われるredlightSeaGreenなどの色名も、RGBなどの数値で表すことができるのでちゃんと適用されます。

transition-duration
変化の開始から完了までにかかる時間を、秒数で指定します。初期値は「0s」カチッと切り替わります。
1秒(1000ミリ秒) = 1s1000ms
transition-timing-function
変化の仕方(イージング)を指定します。初期値は「ease」ゆっくり始まってゆっくり終わる、一番いい感じのイージングです。
他にlinearease-inease-outease-in-outが用意されてます。
cubic-bezier関数を使えばオリジナルなイージングを作ることもできます。詳しくはこちらの記事を参照のこと。
transition-delay
変化を開始するまでの待ち時間を、秒数で指定します。初期値は「0s」すぐに変化を開始します。
マイナスの値を指定すると、その分進んだ時点から変化を開始します。詳しくは後述

下線も同じようにtext-decoration-colortransitionさせたいところですが、text-decoration-colorプロパティはまだ対応ブラウザが少ないみたいなので、下線はtext-decorationじゃなくてborder-bottomで表示することにしました(2014年4月現在)
border-colorを、カーソルが乗る前は「rgba(32,178,170,1)(みどり)」、カーソルが乗った時は「rgba(105,92,92,0)(あかい透明)」となるように指定しました。
文字色と下線の色、ひとつの要素内で複数のプロパティをtransitionさせるには、transitionの値を、プロパティごとに「,(カンマ)」区切りで続けて書きます。ここでは、前述のtransitionborder-colorを追記しました。

.txt a {
  border-bottom: 1px solid rgba(32,178,170,1);
  text-decoration: none;
  transition: color 0.3s, border-color 0.3s;
}
.txt a:hover {
  border-color: rgba(105,92,92,0);
}

#20b2aaという16進数の値から、rgba(32,178,170,1)みたいなRGB値に変換するのには下記ページを利用しましたよ;D。

16進数形式をRGB,RGBAに変換するだけ - jsdo.it

目次に戻る

画像ボタンもふわっとする

画像ボタンの構造

画像ボタンやバナーの場合は、<img>を包む<a>の背景画像にマウスオーバー時の画像を指定して、<img>のopacityを徐々に変化させれば、ふわっと切り替わったように見えます:)。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 画像ボタンもふわっとする</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="bnr"><a><img src="http://placehold.it/300x100/20b2aa/ffffff&text=banner"></a></p>
</div>
</body>
</html>
.bnr a {
  display: inline-block;
  background: url(http://placehold.it/300x100/cd5c5c/ffffff&text=banana) no-repeat;
  background-size: cover;
}

.bnr a img {
  vertical-align: middle;
  transition: opacity 0.3s;
}

.bnr a:hover img {
  opacity: 0;
}

ふわっとカチッする

CSSで作ったボタンなら、background-colorbox-shadowなど、いじれるプロパティがいっぱいあるので、ふわっとさせ甲斐がありますねー!まとめてtransitionを指定すれば、より魅力的な変化を表現できます。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - ふわっとカチッする</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="btn"><a>ボタンでございます</a></p>
</div>
</body>
</html>
.btn a {
  display: block;
  cursor: pointer;
  width: 300px;
  margin: 0 auto;
  padding: 20px;
  color: #fff;
  text-align: center;
  text-decoration: none;
  background-color: #20b2aa;
  border-radius: 5px;
  box-shadow: 0 6px 0 #047c71, 0 12px 0 rgba(0,0,0,0.2);
  -webkit-transition: color 0.3s, background-color 0.3s, box-shadow 0.3s, -webkit-transform 0.3s;
  transition: color 0.3s, background-color 0.3s, box-shadow 0.3s, transform 0.3s;
}

.btn a:hover {
  background-color: #3cc4bd;
  box-shadow: 0 3px 0 #12978d, 0 6px 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(3px);
  transform: translateY(3px);
}

.btn a:active {
  color: #ddd;
  background-color: #12978d;
  box-shadow: 0 0 0 #047c71, 0 0 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(6px);
  transform: translateY(6px);
  transition-duration: 0.1s;
}

ボタンの仕組み

上の例では、ボタンの地色background-color、文字色color、側面と影の色と縦幅box-shadow、ボタンの上下位置transformを、徐々に変化させてます。

また、カーソルを乗せた時にはゆったり動いてますが、マウスを押下した時にはちょっと早めに動くようにしてます。ここでは、durationの値を、下記のように変えています。

.btn a {
  /* 略 */
  transition: color 0.3s, background-color 0.3s, box-shadow 0.3s, transform 0.3s;
  -webkit-transition: color 0.3s, background-color 0.3s, box-shadow 0.3s, -webkit-transform 0.3s;
}
.btn a:active {
  transition-duration: 0.1s;
}

<a>に対して指定したtransitionの値を、active時にtransition-durationの値のみ上書きしてるんですねー。これだけで、マウスを押下した時は0.1秒で変化して、それ以外のときは0.3秒で変化するようになります。

目次に戻る

発光する

ピカッとしっぱなし

カーソルを乗せた時に一瞬ピカッとか、キラッとか、発光するボタンが作りたいという時、transitionだと「一瞬ピカッとする」まではできますが、そこからもとの明るさに戻るっていうのができません…。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 発光するボタン</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="btn"><a>発光するボタンでございます</a></p>
</div>
</body>
</html>
/* 略 */

.btn a:hover {
  background-color: #96e9e6;
  box-shadow: 0 3px 0 #12978d, 0 6px 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(3px);
  transform: translateY(3px);
}

.btn a:active {
  color: #ddd;
  background-color: #12978d;
  box-shadow: 0 0 0 #047c71, 0 0 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(6px);
  transform: translateY(6px);
  transition-duration: 0.1s;
}

こんな時にはanimationというプロパティが使えます。ピカッと感が出ましたね!

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 発光するボタン</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p class="btn"><a>発光するボタンでございます</a></p>
</div>
</body>
</html>
/* 略 */

.btn a:hover {
  background-color: #20b2aa;
  box-shadow: 0 3px 0 #12978d, 0 6px 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(3px);
  transform: translateY(3px);
  -webkit-animation: flash 1s;
  animation: flash 1s;
}

.btn a:active {
  color: #ddd;
  background-color: #12978d;
  box-shadow: 0 0 0 #047c71, 0 0 0px rgba(0,0,0,0.2);
  -webkit-transform: translateY(6px);
  transform: translateY(6px);
  transition-duration: 0.1s;
}

@-webkit-keyframes flash {
  0% { background-color: #20b2aa; }
  10% { background-color: #96e9e6; }
  100% { background-color: #20b2aa; }
}

@keyframes flash {
  0% { background-color: #20b2aa; }
  10% { background-color: #96e9e6; }
  100% { background-color: #20b2aa; }
}

animationプロパティ

まずは1〜4行めのanimationプロパティについて。

.flash a:hover {
  background-color: #20b2aa;
  animation: flash 1s;
  -webkit-animation: flash 1s;
}

animationプロパティにはnamedurationtiming-functiondelayiteration-countdirectionplay-statefill-modeの8つの値が指定できます。durationtiming-functiondelaytransitionにもありましたね。

それぞれ、以下の役割と初期値を持ってます。


animation-name
適用したいアニメーション名を指定します。初期値は「none」何も指定されてません。
詳しくは@keyframesルールの項を参照。
animation-duration
アニメーションの一回分の長さを、秒数で指定します。初期値は「0s」アニメーションしません。
animation-timing-function
アニメーションの仕方(イージング)を指定します。初期値は「easetransitionと同様)
animation-delay
アニメーションを開始するまでの待ち時間を、秒数で指定します。初期値は「0s」すぐにアニメーションを開始します。
マイナスの値を指定すると、その分進んだ時点からアニメーションを開始しますtransitionと同様)
animation-iteration-count
アニメーションを繰り返す回数を指定します。初期値は「1」1回だけ再生します。
infinite(無限)」という指定もできます。
animation-direction
animation-iteration-countで2回以上に指定した場合に、アニメーションを折り返すか、始めに戻すかを指定します。初期値は「normal」同じアニメーションを繰り返します。
alternate」とすると、偶数回めのアニメーションが逆再生します。
reverse」とすると、逆再生が繰り返され、「alternate-reverse」とすると、奇数回めのアニメーションが逆再生になります。
animation-play-state
アニメーションを再生させたり一時停止させたりできます。初期値は「running」再生する状態です。
paused」と指定すると、一時停止の状態になります。
animation-fill-mode
アニメーションする前と後に、適用するスタイルを指定します。初期値は「none」アニメーションしてるとき以外に、スタイルは適用されません。詳しくは後述

animationプロパティにまとめて指定する場合は、半角スペースを空けて、下記みたく連ねて書くこともできます:)。

p {
  animation: name ease-in-out 2s 1s 5 alternate running forwards;
}

順番は自由だけれど、ひとつだけ、durationdelayの順番だけは「durationが先」と決まってるので注意です。
上記の場合なら、1秒待ってから2秒かけてアニメーションすることになります。

@keyframesルール

アニメーション」は、別途@keyframesルールという、キーフレームを定義するための特別な構文を使って用意します。ここで定義したアニメーション名が、animation-nameで指定する値として使えるって寸法です。

@keyframes flash {
  0% { background-color: #20b2aa; }
  10% { background-color: #96e9e6; }
  100% { background-color: #20b2aa; }
}

@-webkit-keyframes flash {
  0% { background-color: #20b2aa; }
  10% { background-color: #96e9e6; }
  100% { background-color: #20b2aa; }
}

@keyframesに付くベンダープレフィックスは、「頭」じゃなくて、「@」の後なのでご注意。

ピカッとするキーフレーム

@keyframesでは、アニメーションの開始から完了までをパーセントで区切って、各時点でのスタイルを指定していくという方法で、アニメーションを定義します。
開始時点が0%、完了時点が100%で、その間は任意の時点を追加できます。

ここでは、開始時点では元の色のままで、開始から10%進んだ時点で明るくなって、完了時点でまた元の色に戻る、というアニメーションを「flash」という名前で定義しました。
animation: flash 1s;」とは、このflashを1秒かけて再生する、ということです。
なので、この場合10%時点は0.1秒進んだ時点ということになりますね。

目次に戻る

目次に戻る

アニメーションの前後に適用されるスタイルanimation-fill-modeについて

初期値noneの状態だと、アニメーション完了後には、もともとその要素に指定していたスタイルが適用されます。
下のサンプルでは、background-colorに緑色が指定してあるp要素に、カーソルを乗せると1秒かけて赤色にグラデーションするgradationというアニメーションを適用しています。

p {
  background-color: lightSeaGreen;
}
p:hover {
  animation: gradation 1s;
}
@keyframes gradation {
  0% { background-color: lightSeaGreen; }
  100% { background-color: indianRed; }
}

カーソルを乗せてみると、アニメーションが終わった瞬間、緑色に戻っちゃいました…!
これを回避するには、下記のように:hoverに別途、完了後のスタイルを指定すればよいです。

p:hover {
  background-color: indianRed;
  animation: gradation 1s;
}

けれど、animation-delayでアニメーションの開始を遅らせた場合、まず:hoverで指定したスタイルが適用されてから、アニメーションが開始するため、変なんなっちゃいます…。

p:hover {
  background-color: indianRed;
  animation: gradation 1s .5s;
}

そんな時に使えるのがanimation-fill-modeプロパティ;D!
値に「backwards」と指定すれば、animation-delayでアニメーションが始まるまで待ってる間も、アニメーション開始時のスタイルを優先して適用してくれます。

p:hover {
  background-color: indianRed;
  animation: gradation 1s .5s;
  animation-fill-mode: backwards;
}

forwards」はその逆で、アニメーション完了時のスタイルが、アニメーション完了後も適用され続けます。
この指定をすれば:hoverに、別途、完了後のスタイルを指定する必要がなくなりますね:D。

p:hover {
  animation: gradation 1s .5s;
  animation-fill-mode: forwards;
}

both」はその両方。@keyframesで指定したスタイルが優先して適用されるようになります。
下のサンプルでは、p要素のbackground-colorをグレーに指定してますが、カーソルを乗せた時には、緑色から赤色へのグラデーションが再生されます。

p {
  background-color: gainsboro;
}
p:hover {
  animation: gradation 1s .5s;
  animation-fill-mode: both;
}

animation-fill-modeの値の役割をまとめてみると下図みたいな感じです!
使いどころに合わせて、効率的に使いたいですねー;)。

animation-fill-modeのまとめ

目次に戻る

詳細はあとから表示する

最初は表示されてないんだけど、サムネイル画像の上にカーソルを乗せると、その画像に関する情報が表示されるような、そんなUIよくありますね。
ごちゃごちゃした情報は見たい時だけ、最初の見た目が煩雑にならずにシンプルなデザインにできるので、フラットなデザインとも相性がいいんですよね:)。
下のサンプルみたいなの、よく見る気がします:D。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 詳細はあとから表示する</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <ul>
    <li class="type1">
      <img src="http://placehold.it/200x180/20b2aa/ffffff&text=image">
      <dl>
        <dt>Placehold.it</dt>
        <dd>この画像は「Placehold.it」で生成されるダミー画像を使用しています。</dd>
        <dd><a href="http://www.placehold.it/" target="_blank">Placehold.it</a></dd>
        </dl>
    </li>
    <li class="type2">
      <img src="http://placehold.it/200x180/20b2aa/ffffff&text=image">
      <dl>
        <dt>Placehold.it</dt>
        <dd>「http://placehold.it/[SIZE]/[BGCOLOR]/[TEXTCOLOR]&text=[DUMMYTEXT]」というようなURLで、任意のダミー画像を生成してくれてとっても便利。</dd>
        <dd><a href="http://www.placehold.it/" target="_blank">Placehold.it</a></dd>
        </dl>
    </li>
    <li class="type3">
      <img src="http://placehold.it/200x180/20b2aa/ffffff&text=image">
      <dl>
        <dt>Placehold.it</dt>
        <dd>このダミー画像の場合は「http://placehold.it/200x180/20b2aa/ffffff&text=image」という具合。</dd>
        <dd><a href="http://www.placehold.it/" target="_blank">Placehold.it</a></dd>
      </dl>
    </li>
  </ul>
</div>
</body>
</html>
body {
  background: url(../img/bg.png);
  font-family: "Heiti SC";
}

a {
  color: lightSeaGreen;
}

a:hover {
  color: indianRed;
  text-decoration: none;
}

ul {
  list-style: none;
  top: 0;
  height: 180px;
  margin: 0;
  padding: 0;
  text-align: center;
}

ul li,
ul li dl {
  width: 200px;
  height: 180px;
}

ul {
  letter-spacing: -1em;
}

ul li {
  display: inline-block;
  position: relative;
  overflow: hidden;
  margin: 0 5px;
  letter-spacing: 0;
}

ul dl {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  position: absolute;
  top: 0;
  margin: 0;
  padding: 20px 25px;
  color: #fff;
  background: rgba(205,92,92,.9);
}

ul dl dt {
  margin-bottom: 0.3em;
}

ul dl dd {
  margin: 0;
  font-size: 10px;
  line-height: 1.6;
  text-align: justify;
  word-break: break-all;
}

ul dl dd:last-of-type {
  margin-top: 10px;
  text-align: right;
}

ul a {
  padding: 0.3em 0.5em;
  background-color: #fff;
}

/* type1 */

.type1 dl {
  opacity: 0;
  -webkit-transform: translateY(100%);
  transform: translateY(100%);
  -webkit-transition: opacity 0.6s, -webkit-transform 0.6s;
  transition: opacity 0.6s, transform 0.6s;
}

.type1:hover dl {
  opacity: 1;
  -webkit-transform: translateY(0);
  transform: translateY(0);
}

/* type2 */

.type2 {
  overflow: visible;
  -webkit-perspective: 1000px;
  perspective: 1000px;
}

.type2 img,
.type2 dl {
  -webkit-transition: opacity 0.6s, -webkit-transform 0.6s;
  transition: opacity 0.6s, transform 0.6s;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.type2:hover img {
  -webkit-transform: rotateX(180deg);
  transform: rotateX(180deg);
}

.type2 dl {
  background-color: #cd5c5c;
  -webkit-transform: rotateX(-180deg);
  transform: rotateX(-180deg);
}

.type2:hover dl {
  -webkit-transform: rotateX(0);
  transform: rotateX(0);
}

/* type3 */

.type3 dl {
  background-color: transparent;
}

.type3 dl dt,
.type3 dl dd {
  position: relative;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.3s;
}

.type3:hover dl dt,
.type3:hover dl dd {
  opacity: 1;
  transition-delay: 0.3s;
}

.type3 dl::before,
.type3 dl::after {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 100px;
  height: 180px;
  background: #cd5c5c;
  opacity: 0;
  -webkit-transition: opacity 0.6s, -webkit-transform 0.6s;
  transition: opacity 0.6s, transform 0.6s;
}

.type3:hover dl::before,
.type3:hover dl::after {
  opacity: 0.9;
  transition-duration: 0.3s;
}

.type3 dl::before {
  -webkit-transform: translateX(-175px) skew(-30deg);
  transform: translateX(-175px) skew(-30deg);
}

.type3 dl::after {
  -webkit-transform: translateX(275px) skew(-30deg);
  transform: translateX(275px) skew(-30deg);
}

.type3:hover dl::before {
  -webkit-transform: translateX(0) skew(0);
  transform: translateX(0) skew(0);
}

.type3:hover dl::after {
  -webkit-transform: translateX(100px) skew(0);
  transform: translateX(100px) skew(0);
}

そんなわけで、左から順に仕組みメモです。
サムネイル画像部分のHTMLはそれぞれ下記のようになってます。

<ul class="details">
  <li>
  <img src="http://placehold.it/200x180/20b2aa/ffffff&text=image">
  <dl>
    <dt>Placehold.it</dt>
    <dd>この画像は「Placehold.it」で生成されるダミー画像を使用しています。</dd>
    <dd><a href="http://www.placehold.it/" target="_blank">Placehold.it</a></dd>
  </dl>
  </li>
  <!-- 略 -->
</ul>

<li>の中に、img要素(サムネイル画像)と、dl要素(詳細情報)が並んでる状態ですね。

下からニュッと出る

普段は画像の下に隠れてる

詳しい情報は画像の下に隠しておいて、カーソルが乗ったら下からスッとスライドする仕組み。

まずはli要素にposition: relativeを指定。これで、li要素が、その小要素を絶対配置するときの基準になります。dl要素にposition: absoluteを指定しtop: 0とすれば、img要素の上に重なった状態で配置されます。

dl要素の上下のスライドはtransformプロパティtranslateで移動させてます。
最初の状態では、dl要素にtranslateY(100%)と指定。これで、その要素の高さ分、下方向に移動します。カーソルが乗ったときはtranslateY(0)として、元の位置に戻します。

目次に戻る

くるんと裏返る

まるで一枚のカードみたく、写真の裏面に詳細情報が載ってるような表現です。

上述と同じように、position: absoluteでimg要素とdl要素を重ねて配置。
最初の状態では、dl要素は裏返ってる状態なので、rotateX()を使ってX軸を中心に上下に回転させておき、カーソルが乗った時に、img要素とdl要素を同時に+180°回転させてます。

.type2 dl {
  background-color: #cd5c5c;
  transform: rotateX(-180deg);
  -webkit-transform: rotateX(-180deg);
}

.type2:hover img {
  transform: rotateX(180deg);
  -webkit-transform: rotateX(180deg);
}

.type2:hover dl {
  transform: rotateX(0);
  -webkit-transform: rotateX(0);
}

カーソルが乗った時に<img><dl>を、同じタイミングで回転させる事で、一枚のカードのように見せてるんですねー。

普段は画像の裏側に隠れてる

裏返る演出で大事なのがbackface-visibilityというプロパティ。このプロパティにhiddenと指定した要素は、裏返った時に不可視状態になります。

backface-visibilityで裏側だと判断されるのは、transformプロパティのrotateX()rotateY()で、90°以上回転した時。下図は、左が「表面の要素のみ」真ん中が「裏面の要素のみ」になってます。表面が裏返ると不可視状態になり、その瞬間に裏面が可視状態になってるのがよくわかりますねー。

この指定がないと下図のように、裏側も丸見え、というか、裏面が表面の上に乗っちゃってます。

backface-visibilityについて詳しくは下記サイトを参照のこと。

backface-visibility - CSS | MDN

あと、回転する要素の親要素には、perspectiveプロパティを指定してます。

.hover .details .type2 {
  perspective: 1000px;
  -webkit-perspective: 1000px;
}

perspectiveは、遠近感を指定することができるプロパティ。指定する値は、その要素を見ている視点の位置を表してて、ここでは、1000px離れた所で見てる感じになります。

100px離れたとこからみてる人と、1000px離れたとこからみてる人

つまり、この値が小さい(近い)ほど遠近感が強く、大きい(遠い)ほど遠近感が緩くなるってことですね:)。
この指定がないと、立体感がなくなって、裏返ったのか縦に縮んだのかわからなくなっちゃいます…。

perspectiveについては下記記事が詳しいです。

HTML5 × CSS3 × jQueryを真面目に勉強 – #10.1 CSS3 Transforms(3D) | Developers.IO(2012.12.27)

目次に戻る

左右から背景が出てくる

パネル状の背景が左右から入ってきて、カーテンを閉めるように中央でピッタリ閉じられると、詳細情報がフェードインしてきます。

左右から出てくる背景は::before疑似要素::after疑似要素で表示させてます。
疑似要素を使うと、指定した要素の中に、新たに要素を追加できちゃいます。
ただし、要素を追加するにはもうひとつ、contentプロパティというのも使わなきゃいけません。下記みたく書きます。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - ::beforeと::afterについて</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <p> / </p>
</div>
</body>
</html>
p {
  margin: 50px 0 0;
  text-align: center;
}

p::before {
  content: "::beforeの疑似ですよ";
}

p::after {
  content: "::afterの疑似ですよ";
}

HTMLには「 / 」と出力するだけのp要素がひとつ、なのにPREVIEWを見るとテキストが表示されてますね!
こんな感じで、疑似要素とcontentプロパティを使えば、HTMLで書かれた要素とは別に、CSSで新たに要素を作れちゃうんです(擬似的に!):D。
::beforeは、指定した要素の開始タグの直後に、::afterは、指定した要素の閉じタグの直前に、要素を追加します。※Chromeとかで「要素の検証」をしてみても確認できますよ;)。

左右から出てくる背景は、dl要素内に、::before::afterで2つの要素を追加してたわけです(擬似的に!:D)

疑似要素で作る疑似背景

他にももっといろんなプロパティと組み合わせればトリッキーな演出だってできちゃいます。
下記サイトでいろんなエフェクトが紹介されてます。どれも素敵ですねーXD!

Circle Hover Effects with CSS Transitions | Codrops(2012.8.8)

目次に戻る

タブコンテンツ

タブボタンをクリックすることで、表示する内容を切り替えるタブコンテンツも、CSSだけでできちゃう時代です:)。
CSSで切り替えを行うためには、ちょっとした下ごしらえが必要なので、まずはその仕組みについてまとめてみます。

CSSで切り替える仕組み

そんなわけで、下の仕組みがよくわかるサンプルのソースコードを見ながら要点を解説です。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - CSSで切り替える仕組みがよく分かるサンプル</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" name="switch" id="tab-1" checked>
  <input type="radio" name="switch" id="tab-2">
  <input type="radio" name="switch" id="tab-3">
  <input type="radio" name="switch" id="tab-4">
  <input type="radio" name="switch" id="tab-5">
  <ul class="tabBtn">
    <li><label for="tab-1">タブ1</label></li>
    <li><label for="tab-2">タブ2</label></li>
    <li><label for="tab-3">タブ3</label></li>
    <li><label for="tab-4">タブ4</label></li>
    <li><label for="tab-5">タブ5</label></li>
  </ul>
  <div class="tabContents">
    <section>タブコンテンツ1</section>
    <section>タブコンテンツ2</section>
    <section>タブコンテンツ3</section>
    <section>タブコンテンツ4</section>
    <section>タブコンテンツ5</section>
  </div>
</div>
</body>
</html>
#wrapper {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

/* :::::: button :::::: */

.tabBtn {
  display: table;
  width: 100%;
  margin: 0 0 1px;
  padding: 0;
}

.tabBtn li {
  display: table-cell;
  width: 20%;
  border-right: 1px solid #fff;
  background-color: #20b2aa;
  text-align: center;
  vertical-align: middle;
}

.tabBtn li:last-child {
  border-right: 0;
}

.tabBtn li label {
  display: block;
  cursor: pointer;
  padding: 10px 0;
  color: #fff;
  transition: background-color .3s;
}

.tabBtn li label:hover {
  background-color: rgba(205,92,92,.5);
}

/* :::::: mechanism :::::: */

.tabContents section {
  opacity: 0.1;
  text-align: center;
  transition: opacity 0.3s;
}

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

HTML

まずはタブボタンと、それに付随するコンテンツを設置します。

<ul class="tabBtn">
  <li><label for="tab-1">タブ1</label></li>
  <li><label for="tab-2">タブ2</label></li>
  <li><label for="tab-3">タブ3</label></li>
  <li><label for="tab-4">タブ4</label></li>
  <li><label for="tab-5">タブ5</label></li>
</ul>
<div class="tabContents">
  <section>タブコンテンツ1</section>
  <section>タブコンテンツ2</section>
  <section>タブコンテンツ3</section>
  <section>タブコンテンツ4</section>
  <section>タブコンテンツ5</section>
</div>

タブボタンに<label>を使うのがポイント:)。
次に、コンテンツを切り替えるスイッチの役割となる<input type="radio">(ラジオボタン)を5つ、上記ソースコードの手前に設置します。

<input type="radio" name="switch" id="tab-1" checked>
<input type="radio" name="switch" id="tab-2">
<input type="radio" name="switch" id="tab-3">
<input type="radio" name="switch" id="tab-4">
<input type="radio" name="switch" id="tab-5">

name属性の値を統一して、ラジオボタンをひとつのグループに(ここではswitchに)。それから<input>id属性の値を、<label>for属性の値と同じにして、タブボタンとラジオボタンを関連付けます。
一番めの<input>にはcheckedを付けて、初期状態では「タブコンテンツ1」が開いているようにしておきます。
以上で下ごしらえ完了!

CSS

そして、以降の指定が、コンテンツの表示/非表示を切り替えるための仕組みの部分になります。
まずは、タブボタンを切り替えた時の、ボタンのスタイルを指定します。

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

一番上の行を分解して見ると。

#tab-1:checked
チェックされている「id属性がtab-1の要素」
~ (チルダ)
それ以降にある同じ階層の要素(兄弟要素)
.tabBtn li [for="tab-1"]
class="tabBtn"の要素の中の「for属性がtab-1の要素」

つまり、チェックされている「id属性がtab-1の要素」と同じ階層にあるclass="tabBtn"の要素の中の「for属性がtab-1の要素」background-color: #cd5c5cを指定する(背景色を赤くする)って事になります。
要するに「1つめのラジオボタンがチェックされてる時は、1つめのタブボタンを赤くする」ということ。

1つめのタジオボタンがcheckedの時は、1つめのラブボタンの色が変わる

タブボタンを切り替えた時のコンテンツのスタイルもタブボタンと同じ要領で、チェックされている「id属性がtab-1の要素」と同じ階層にあるclass="tabContents"の要素の中の「ひとつめのsection要素」というように、タブコンテンツを特定します。

.tabContents section {
  opacity: 0.1;
  text-align: center;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

チェックされていない時は透明(ここでは仕組みが見えるように半透明)にしておき、チェックされたボタンを不透明にすることで、表示/非表示が切り替わるというわけです。

目次に戻る

目次に戻る

アニメーションして切り替わる

タブコンテンツにコンテンツを入れてみました;)。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - タブコンテンツにコンテンツを入れてみました</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" name="switch" id="tab-1" checked>
  <input type="radio" name="switch" id="tab-2">
  <input type="radio" name="switch" id="tab-3">
  <input type="radio" name="switch" id="tab-4">
  <input type="radio" name="switch" id="tab-5">
  <ul class="tabBtn">
    <li><label for="tab-1">タブ1</label></li>
    <li><label for="tab-2">タブ2</label></li>
    <li><label for="tab-3">タブ3</label></li>
    <li><label for="tab-4">タブ4</label></li>
    <li><label for="tab-5">タブ5</label></li>
  </ul>
  <div class="tabContents">
    <section>
      <figure>
        <img src="http://lopan.jp/wp/wp-content/uploads/2014/01/title.png">
        <figcaption>フォント好きな人がフォントについて熱く語る「LOVEFONT」という企画にあと乗りで、僕の好きなフォント「きりぎりす」について、語るってほどは語れませんが、記事にさせていただきます。<a href="#">この記事を読む</a></figcaption>
      </figure>
    </section>
    <section>
      <figure>
        <img src="http://lopan.jp/wp/wp-content/uploads/2013/09/title.jpg">
        <figcaption>ちょっとざらざらした質感とか、手触りを感じるテクスチャって、背景にさりげなく敷くだけで、ほんのり暖かみが出ていいですよね。そんなざらざらノイズ画像を半透明にした「透明ノイズ」のつくり方についてまとめてみました。<a href="#">この記事を読む</a></figcaption>
      </figure>
    </section>
    <section>
      <figure>
        <img src="http://lopan.jp/wp/wp-content/uploads/2013/06/title.jpg">
        <figcaption>トップページのコーディングがひと通り完了したので、下層ページのコーディングに移る前に、一旦ブラウザチェックしてみようと思います:)。ブラウザチェックからIEでの表示崩れを整えるまでのまとめです。<a href="#">この記事を読む</a></figcaption>
      </figure>
    </section>
    <section>
      <figure>
        <img src="http://lopan.jp/wp/wp-content/uploads/2013/03/title.jpg">
        <figcaption>拡大しても劣化しないし、ダブルクリックでカンタンに色を変えられるし、もちろんIllustratorでも使い回せる、そんなPhotoshopの万能シェイプの機能や特長について、個人的なまとめです。<a href="#">この記事を読む</a></figcaption>
      </figure>
    </section>
    <section>
      <figure>
        <img src="http://lopan.jp/wp/wp-content/uploads/2012/12/title.jpg">
        <figcaption>CSS Programming Advent Calendar 2012、22日目のための記事です。前回の記事で作った、グローバルナビの下の大きめの画像のところを、CSSだけで実装してみました。<a href="#">この記事を読む</a></figcaption>
      </figure>
    </section>
  </div>
</div>
</body>
</html>

#wrapper {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

[name="switch"] {
  display: none;
}

/* :::::: button :::::: */

/* 略 */

/* :::::: contents :::::: */

.tabContents {
  position: relative;
}

.tabContents section {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  width: 100%;
  padding: 20px;
  background-color: #fff;
}

.tabContents figure {
  overflow: hidden;
}

.tabContents figure img {
  float: left;
  max-width: 50%;
  margin-right: 20px;
}

.tabContents figcaption {
  font-size: 12px;
  line-height: 1.8;
}

/* :::::: mechanism :::::: */

.tabContents section {
  opacity: 0.1;
  transition: opacity 0.3s;
}

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

タブコンテンツも、前述のボタンの時みたく、「transition」を使って切り替わり方をアレンジすれば、印象的な表現ができちゃいますよ。

スライドして切り替わる

タブボタンの切り替えに合わせて、<div class="tabContents">の位置を上下にズラせば、スクロールコンテンツみたいなものもお手のもの。

タブボタンに対応するタブコンテンツの位置

上図のように、あらかじめtransform: translateY()で、タブボタンに対応するコンテンツの位置を指定しておきます。例えば下記なら、「タブ2」がチェックされてる時には、.tabContentsを上へ20%ズラす、ということ。.tabContents全体の高さを100%とした20%分。

.tabs #tab-2:checked ~ .tabContents {
  transform: translateY(-20%);
  -webkit-transform: translateY(-20%);
}

これをタブコンテンツ分(このサンプルでは5つ)用意し、transitionを適用すれば、上下にスライドしながらコンテンツが切り替わるようになります。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 縦にスライドして切り替わるタブコンテンツ</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述のと同じ -->

</body>
</html>
/* 略 */

/* :::::: slide :::::: */

.tabContents {
  -webkit-transition: -webkit-transform 0.6s;
  transition: transform 0.6s;
}

.tabContents section {
  opacity: 0.1;
  transition: opacity 0.3s;
}

/* :::::: mechanism :::::: */

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

#tab-1:checked ~ .tabContents { -webkit-transform: translateY(0); transform: translateY(0); }
#tab-2:checked ~ .tabContents { -webkit-transform: translateY(-20%); transform: translateY(-20%); }
#tab-3:checked ~ .tabContents { -webkit-transform: translateY(-40%); transform: translateY(-40%); }
#tab-4:checked ~ .tabContents { -webkit-transform: translateY(-60%); transform: translateY(-60%); }
#tab-5:checked ~ .tabContents { -webkit-transform: translateY(-80%); transform: translateY(-80%); }

あれれ…、タブコンテンツがタブボタンの上に被さってタブボタンが押せなくなっちゃう…X(。。

タブボタンをタブコンテンツより手前の階層に

こんな時は.tabBtnz-indexを指定して、手前に配置すれば安心。

z-indexpositionプロパティstatic以外の値が指定してある要素でないと効果がないので、position: relativeも一緒に指定。

.tabs .tabBtn {
  position: relative;
  z-index: 1;
}

無事タブボタンが押せるようになりました:D!

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 縦にスライドして切り替わるタブコンテンツ</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述のと同じ -->

</body>
</html>
/* 略 */

/* :::::: slide :::::: */

.tabBtn {
  position: relative;
  z-index: 1;
}

.tabContents {
  -webkit-transition: -webkit-transform 0.6s;
  transition: transform 0.6s;
}

.tabContents section {
  opacity: 0.1;
  transition: opacity 0.3s;
}

/* :::::: mechanism :::::: */

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

#tab-1:checked ~ .tabContents { -webkit-transform: translateY(0); transform: translateY(0); }
#tab-2:checked ~ .tabContents { -webkit-transform: translateY(-20%); transform: translateY(-20%); }
#tab-3:checked ~ .tabContents { -webkit-transform: translateY(-40%); transform: translateY(-40%); }
#tab-4:checked ~ .tabContents { -webkit-transform: translateY(-60%); transform: translateY(-60%); }
#tab-5:checked ~ .tabContents { -webkit-transform: translateY(-80%); transform: translateY(-80%); }

目次に戻る

横にスライドして切り替わる

タブコンテンツを横並びにして、transform: translateX()で横へズラせば、横スライドもお手のもの。

.tabContentsの横幅20%分ずつスライドする

.tabContentsの横幅をウィンドウ幅5つ分(500%)にして、その中にタブコンテンツを横並びにします。そのままだとスクロールバーが出てしまうので、全体を包む<div id="wrapper">overflow: hiddenを指定して、スクロールバーを出さないようにすればできあがり。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 横にスライドして切り替わるタブコンテンツ</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述のと同じ -->

</body>
</html>
/* 略 */

/* :::::: slide :::::: */

#wrapper {
  overflow: hidden;
}

.tabContents {
  width: 500%;
  -webkit-transition: -webkit-transform 0.6s;
  transition: transform 0.6s;
}

.tabContents section {
  float: left;
  width: 20%;
  opacity: 0.1;
  transition: opacity 0.3s;
}

/* :::::: mechanism :::::: */

#tab-1:checked ~ .tabBtn li [for="tab-1"],
#tab-2:checked ~ .tabBtn li [for="tab-2"],
#tab-3:checked ~ .tabBtn li [for="tab-3"],
#tab-4:checked ~ .tabBtn li [for="tab-4"],
#tab-5:checked ~ .tabBtn li [for="tab-5"] {
  background-color: #cd5c5c;
}

#tab-1:checked ~ .tabContents section:nth-child(1),
#tab-2:checked ~ .tabContents section:nth-child(2),
#tab-3:checked ~ .tabContents section:nth-child(3),
#tab-4:checked ~ .tabContents section:nth-child(4),
#tab-5:checked ~ .tabContents section:nth-child(5) {
  opacity: 1;
  background-color: #fff;
}

#tab-1:checked ~ .tabContents { -webkit-transform: translateX(0); transform: translateX(0); }
#tab-2:checked ~ .tabContents { -webkit-transform: translateX(-20%); transform: translateX(-20%); }
#tab-3:checked ~ .tabContents { -webkit-transform: translateX(-40%); transform: translateX(-40%); }
#tab-4:checked ~ .tabContents { -webkit-transform: translateX(-60%); transform: translateX(-60%); }
#tab-5:checked ~ .tabContents { -webkit-transform: translateX(-80%); transform: translateX(-80%); }

目次に戻る

表示モード切り替え

ここまではいくつかのコンテンツをタブボタンで切り替えてましたが、タブボタンのON/OFFで、同一コンテンツのスタイルを変えるようにすれば、表示モード切り替えみたいな事もできます。

ここでは、「画像とテキスト全部入りのレイアウト」、「画像が主役のレイアウト」、「テキストのみのレイアウト」の3タイプの表示モードを、タブボタンで切り替えてます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 表示モード切り替え</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" name="switch" id="normalList" checked>
  <input type="radio" name="switch" id="imageList">
  <input type="radio" name="switch" id="textList">
  <ul class="tabBtn">
    <li><label for="normalList"></label></li>
    <li><label for="imageList"></label></li>
    <li><label for="textList"></label></li>
  </ul>
  <ul class="menu">
    <li><a href="#"><dl>
      <dt class="date"><span class="year">2014</span><span class="day">1.30</span><span class="week">Thu</span></dt>
      <dd class="img"><img src="http://lopan.jp/wp/wp-content/uploads/2014/01/icon_lovefont-300x300.png"></dd>
      <dd class="ttl">なつかしくってあったかい、きりぎりす。 #LOVEFONT</dd>
      <dd class="excerpt">フォント好きな人がフォントについて熱く語る「LOVEFONT」という企画にあと乗りで、僕の好きなフォント「きりぎりす」について、語るってほどは語れませんが、記事にさせていただきます。</dd>
    </dl></a></li>
    <li><a href="#"><dl>
      <dt class="date"><span class="year">2013</span><span class="day">9.15</span><span class="week">Sun</span></dt>
      <dd class="img"><span><img src="http://lopan.jp/wp/wp-content/uploads/2013/09/icon_texture.jpg"></span></dd>
      <dd class="ttl">透明ノイズと紙テクスチャ。</dd>
      <dd class="excerpt">ちょっとざらざらした質感とか、手触りを感じるテクスチャって、背景にさりげなく敷くだけで、ほんのり暖かみが出ていいですよね。そんなざらざらノイズ画像を半透明にした「透明ノイズ」のつくり方についてまとめてみました。</dd>
    </dl></a></li>
    <li><a href="#"><dl>
      <dt class="date"><span class="year">2013</span><span class="day">6.17</span><span class="week">Mon</span></dt>
      <dd class="img"><span><img src="http://lopan.jp/wp/wp-content/uploads/2013/09/icon_webdesign4.jpg"></span></dd>
      <dd class="ttl">Webサイトの作り方のまとめ!ブラウザチェック。</dd>
      <dd class="excerpt">トップページのコーディングがひと通り完了したので、下層ページのコーディングに移る前に、一旦ブラウザチェックしてみようと思います:)。ブラウザチェックからIEでの表示崩れを整えるまでのまとめです。</dd>
    </dl></a></li>
    <li><a href="#"><dl>
      <dt class="date"><span class="year">2013</span><span class="day">3.19</span><span class="week">Tue</span></dt>
      <dd class="img"><span><img src="http://lopan.jp/wp/wp-content/uploads/2013/03/icon_photoshop_shape.jpg"></span></dd>
      <dd class="ttl">Photoshopのシェイプでできること。</dd>
      <dd class="excerpt">拡大しても劣化しないし、ダブルクリックでカンタンに色を変えられるし、もちろんIllustratorでも使い回せる、そんなPhotoshopの万能シェイプの機能や特長について、個人的なまとめです。</dd>
    </dl></a></li>
  </ul>
</div>
</body>
</html>
/* 略 */

ul, dl, dd {
  margin: 0;
  padding: 0;
}

ul {
  list-style: none;
}

/* :::::: button :::::: */

.tabBtn {
  display: table;
  width: 100%;
  margin: 0 0 5px;
  padding: 0;
  background-color: #20b2aa;
  text-align: right;
}

.tabBtn li {
  display: inline-block;
  width: 50px;
  border-left: 1px solid #fff;
  background-color: #20b2aa;
  text-align: center;
  vertical-align: middle;
}

.tabBtn li label {
  display: block;
  cursor: pointer;
  height: 18px;
  padding: 9px 0;
  color: #fff;
  transition: background-color .3s;
}

.tabBtn li label::before {
  content: "";
  display: inline-block;
  overflow: hidden;
  width: 18px;
  height: 18px;
  background: url(../img/ico_tabs.svg) no-repeat;
}

.tabBtn li label[for="normalList"]::before {
  background-position: 0 0;
}

.tabBtn li label[for="imageList"]::before {
  background-position: -30px 0;
}

.tabBtn li label[for="textList"]::before {
  background-position: -60px 0;
}

.tabBtn li label:hover {
  background-color: rgba(205,92,92,.5);
}

/* :::::: contents :::::: */

.menu li,
.menu dl,
.menu dt,
.menu dd {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
}

.menu::after {
  content: "";
  display: block;
  clear: both;
}

.menu li {
  float: left;
  width: 25%;
  padding: 2px;
}

.menu li a {
  display: block;
  text-decoration: none;
  background-color: #fff;
  transition: color 0.6s, background-color 0.6s, opacity 0.6s;
}

.menu dl {
  position: relative;
  overflow: hidden;
  padding: 10px;
}

.menu dt,
.menu dd {
  font-size: 0.8em;
  line-height: 1.6;
}

.menu img {
  width: 100%;
  vertical-align: middle;
}

.menu .date,
.menu .excerpt {
  color: #373039;
}

.menu .ttl {
  margin-bottom: 0.3em;
  font-size: 1em;
  line-height: 1.4;
}

.menu .excerpt {
  font-size: 0.7em;
}

/* :::::: normal :::::: */

#normalList:checked ~ .menu li {
  width: 50%;
}

#normalList:checked ~ .menu dl {
  height: 140px;
}

#normalList:checked ~ .menu a:hover {
  opacity: 0.6;
}

#normalList:checked ~ .menu .date {
  height: 20px;
}

#normalList:checked ~ .menu .img {
  position: relative;
  float: left;
  overflow: hidden;
  width: 40%;
  height: 100px;
  margin-right: 20px;
  margin-bottom: 0.6em;
}

#normalList:checked ~ .menu .img img {
  position: absolute;
  top: 50%;
  -webkit-transform: translateY(-50%);
  transform: translateY(-50%);
}

#normalList:checked ~ .menu .img {
  z-index: 1;
}

#normalList:checked ~ .menu dl::after {
  content: "";
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 3em;
  background-image: -webkit-linear-gradient(bottom, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
  background-image: linear-gradient(bottom, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
}

/* :::::: image :::::: */

#imageList:checked ~ .menu .date,
#imageList:checked ~ .menu .ttl {
  z-index: 1;
  position: absolute;
  left: 0;
  line-height: 1;
  background-color: rgba(255,255,255,0.9);
}

#imageList:checked ~ .menu .date {
  top: 15px;
  padding: 0.3em 5px 0.15em 15px;
}

#imageList:checked ~ .menu .ttl {
  bottom: 0;
  width: 100%;
  margin: 0;
  padding: 0.5em 15px 15px;
  font-size: 0.8em;
}

#imageList:checked ~ .menu .excerpt {
  display: none;
}

#imageList:checked ~ .menu .date,
#imageList:checked ~ .menu .ttl {
  opacity: 0;
  -webkit-transition: opacity 0.3s, -webkit-transform 0.6s;
  transition: opacity 0.3s, transform 0.6s;
}

#imageList:checked ~ .menu .date {
  -webkit-transform: translateY(-100%);
  transform: translateY(-100%);
}

#imageList:checked ~ .menu .ttl {
  -webkit-transform: translateY(100%);
  transform: translateY(100%);
}

#imageList:checked ~ .menu a:hover {
  background-color: rgba(255,255,255,0.3);
}

#imageList:checked ~ .menu a:hover .date,
#imageList:checked ~ .menu a:hover .ttl {
  opacity: 1;
  -webkit-transform: translateY(0);
  transform: translateY(0);
  transition-duration: 1s, 0.6s;
}

#imageList:checked ~ .menu .img {
  overflow: hidden;
  background-color: #593869;
  transition: background-color 0.6s 1s;
}

#imageList:checked ~ .menu dl .img img {
  -webkit-transition: opacity 1s, -webkit-transform 0.3s;
  transition: opacity 1s, transform 0.3s;
}

#imageList:checked ~ .menu:hover dl .img img {
  transition-duration: 1s;
}

#imageList:checked ~ .menu a:hover .img img {
  opacity: .6;
  -webkit-transform: scale(1.2);
  transform: scale(1.2);
}

/* :::::: text :::::: */

#textList:checked ~ .menu li {
  float: none;
  width: 100%;
}

#textList:checked ~ .menu li a {
  background-color: rgba(255,255,255,0.3);
}

#textList:checked ~ .menu li a:hover {
  background-color: #fff;
}

#textList:checked ~ .menu dl {
  padding: 0;
}

#textList:checked ~ .menu dl::after {
  content: "";
  display: block;
  clear: both;
}

#textList:checked ~ .menu dt,
#textList:checked ~ .menu dd {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  margin: 0;
  padding: 10px;
}

#textList:checked ~ .menu .date {
  float: left;
  width: 12%;
  margin-right: 2px;
  background-color: #fff;
}

#textList:checked ~ .menu .date span {
  display: block;
  font-size: 0.8em;
  line-height: 1.2;
  text-align: center;
}

#textList:checked ~ .menu .date .day {
  font-size: 1.2em;
}

#textList:checked ~ .menu .date .week {
  background-color: #f4f4f4;
}

#textList:checked ~ .menu .img {
  display: none;
}

#textList:checked ~ .menu .ttl,
#textList:checked ~ .menu .excerpt {
  float: right;
  width: calc(88% - 2px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#textList:checked ~ .menu .ttl {
  padding-bottom: 0.3em;
}

#textList:checked ~ .menu .excerpt {
  padding: 0 10px;
}

/* :::::: media queries :::::: */

@media screen and (max-width: 480px) {
  .menu li {
    width: 50%;
  }
  #normalList:checked ~ .menu li {
    float: none;
    width: 100%;
  }
  #textList:checked ~ .menu .date {
    width: 20%;
  }
  #textList:checked ~ .menu .ttl,
  #textList:checked ~ .menu .excerpt {
    width: calc(80% - 2px);
  }
}

/* :::::: mechanism :::::: */

#normalList:checked ~ .tabBtn li [for="normalList"],
#imageList:checked ~ .tabBtn li [for="imageList"],
#textList:checked ~ .tabBtn li [for="textList"] {
  background-color: #cd5c5c;
}

#normalList:checked ~ .menu .date .year::after,
#imageList:checked ~ .menu .date .year::after,
#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  content: ".";
}

#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  margin-right: 0.5em;
}

下記のような記述で、各モード専用のスタイルを用意しておけば、チェックされているタブボタンに合わせて、指定したスタイルが適用される仕組みです。※該当CSSは127行め〜

#normalList:checked ~ .menu elements {
  /* 全部入り用のスタイル */
}

#imageList:checked ~ .menu elements {
  /* 画像が主役用のスタイル */
}

#textList:checked ~ .menu elements {
  /* テキストのみ用のスタイル */
}

アニメーションを加える

上のサンプルだと、transitionを指定してる所だと、前のモードのスタイルがちょっと見えちゃったり、モードの切り替わり方がちょっとかっこわるいですよね…。
下記のようにアニメーションを定義して、タブボタンが:checkedになった時に一度だけ再生するようにしてみます。モードが切り替わったときに、ちょっと間を置いてからフェードインする感じです。

@keyframes fadeIn {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}

このアニメーションをコンテンツに適用します。※該当CSSは6〜7行め

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 表示モード切り替えフェード</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述の参照 -->

</body>
</html>
/* 略 */

/* :::::: fade change :::::: */

input:checked ~ .menu {
  -webkit-animation: fadeIn 1s 0s 1;
  animation: fadeIn 1s 0s 1;
}

@-webkit-keyframes fadeIn {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes fadeIn {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}

/* :::::: mechanism :::::: */

#normalList:checked ~ .tabBtn li [for="normalList"],
#imageList:checked ~ .tabBtn li [for="imageList"],
#textList:checked ~ .tabBtn li [for="textList"] {
  background-color: #cd5c5c;
}

#normalList:checked ~ .menu .date .year::after,
#imageList:checked ~ .menu .date .year::after,
#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  content: ".";
}

#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  margin-right: 0.5em;
}

ページが開いた時に一度だけフェードインしますが、タブボタンで切り替える時には、アニメーションが再生されません…X(。。
:checkedされるタブが切り替わっても「fadeIn」というアニメーションはすでに再生された後なので、それ以上は再生されないみたいです…。
そこで、下のサンプルでは、同じアニメーションを各タブ用に3つ用意して、各タブごとに違うアニメーションを指定してみます。※該当CSSは5〜18行め

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 表示モード切り替えフェード</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述の参照 -->

</body>
</html>
/* 略 */

/* :::::: fade change :::::: */

#normalList:checked ~ .menu {
  -webkit-animation: fadeIn1 1s 0s 1;
  animation: fadeIn1 1s 0s 1;
}

#imageList:checked ~ .menu {
  -webkit-animation: fadeIn2 1s 0s 1;
  animation: fadeIn2 1s 0s 1;
}

#textList:checked ~ .menu {
  -webkit-animation: fadeIn3 1s 0s 1;
  animation: fadeIn3 1s 0s 1;
}

@-webkit-keyframes fadeIn1 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes fadeIn1 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}

@-webkit-keyframes fadeIn2 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes fadeIn2 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}

@-webkit-keyframes fadeIn3 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes fadeIn3 {
  0% { opacity: 0; }
  30% { opacity: 0; }
  100% { opacity: 1; }
}

/* :::::: mechanism :::::: */

#normalList:checked ~ .tabBtn li [for="normalList"],
#imageList:checked ~ .tabBtn li [for="imageList"],
#textList:checked ~ .tabBtn li [for="textList"] {
  background-color: #cd5c5c;
}

#normalList:checked ~ .menu .date .year::after,
#imageList:checked ~ .menu .date .year::after,
#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  content: ".";
}

#normalList:checked ~ .menu .date .day::after,
#imageList:checked ~ .menu .date .day::after {
  margin-right: 0.5em;
}

:checkedされるタブが変わる度に再生するアニメーションも切り替えることで、タブを切り替える度にアニメーションが再生されるようになりましたね:D!

目次に戻る

スライドショー

表示を切り替える仕組みは前述のタブコンテンツと全く同じ。
だけど、タブボタンの代わりに、左右の矢印ボタンでコンテンツを切り替えるようにしてます。
まずは、矢印ボタンとして機能させるための仕掛けについてまとめます。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - スライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" name="slideshow" id="switch1" checked>
  <input type="radio" name="slideshow" id="switch2">
  <input type="radio" name="slideshow" id="switch3">
  <input type="radio" name="slideshow" id="switch4">
  <input type="radio" name="slideshow" id="switch5">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide1">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide2">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide3">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
      <section id="slide4">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_4">
      </section>
      <section id="slide5">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_5">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
      <label for="switch4"></label>
      <label for="switch5"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
      <label for="switch4"></label>
      <label for="switch5"></label>
    </p>
  </div>
</div>
</body>
</html>
/* :::::: slideshow :::::: */

#wrapper {
  overflow: hidden;
  width: 100%;
  padding: 0;
}

input[type="radio"] {
  display: none;
}

#slideshow {
  position: relative;
  width: 100%;
}

.slideContents {
  position: relative;
  background: lightSeaGreen;
  text-align: center;
  -webkit-user-select: none;
  user-select: none;
}

.slideContents {
  width: 500%;
  -webkit-transition: -webkit-transform .6s;
  transition: transform .6s;
}

.slideContents::after {
  content: "";
  display: block;
  clear: both;
}

.slideContents section {
  float: left;
  width: 20%;
  -webkit-transition: opacity .6s;
  transition: opacity .6s;
}

.slideContents section img {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  max-width: 100%;
  height: auto;
  padding: 0 50px;
  vertical-align: middle;
}

/* :::::: slideshow mechanism :::::: */

#switch1:checked ~ #slideshow .slideContents {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}
#switch2:checked ~ #slideshow .slideContents {
  -webkit-transform: translateX(-20%);
  transform: translateX(-20%);
}
#switch3:checked ~ #slideshow .slideContents {
  -webkit-transform: translateX(-40%);
  transform: translateX(-40%);
}
#switch4:checked ~ #slideshow .slideContents {
  -webkit-transform: translateX(-60%);
  transform: translateX(-60%);
}
#switch5:checked ~ #slideshow .slideContents {
  -webkit-transform: translateX(-80%);
  transform: translateX(-80%);
}

/* :::::: arrows :::::: */

.arrow,
.arrow label,
.arrow .ico {
  position: absolute;
}

.arrow {
  top: 0;
  margin: 0;
  transition: background .3s;
}
.prev { left: 0; }
.next { right: 0; }

.arrow:hover {
  background: rgba(255,255,255,.2);
}

.arrow,
.arrow label {
  cursor: pointer;
  width: 50px;
  height: 100%;
}

.arrow label {
  top: 0;
  left: 0;
  z-index: 1;
}

.arrow .ico {
  top: 50%;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  border-top: 3px solid #fff;
  border-right: 3px solid #fff;
  opacity: 0;
  transition: right .6s, left .6s, opacity .6s;
}

.arrow:hover .ico {
  opacity: .6;
  transition-duration: .3s;
}

.prev .ico {
  left: 60%;
  -webkit-transform: rotate(-135deg);
  transform: rotate(-135deg);
}

.next .ico {
  right: 60%;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
}
.prev:hover .ico { left: 30%; }
.next:hover .ico { right: 30%; }

/* :::::: arrows mechanism :::::: */

.arrow label {
  pointer-events: none;
}

#switch1:checked ~ #slideshow .prev label[for="switch5"],
#switch2:checked ~ #slideshow .prev label[for="switch1"],
#switch3:checked ~ #slideshow .prev label[for="switch2"],
#switch4:checked ~ #slideshow .prev label[for="switch3"],
#switch5:checked ~ #slideshow .prev label[for="switch4"],

#switch1:checked ~ #slideshow .next label[for="switch2"],
#switch2:checked ~ #slideshow .next label[for="switch3"],
#switch3:checked ~ #slideshow .next label[for="switch4"],
#switch4:checked ~ #slideshow .next label[for="switch5"],
#switch5:checked ~ #slideshow .next label[for="switch1"] {
  pointer-events: auto;
}

矢印ボタンの仕組み

矢印ボタンはそれぞれ、左矢印が戻る用(コンテンツを右方向にスライド)、右矢印が送る用(コンテンツを左方向にスライド)となっていて、例えば、1つめのコンテンツが表示されている時に右矢印ボタンをクリックすると、2つめのコンテンツまでスライドし、そこからさらに右矢印ボタンをクリックすると、3つめのコンテンツまでスライドします。
コンテンツは、タブコンテンツの時と同じように、全コンテンツを包む.slideContentsをスライドさせてます。

コンテンツがスライドするイメージ

1つめのコンテンツが表示されている時の右矢印ボタンは#switch2をチェック、2つめのコンテンツが表示されている時の右矢印ボタンは#switch3をチェックするってこと。クリックする度にターゲットが変わるわけですねー。
とはいえCSSでは、for属性だけ書き換えるとかできないので、最初からすべてのlabel要素を用意しておき、クリックする度にCSSで出し分けるようにします。

HTML

構造はタブコンテンツのものとほぼ同じですが、タブボタンの代わりに、左右の矢印ボタンを設置します。p要素の中にlabel要素を5つ並べたものを、2つ設置します。

左右の矢印の構造とそのソースコード

CSS

pointer-eventsプロパティの値をnoneに指定すると、その要素のリンククリックイベント動的な疑似クラスの操作などのマウスイベントを無効にすることができます。※初期値はautoで、操作が有効の状態。※動的な疑似クラスってのは:hoverとか:actionのこと。
これを使って、label要素のマウスイベントを一旦、無効にしておきます。

.slideshow .arrow label {
  pointer-events: none;
}

下記のように、チェックされたラジオボタンのid属性と、label要素のfor属性が、順繰りになるように、ラジオボタンの状態に合わせて、label要素のマウスイベントを有効にすればできあがり!

#switch1:checked ~ #slideshow .next label[for="switch2"],
#switch2:checked ~ #slideshow .next label[for="switch3"],
#switch3:checked ~ #slideshow .next label[for="switch4"],
#switch4:checked ~ #slideshow .next label[for="switch5"],
#switch5:checked ~ #slideshow .next label[for="switch1"] {
  pointer-events: auto;
}

上記ソースコードでは、右矢印ボタンの操作を、
#switch1がチェックされている時(=コンテンツ1が表示されてる時)<label for="switch2">を有効に、
#switch2がチェックされている時(=コンテンツ2が表示されてる時)<label for="switch3">を有効に、
…という具合に切り替えてます。

表示中のコンテンツに合わせて矢印ボタンを有効化

pointer-eventsプロパティについて詳しくは下記ページを参照のこと。

pointer-events - CSS | MDN

目次に戻る

同じ方向にスライド

コンテンツ1からコンテンツ5に切り替わる時と、コンテンツ5からコンテンツ1に切り替わる時、逆方向にスライドして戻るんじゃなくて、常に同じ方向にスライドした方がスマートですよね:)。

シームレスにスライドするイメージ

上図みたく、スライドさせる要素を、.slideContentsじゃなく、その中のコンテンツに変えればできそうな気がします。

まずはコンテンツをposition: absoluteで、すべて同じ位置に絶対配置してから、transform: translateX(100%)スライドショーの横幅分右側にズラして、隠しておきます。

#slideshow .slideContents section {
  position: absolute;
  top: 0;
  left: 0;
  transform: translateX(100%);
  -webkit-transform: translateX(100%);
  transition: transform .6s;
  -webkit-transition: -webkit-transform .6s;
}

タブボタンと同じように、#switch1:checkedの時はひとつめ<section>を真ん中に、#switch2:checkedの時はふたつめ<section>を真ん中に…という風に指定します。

#switch1:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide5 {
  z-index: 1;
  position: relative;
  transform: translateX(0);
  -webkit-transform: translateX(0);
}

この時にposition: relativeも一緒に指定するのがポイント。ぜんぶ絶対配置にすると.slideContents高さがなくなってしまうので、表示中のコンテンツだけは絶対配置じゃなくして、高さを保持します。真ん中のコンテンツも絶対配置だとこんななる。

これで、矢印ボタンをクリックして:checkedが切り替わると、それに合わせてコンテンツがスライドするようになりました!けどこれだけだと下図みたいな感じ。右側から出たり入ったりするだけになっちゃってます…。

右矢印ボタンをクリックした時には、表示中のコンテンツは左側にスライドしないといけないですよね。
つまり下図みたく、コンテンツが順繰りローテーションするような構造になります。

順繰りスライドしてくイメージ

「コンテンツ2」表示中はコンテンツ5コンテンツ1、「コンテンツ3」表示中はコンテンツ2コンテンツ1という具合に、表示中のコンテンツの手前ふたつのコンテンツは左側に来るように指定すればいいっぽいです!

#switch1:checked ~ #slideshow .slideContents #slide5,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  transform: translateX(-100%);
  -webkit-transform: translateX(-100%);
}

そしてできたのがこちら。むむ!何やらめまぐるしい…。

translateX(-100%)からtranslateX(100%)へ移動してくのが見えちゃってるんですね…。
端から端へ移動する時だけは、スライドじゃなくて、瞬間移動するようにしないといけません。つまりtransition-duration(変化にかかる時間)を0秒にすればいいって事ですね!

#switch1:checked ~ #slideshow .slideContents #slide3,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  transition-duration: 0s;
}

そんなこんなで、できあがり!

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 同じ方向にスライドするスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述の参照 -->

</body>
</html>
/* :::::: slideshow :::::: */

#wrapper {
  overflow: hidden;
  width: 100%;
  padding: 0;
}

input[type="radio"] {
  display: none;
}

#slideshow {
  position: relative;
  width: 100%;
}

.slideContents {
  position: relative;
  background: lightSeaGreen;
  text-align: center;
  -webkit-user-select: none;
  user-select: none;
}

.slideContents,
.slideContents section {
  width: 100%;
  height: auto;
}

.slideContents section {
  position: absolute;
  top: 0;
  left: 0;
  -webkit-transform: translateX(100%);
  transform: translateX(100%);
  -webkit-transition: opacity .6s, -webkit-transform .6s;
  transition: opacity .6s, transform .6s;
}

.slideContents section img {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  max-width: 100%;
  height: auto;
  padding: 0 50px;
  vertical-align: middle;
}

/* :::::: slideshow mechanism :::::: */

#switch1:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide5 {
  z-index: 1;
  position: relative;
  -webkit-transform: translateX(0);
  transform: translateX(0);
}

#switch1:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide5 {
  opacity: 1;
}

#switch1:checked ~ #slideshow .slideContents #slide5,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  -webkit-transform: translateX(-100%);
  transform: translateX(-100%);
}

#switch1:checked ~ #slideshow .slideContents #slide3,
#switch2:checked ~ #slideshow .slideContents #slide4,
#switch3:checked ~ #slideshow .slideContents #slide5,
#switch4:checked ~ #slideshow .slideContents #slide1,
#switch5:checked ~ #slideshow .slideContents #slide2,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  transition-duration: 0s;
}

/* :::::: arrows :::::: */

/* 略 */

目次に戻る

6秒おきに切り替わる

スライドショーなら、自動でスライドさせてみたいです。
animationプロパティを使って、スライドするアニメーションを、各コンテンツに個別に指定して、タイミングよく順番にスライドさせれば、できそうな気がします:D!

まずはアニメーションのキーフレームを作ります。
5つのコンテンツを順番にスライドさせるので、コンテンツひとつにつき、表示される時間は、全体の20%ずつ割り振れます。アニメーション全体の長さを100%秒とすると、各コンテンツのアニメーションの一連の流れは、下図みたいな感じになると思います。

スライドショーの一連の流れ

  1. 0%秒から16%秒までは真ん中でじっとしてる。

  2. 16%秒から20%秒にかけて、真ん中から左側へスライド。

  3. 右側へ瞬間移動。

  4. 22%秒から96%秒までは右側でじっとしてる。

  5. 96%秒から100%秒にかけて、右側から真ん中へスライド。

@keyframes autoplay {
  0% { transform: translateX(0); }
  16% { transform: translateX(0); }
  20% { transform: translateX(-100%); }
  20.001% { transform: translateX(100%); }
  96% { transform: translateX(100%); }
  100% { transform: translateX(0); }
}

瞬間移動のところは、@keyframesでは同じパーセント値を指定すると、後に書いた指定が優先されてしまうので、パーセント値をほんのちょっとズラして、瞬間的に移動するようにしてます。

そして、上で定義したautoplayを、スライドさせるコンテンツに指定します。

#slideshow .slideContents section {
  animation: autoplay 30s infinite;
  -webkit-animation: autoplay 30s infinite;
}

autoplayというアニメーションを、30秒かけて、繰り返し再生すよう指定しました。なので20%秒がちょうど6秒になります:)。
ただし、このままだと全部のコンテンツが重なってスライドしてる状態。6秒後には全コンテンツが一緒にスライドして、何もなくなっちゃいます…X(。24秒後にまた戻ってきます。

各コンテンツのアニメーションの開始位置をちょっとずつズラせば、同じキーフレームを使って、コンテンツを順番にスライドさせることができます。
animation-delayを使って、下記のように指定します。

#slideshow .slideContents #slide1 { animation-delay: 0; }
#slideshow .slideContents #slide2 { animation-delay: -24s; }
#slideshow .slideContents #slide3 { animation-delay: -18s; }
#slideshow .slideContents #slide4 { animation-delay: -12s; }
#slideshow .slideContents #slide5 { animation-delay: -6s; }

animation-delayプロパティにマイナスの値を指定すると、その分進んだ時点からアニメーションを開始するので、上記指定で、下図のように開始位置がズレるわけですねー。

開始位置が6秒ずつ後ろにズレる

できましたー!

けど、矢印ボタンをクリックしても何も起こりません…。
矢印ボタンではtransform: translateX()の値を切り替えてスライドさせたんですが、アニメーション中は@keyframesルールで定義したスタイルの方が優先されるので、矢印ボタンで切り替えてもびくともしないんですね…。自動スライドと矢印ボタンの併用はできなさそう…¦(。

そんなわけで、矢印ボタンをなくして、できあがり!

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 同じ方向にスライドするスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide1">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide2">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide3">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
      <section id="slide4">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_4">
      </section>
      <section id="slide5">
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_5">
      </section>
    </div>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: timer mechanism :::::: */

.slideContents section {
  -webkit-animation: autoplay 30s infinite;
  animation: autoplay 30s infinite;
}

.slideContents section {
  -webkit-transform: none;
  transform: none;
  transition: none;
}

.slideContents #slide1 {
  position: relative;
  -webkit-animation-delay: 0;
  animation-delay: 0;
}

.slideContents #slide2 {
  -webkit-animation-delay: -24s;
  animation-delay: -24s;
}

.slideContents #slide3 {
  -webkit-animation-delay: -18s;
  animation-delay: -18s;
}

.slideContents #slide4 {
  -webkit-animation-delay: -12s;
  animation-delay: -12s;
}

.slideContents #slide5 {
  -webkit-animation-delay: -6s;
  animation-delay: -6s;
}

@-webkit-keyframes autoplay {
  0% { -webkit-transform: translateX(0); }
  16% { -webkit-transform: translateX(0); }
  20% { -webkit-transform: translateX(-100%); }
  20.001% { -webkit-transform: translateX(100%); }
  96% { -webkit-transform: translateX(100%); }
  100% { -webkit-transform: translateX(0); }
}
@keyframes autoplay {
  0% { transform: translateX(0); }
  16% { transform: translateX(0); }
  20% { transform: translateX(-100%); }
  20.001% { transform: translateX(100%); }
  96% { transform: translateX(100%); }
  100% { transform: translateX(0); }
}

目次に戻る

演出を加える

スライドしてきた時にテキストだけ後から出てくるとか、イラストだけチロチロ動いてるとか、切り替わる時にほんの少しの動きを加えてみます。より印象的になること請け合いです:)。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - スライドショーに演出を加える</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <input type="radio" id="switch4" name="slideshow">
  <input type="radio" id="switch5" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide1">
        <div class="contents">
          <h1>奥行きがある感じ</h1>
          <p>スライドする距離を変えれば、やんわりパララックス。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide2">
        <div class="contents">
          <h1>遅れて出てくる</h1>
          <p>スライドするタイミングをずらして、さりげなくアクセント。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide3">
        <div class="contents">
          <h1>要素を立体的に</h1>
          <p>3Dtransformを使って、さらに立体感。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
      <section id="slide4">
        <div class="contents">
          <h1>アニメーションする</h1>
          <p>animationプロパティを使って、ほんのりアピール。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_4">
      </section>
      <section id="slide5">
        <div class="contents">
          <h1><span>いろいろアニメーション</span></h1>
          <p>飛んだり跳ねたりブルブルしたりして、賑やかし。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_5">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
      <label for="switch4"></label>
      <label for="switch5"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
      <label for="switch4"></label>
      <label for="switch5"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: contents :::::: */

.slideContents section {
  opacity: 0;
}

.slideContents section .contents {
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  position: absolute;
  top: 0;
  left: 50%;
  width: 600px;
  height: 200px;
  margin-left: -300px;
  padding: 20px;
}

.slideContents section h1,
.slideContents section p {
  color: lightseagreen;
  opacity: 0;
}

.slideContents section h1 {
  margin: 0;
  font-size: 16px;
}

.slideContents section p {
  font-size: 12px;
}

/* :::::: slideshow mechanism :::::: */

#switch1:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide5 {
  z-index: 1;
  position: relative;
  -webkit-transform: translateX(0);
  transform: translateX(0);
}

#switch1:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide5 {
  opacity: 1;
}

#switch1:checked ~ #slideshow .slideContents #slide5,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide1,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide2,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide3,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide4,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  -webkit-transform: translateX(-100%);
  transform: translateX(-100%);
}

#switch1:checked ~ #slideshow .slideContents #slide3,
#switch2:checked ~ #slideshow .slideContents #slide4,
#switch3:checked ~ #slideshow .slideContents #slide5,
#switch4:checked ~ #slideshow .slideContents #slide1,
#switch5:checked ~ #slideshow .slideContents #slide2,
#switch1:checked ~ #slideshow .slideContents #slide4,
#switch2:checked ~ #slideshow .slideContents #slide5,
#switch3:checked ~ #slideshow .slideContents #slide1,
#switch4:checked ~ #slideshow .slideContents #slide2,
#switch5:checked ~ #slideshow .slideContents #slide3 {
  transition-duration: 0s;
}

/* :::::: arrows :::::: */

/* 略 */

/* 奥行きがある感じ
 * 遅れて出てくる
 * 要素を立体的に
 * アニメーションする
 * いろいろアニメーション
 *
 * それぞれ、以下項のソース参照。
 */

上のサンプルでは、これまでのスライドショーに、h1要素とp要素を追加してみました。
<img>の上に<div class="contents">を重ねて、その中に<h1><p>を入れてる構造になります。

コンテンツの構造

コンテンツと、その中のh1要素p要素、それぞれの動きを個別に変えることで、スライドしてくる時のコンテンツにちょっとしたアクセントを付けてます。
コンテンツ1〜3まではtransitionプロパティを使って、コンテンツ4と5はanimationプロパティを使って、動きの違いを表現しています。
それでは、順番に(おおざっぱに)解説です!

奥行きがある感じ

h1要素とp要素の初期位置(左右に隠れてる時の位置)を、コンテンツの中心よりズラして配置し、コンテンツのスライドに合わせて徐々に中央に来るようスライドしてます。

h1要素とp要素は、コンテンツの中で、別にスライドしてる

遠くからスライドしてくる要素ほど速く動くので、やんわり遠近感が感じられる表現になるってわけで、これがパララックスってやつです。

よりパララックスがじっくり感じられるように、コンテンツ自体とh1要素とp要素それぞれに、transition-timing-functionで、ゆっくり始まってゆっくり終わる「easeInOutCubic」というイージングを適用したりしてます。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 奥行きがある感じのスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide01">
        <div class="contents">
          <h1>奥行きがある感じ</h1>
          <p>スライドする距離を変えれば、やんわりパララックス。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide02">
        <div class="contents">
          <h1>奥行きがある感じ</h1>
          <p>スライドする距離を変えれば、やんわりパララックス。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide03">
        <div class="contents">
          <h1>奥行きがある感じ</h1>
          <p>スライドする距離を変えれば、やんわりパララックス。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: action mechanism :::::: */

.slideContents section,
.slideContents section h1,
.slideContents section p {
  -webkit-transition: opacity 1s, -webkit-transform 1s;
  transition: opacity 1s, transform 1s;
}

#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  opacity: 1;
}

/* 奥行きがある感じ */
.slideContents section,
.slideContents section h1,
.slideContents section p {
  transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); /* easeInOutCubic */
}
#switch1:checked ~ #slideshow .slideContents #slide01,
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); /* easeOutCubic */
}
.slideContents section h1 {
  -webkit-transform: translateX(400px);
  transform: translateX(400px);
}
.slideContents section p {
  -webkit-transform: translateX(200px);
  transform: translateX(200px);
}
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}
#switch2:checked ~ #slideshow .slideContents #slide01 h1,
#switch3:checked ~ #slideshow .slideContents #slide02 h1,
#switch1:checked ~ #slideshow .slideContents #slide03 h1 {
  -webkit-transform: translateX(-400px);
  transform: translateX(-400px);
}
#switch2:checked ~ #slideshow .slideContents #slide01 p,
#switch3:checked ~ #slideshow .slideContents #slide02 p,
#switch1:checked ~ #slideshow .slideContents #slide03 p {
  -webkit-transform: translateX(-200px);
  transform: translateX(-200px);
}

遅れて出てくる

コンテンツ自体の動きは変えずに、h1要素とp要素の動きをちょっと変えてるだけ。

上のサンプルと同じように、h1要素とp要素の初期位置をコンテンツの中心よりズラして配置し、transition-delayで、0.3秒ずつ遅れて出てくるように指定したり、transition-durationで、コンテンツよりも、変化にかかる時間を長めに指定してます。

さらに、変化の仕方transition-timing-functionで、ちょっと行き過ぎて戻る、既存の「easeOutBack」というイージングを、緩めにアレンジしたものを適用。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 遅れて出てくるスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide01">
        <div class="contents">
          <h1>遅れて出てくる</h1>
          <p>スライドするタイミングをずらして、さりげなくアクセント。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide02">
        <div class="contents">
          <h1>遅れて出てくる</h1>
          <p>スライドするタイミングをずらして、さりげなくアクセント。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide03">
        <div class="contents">
          <h1>遅れて出てくる</h1>
          <p>スライドするタイミングをずらして、さりげなくアクセント。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: action mechanism :::::: */

.slideContents section,
.slideContents section h1,
.slideContents section p {
  -webkit-transition: opacity 1s, -webkit-transform 1s;
  transition: opacity 1s, transform 1s;
}

#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  opacity: 1;
}

/* 遅れて出てくる */
.slideContents section h1,
.slideContents section p {
  transition-duration: 1.2s;
  transition-timing-function: cubic-bezier(.1,1.3,.3,1); /* easeOutBackを緩めた感じ */
}
.slideContents section h1 {
  transition-delay: .3s;
}
.slideContents section p {
  transition-delay: .6s;
}
.slideContents section h1,
.slideContents section p {
  -webkit-transform: translateX(600px);
  transform: translateX(600px);
}
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}
#switch3:checked ~ #slideshow .slideContents #slide02 h1,
#switch3:checked ~ #slideshow .slideContents #slide02 p,
#switch1:checked ~ #slideshow .slideContents #slide03 h1,
#switch1:checked ~ #slideshow .slideContents #slide03 p,
#switch2:checked ~ #slideshow .slideContents #slide01 h1,
#switch2:checked ~ #slideshow .slideContents #slide01 p {
  -webkit-transform: translateX(-600px);
  transform: translateX(-600px);
}

要素を立体的に

コンテンツの初期状態(左右に隠れてる時の状態)を、コンテンツの表面が内側を向くように、横に90°回転した状態にしてます。
その時にちゃんと立体的な表現になるように、親要素<div class="slideContents">perspectiveプロパティを追加。

#slideshow .slideContents {
  perspective: 1000px;
  -webkit-perspective: 1000px;
}

回転する様子がよく見れるように、初期位置をいつもより手前に指定したり、回転の最中に透明になるように、透明度だけtransition-durationを短めにしたり、アニメーション具合を確認しながら、満足な動きになるまで適宜、微調整。
したりなんだりで、できあがり。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - スライドショーの要素を立体的に</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide01">
        <div class="contents">
          <h1>要素を立体的に</h1>
          <p>3Dtransformを使って、さらに立体感。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide02">
        <div class="contents">
          <h1>要素を立体的に</h1>
          <p>3Dtransformを使って、さらに立体感。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide03">
        <div class="contents">
          <h1>要素を立体的に</h1>
          <p>3Dtransformを使って、さらに立体感。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: action mechanism :::::: */

.slideContents section,
.slideContents section h1,
.slideContents section p {
  -webkit-transition: opacity 1s, -webkit-transform 1s;
  transition: opacity 1s, transform 1s;
}

#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  opacity: 1;
}

/* 要素を立体的に */
.slideContents {
  -webkit-perspective: 1000px;
  perspective: 1000px;
}
.slideContents section h1 {
  transition-delay: .6s, 0s;
}
.slideContents section p {
  transition-delay: .4s, 0s;
}
.slideContents section {
  -webkit-transform: translateX(500px) rotateY(-90deg);
  transform: translateX(500px) rotateY(-90deg);
  transition-duration: .8s, 1.2s;
}
#switch1:checked ~ #slideshow .slideContents #slide01,
#switch2:checked ~ #slideshow .slideContents #slide02,
#switch3:checked ~ #slideshow .slideContents #slide03 {
  -webkit-transform: translateX(0) rotateY(0deg);
  transform: translateX(0) rotateY(0deg);
  transition-delay: .2s, 0s;
}
#switch2:checked ~ #slideshow .slideContents #slide01,
#switch3:checked ~ #slideshow .slideContents #slide02,
#switch1:checked ~ #slideshow .slideContents #slide03 {
  -webkit-transform: translateX(-500px) rotateY(90deg);
  transform: translateX(-500px) rotateY(90deg);
}

アニメーションする

スライドする時の動きは変えずに、スライドした後、一度だけ、h1要素とp要素をアニメーションさせてます。
h1要素がぽよんと出てくる「h1Appear」というアニメーションと、同じくp要素がぽよんと出てくる「pAppear」というアニメーションを用意し、#switch4チェックされた時に一度だけ再生するよう、指定します。

#switch4:checked ~ #slideshow .slideContents #slide4 h1 {
  -webkit-animation: h1Appear 1.5s;
}
#switch4:checked ~ #slideshow .slideContents #slide4 p {
  -webkit-animation: pAppear 1.3s;
}

#switch4:checkedのh1要素とp要素だけにanimationを指定する事で、真ん中にスライドする時だけ、アニメーションが適用されます。※キーフレームの定義は47行め〜

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - アニメーションするスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide01">
        <div class="contents">
          <h1>アニメーションする</h1>
          <p>animationプロパティを使って、ほんのりアピール。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide02">
        <div class="contents">
          <h1>アニメーションする</h1>
          <p>animationプロパティを使って、ほんのりアピール。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide03">
        <div class="contents">
          <h1>アニメーションする</h1>
          <p>animationプロパティを使って、ほんのりアピール。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: action mechanism :::::: */

.slideContents section,
.slideContents section h1,
.slideContents section p {
  -webkit-transition: opacity 1s, -webkit-transform 1s;
  transition: opacity 1s, transform 1s;
}

#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  opacity: 1;
}

/* アニメーションする */
.slideContents section h1,
.slideContents section p {
  -webkit-transform-origin: 50% 100%;
  transform-origin: 50% 100%;
}
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  transition: none;
}
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 h1 {
  -webkit-animation: titleAppear 1.5s;
  animation: titleAppear 1.5s;
}
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  -webkit-animation: textAppear 1.3s;
  animation: textAppear 1.3s;
}
@-webkit-keyframes titleAppear {
  0% { opacity: 0; }
  68% { opacity: 0; -webkit-transform: translateY(6px) scaleY(1); }
  75% { opacity: 1; -webkit-transform: translateY(6px) scaleY(.8); }
  100% { -webkit-transform: translateY(0) scaleY(1); }
}
@-webkit-keyframes textAppear {
  0% { opacity: 0; }
  60% { opacity: 0; -webkit-transform: translateY(10px) scaleY(1); }
  68% { opacity: 1; -webkit-transform: translateY(10px) scaleY(.6); }
  95% { -webkit-transform: translateY(0) scaleY(1); }
}

@keyframes titleAppear {
  0% { opacity: 0; }
  68% { opacity: 0; transform: translateY(6px) scaleY(1); }
  75% { opacity: 1; transform: translateY(6px) scaleY(.8); }
  100% { transform: translateY(0) scaleY(1); }
}
@keyframes textAppear {
  0% { opacity: 0; }
  60% { opacity: 0; transform: translateY(10px) scaleY(1); }
  68% { opacity: 1; transform: translateY(10px) scaleY(.6); }
  95% { transform: translateY(0) scaleY(1); }
}

いろいろアニメーション

これも、スライドする時の動きは変えず、h1要素とp要素に、個別にアニメーションを適用しています。
h1要素にはその中にspan要素を入れてて、h1には上下に跳ねるアニメーションを指定し、spanには前後に回転するアニメーションを指定することで、宙返りするアニメーションを表現しています。

p要素は、translate()で上下左右に移動と、rotate()で傾きを、アニメーション具合を確認しながら、良い感じなランダムになるよう適宜、微調整。

  • HTML
  • CSS
  • PREVIEW
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - いろいろアニメーションスライドショー</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="radio" id="switch1" name="slideshow" checked>
  <input type="radio" id="switch2" name="slideshow">
  <input type="radio" id="switch3" name="slideshow">
  <div id="slideshow">
    <div class="slideContents">
      <section id="slide01">
        <div class="contents">
          <h1><span>いろいろアニメーション</span></h1>
          <p>飛んだり跳ねたりブルブルしたりして、賑やかし。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_1">
      </section>
      <section id="slide02">
        <div class="contents">
          <h1><span>いろいろアニメーション</span></h1>
          <p>飛んだり跳ねたりブルブルしたりして、賑やかし。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_2">
      </section>
      <section id="slide03">
        <div class="contents">
          <h1><span>いろいろアニメーション</span></h1>
          <p>飛んだり跳ねたりブルブルしたりして、賑やかし。</p>
        </div>
        <img src="http://placehold.it/600x200/fafafa/20b2aa/&text=slide_3">
      </section>
    </div>
    <p class="arrow prev">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
    <p class="arrow next">
      <i class="ico"></i>
      <label for="switch1"></label>
      <label for="switch2"></label>
      <label for="switch3"></label>
    </p>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: action mechanism :::::: */

.slideContents section,
.slideContents section h1,
.slideContents section p {
  -webkit-transition: opacity 1s, -webkit-transform 1s;
  transition: opacity 1s, transform 1s;
}

#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  opacity: 1;
}

/* いろいろアニメーション */
#switch1:checked ~ #slideshow .slideContents #slide01 h1,
#switch1:checked ~ #slideshow .slideContents #slide01 p,
#switch2:checked ~ #slideshow .slideContents #slide02 h1,
#switch2:checked ~ #slideshow .slideContents #slide02 p,
#switch3:checked ~ #slideshow .slideContents #slide03 h1,
#switch3:checked ~ #slideshow .slideContents #slide03 p {
  transition: none;
}
.slideContents section h1 {
  -webkit-perspective: 500px;
  perspective: 500px;
  -webkit-transform-origin: 50% 100%;
  transform-origin: 50% 100%;
  -webkit-animation: jump .5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite alternate;
  animation: jump .5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite alternate;
}
.slideContents section h1 span {
  display: block;
  -webkit-animation: rotate 2s infinite;
  animation: rotate 2s infinite;
}
.slideContents section p {
  -webkit-animation: shake .3s infinite alternate;
  animation: shake .3s infinite alternate;
}
@-webkit-keyframes shake {
  0% { -webkit-transform: translate(0) rotate(0deg); }
  10% { -webkit-transform: translate(-3px, -2px) rotate(-1.5deg); }
  20% { -webkit-transform: translate(1px, -1px) rotate(1deg); }
  30% { -webkit-transform: translate(-2px, -2px) rotate(-.6deg); }
  40% { -webkit-transform: translate(3px, 3px) rotate(.5deg); }
  50% { -webkit-transform: translate(0) rotate(0deg); }
  60% { -webkit-transform: translate(-3px, -4px) rotate(-1deg); }
  70% { -webkit-transform: translate(1px, -4px) rotate(1.5deg); }
  80% { -webkit-transform: translate(-3px, -2px) rotate(-.3deg); }
  90% { -webkit-transform: translate(3px, 2px) rotate(.4deg); }
  100% { -webkit-transform: translate(0) rotate(0deg); }
}
@-webkit-keyframes jump {
  0% { -webkit-transform: translateY(0); }
  100% { -webkit-transform: translateY(-10px); }
}
@-webkit-keyframes rotate {
  0% { -webkit-transform: rotateX(0deg); }
  5% { -webkit-transform: rotateX(0deg); }
  45% { -webkit-transform: rotateX(-180deg); }
  65% { -webkit-transform: rotateX(-180deg); }
  95% { -webkit-transform: rotateX(-360deg); }
  100% { -webkit-transform: rotateX(-360deg); }
}

@keyframes shake {
  0% { transform: translate(0) rotate(0deg); }
  10% { transform: translate(-3px, -2px) rotate(-1.5deg); }
  20% { transform: translate(1px, -1px) rotate(1deg); }
  30% { transform: translate(-2px, -2px) rotate(-.6deg); }
  40% { transform: translate(3px, 3px) rotate(.5deg); }
  50% { transform: translate(0) rotate(0deg); }
  60% { transform: translate(-3px, -4px) rotate(-1deg); }
  70% { transform: translate(1px, -4px) rotate(1.5deg); }
  80% { transform: translate(-3px, -2px) rotate(-.3deg); }
  90% { transform: translate(3px, 2px) rotate(.4deg); }
  100% { transform: translate(0) rotate(0deg); }
}
@keyframes jump {
  0% { transform: translateY(0); }
  100% { transform: translateY(-10px); }
}
@keyframes rotate {
  0% { transform: rotateX(0deg); }
  5% { transform: rotateX(0deg); }
  45% { transform: rotateX(-180deg); }
  65% { transform: rotateX(-180deg); }
  95% { transform: rotateX(-360deg); }
  100% { transform: rotateX(-360deg); }
}

以上!ほとんど適宜、微調整です…。ちょっと考えて、ちょっと試して、ちょっと考えて、ちょっとずついじりながら動きを作っくのは楽しいですよー;)。

目次に戻る

画面の端からニュッと出るメニュー

スマートフォンサイトなどでたまに見かけるこんなメニューも、CSSだけで作れます。
引き出しみたいに出し入れできるメニューだからドロワーメニューとかって言います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 画面の端からニュッと出るメニュー</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="checkbox" id="navTgl">

  <label for="navTgl" class="open">≡</label>
  <label for="navTgl" class="close"></label>
  <nav class="menu">
    <h2>menu</h2>
    <ul>
      <li><a href="#article1">なつかしくってあったかい、きりぎりす。</a></li>
      <li><a href="#article2">透明ノイズと紙テクスチャ。</a></li>
      <li><a href="#article3">Webサイトの作り方のまとめ!ブラウザチェック。</a></li>
      <li><a href="#article4">Photoshopのシェイプでできること。</a></li>
      <li><a href="#article5">CSSだけでスライドショーはつくれるよ。</a></li>
      </ul>
  </nav>

  <div class="contents">
    <header>
      <h1 class="logo">Lopan.jp</h1>
    </header>

    <article>
      <h1>Sample</h1>
      <section id="article1">
        <h2>なつかしくってあったかい、きりぎりす。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2014/01/title.png">
          <figcaption>フォント好きな人がフォントについて熱く語る「LOVEFONT」という企画にあと乗りで、僕の好きなフォント「きりぎりす」について、語るってほどは語れませんが、記事にさせていただきます。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article2">
        <h2>透明ノイズと紙テクスチャ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/09/title.jpg">
          <figcaption>ちょっとざらざらした質感とか、手触りを感じるテクスチャって、背景にさりげなく敷くだけで、ほんのり暖かみが出ていいですよね。そんなざらざらノイズ画像を半透明にした「透明ノイズ」のつくり方についてまとめてみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article3">
        <h2>Webサイトの作り方のまとめ!ブラウザチェック。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/06/title.jpg">
          <figcaption>トップページのコーディングがひと通り完了したので、下層ページのコーディングに移る前に、一旦ブラウザチェックしてみようと思います:)。ブラウザチェックからIEでの表示崩れを整えるまでのまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article4">
        <h2>Photoshopのシェイプでできること。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/03/title.jpg">
          <figcaption>拡大しても劣化しないし、ダブルクリックでカンタンに色を変えられるし、もちろんIllustratorでも使い回せる、そんなPhotoshopの万能シェイプの機能や特長について、個人的なまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article5">
        <h2>CSSだけでスライドショーはつくれるよ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2012/12/title.jpg">
          <figcaption>CSS Programming Advent Calendar 2012、22日目のための記事です。前回の記事で作った、グローバルナビの下の大きめの画像のところを、CSSだけで実装してみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>
    </article>

    <footer>
      <p class="copyright"><small>© Lopan.jp</small></p>
    </footer>
  </div>
</div>
</body>
</html>
@font-face {
  font-family: "Ubuntu Condensed";
  font-style: normal;
  font-weight: 400;
  src: local("Ubuntu Condensed"),
       local("UbuntuCondensed-Regular"),
       url(UbuntuCondensed-Regular.woff) format("woff");
}

header .logo,
footer .copyright {
  margin: 0;
  color: #593869;
  font-family: "Ubuntu Condensed";
  font-weight: normal;
  text-align: center;
  letter-spacing: .1em;
}

/* :::::: contents :::::: */

#wrapper {
  overflow: hidden;
  min-width: 320px;
  height: auto;
  padding: 0;
}

.contents {
  -webkit-transition: -webkit-transform .6s;
  transition: transform .6s;
}

#navTgl:checked ~ .contents {
  -webkit-transform: translateX(250px);
  transform: translateX(250px);
}

/* :::::: toggle button :::::: */

#navTgl {
  display: none;
  overflow: hidden;
}

label {
  cursor: pointer;
  position: fixed;
  top: 0;
  left: 0;
}

.open {
  z-index: 2;
  width: 50px;
  height: 50px;
  color: white;
  background-color: lightSeaGreen;
  font-size: 2em;
  line-height: 50px;
  text-align: center;
  -webkit-transition: background-color .6s, -webkit-transform .6s;
  transition: background-color .6s, transform .6s;
}

#navTgl:checked + .open {
  background-color: indianRed;
  -webkit-transform: translateX(250px);
  transform: translateX(250px);
}

.close {
  pointer-events: none;
  z-index: 1;
  width: 100%;
  height: 100%;
  transition: background-color .6s;
}

#navTgl:checked ~ .close {
  pointer-events: auto;
  background-color: rgba(0,0,0,.3);
}

/* :::::: drawer menu :::::: */

.menu {
  z-index: 1;
  position: fixed;
  overflow: auto;
  top: 0;
  left: 0;
  width: 250px;
  height: 100%;
  padding: 10px;
  background-color: rgba(0,0,0,.6);
  -webkit-transform: translateX(-100%);
  transform: translateX(-100%);
  -webkit-transition: -webkit-transform .6s;
  transition: transform .6s;
}

#navTgl:checked ~ .menu {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}

.menu h2,
.menu li a {
  color: white;
}

.menu h2 {
  text-align: center;
}

.menu ul,
header nav ul {
  padding: 0;
}

.menu li {
  border-bottom: 1px solid rgba(255,255,255,.6);
  font-size: .8em;
  line-height: 1.4;
}

.menu li:first-child {
  border-top: 1px solid rgba(255,255,255,.6);
}

.menu li a,
header nav li a {
  display: block;
  padding: 1em 2em;
  text-decoration: none;
  transition: background-color .6s;
}

.menu li a:hover {
  background-color: black;
}

/* :::::: header, footer :::::: */

header,
footer,
.menu {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

header,
footer {
  height: 100px;
}

header .logo,
footer .copyright {
  line-height: 100px;
}

header {
  position: relative;
  margin-bottom: 30px;
}

footer {
  background-color: rgba(255,255,255,.6);
}

footer small {
  font-size: 1em;
}

/* :::::: article :::::: */

article {
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  width: 100%;
  max-width: 647px;
  margin: 0 auto 100px;
  padding: 0 10px;
}

article h1 {
  width: 7em;
  height: 7em;
  margin: 0 auto;
  font-size: 1em;
  line-height: 7em;
  font-weight: normal;
  text-align: center;
  background-color: rgba(0,0,0,.05);
  border-radius: 50%;
}

section {
  margin: 50px 0;
}

section h2,
figure img,
figcaption {
  margin-bottom: 1em;
}

section h2 {
  margin: 0 0 20px;
  text-align: center;
}

figure {
  position: relative;
  padding-bottom: 50px;
}

#wrapper figure img {
  max-width: calc(100% - 10px);
}

figure img {
  height: auto;
  padding: 5px;
  background-color: rgba(255,255,255,.6);
}

figcaption {
  font-size: .8em;
  line-height: 1.6;
}

figcaption a {
  display: block;
  position: absolute;
  right: 0;
  bottom: 0;
  padding: 1em 2em;
  color: white;
  background: lightSeaGreen;
  text-align: center;
  text-decoration: none;
  transition: background-color .3s;
}

figcaption a:hover {
  background: indianRed;
}

開閉する仕組み

メニューが開閉する仕組みは、これまでのサンプル同様<input><label>を使った方法で、今回はラジオボタンじゃなくて、チェックボックスを使います:)。

ページ全体のHTMLの構造は下記の通り。

<body>
<div id="wrapper">
  <input type="checkbox" id="navTgl">

  <label for="navTgl" class="open">≡</label>
  <label for="navTgl" class="close"></label>
  <nav class="menu">
  </nav>

  <div class="contents">
    <header>
    </header>

    <article>
    </article>

    <footer>
    </footer>
  </div>
</div>
</body>

メニューを開閉するためのボタンは2つ用意しておき、ひとつは開くと閉じるの両用、もうひとつを閉じる用としておきます。両用の<label for="navTgl" class="open">は、常に見えている、ボタンの形をしたもの。閉じる用の<label for="navTgl" class="close">は、全面を覆うように固定配置してあります。

そして、スイッチの役割となる<input type="checkbox">は、<div id="wrapper">内の一番最初に設置。

ニュッと出るメニューとそのページ全体の構造

これが:checkedになった時に、それ以降の兄弟要素<label><nav><div class="contents">のスタイルを変える仕組みです。

メニューがニュッと出て、コンテンツも右へスライド

全面を覆っている閉じるボタンは、メニューが閉じている時はpointer-events: noneでマウスでの操作を無効にしておき、メニューが開いた時にはautoにして、クリックできるようにします。スライドショーの矢印ボタンの時と方法は一緒ですねー:)。

.close {
  pointer-events: none;
  z-index: 1;
  width: 100%;
  height: 100%;
  transition: background-color .6s;
}

#navTgl:checked ~ .close {
  pointer-events: auto;
  background-color: rgba(0,0,0,.3);
}

pointer-events: noneでマウスイベントが無効になるので、前面を覆っていても、その下のコンテンツには触ることができるんですねー:D。

目次に戻る

ウィンドウの幅に合わせてメニューを使い分ける

上のサンプルみたいなメニューは、画面の幅が狭い時だけ使えればよくて、通常は普通のメニューを表示させときたいって時もあるでしょう。

.open { display: none; }

@media screen and (max-width: 480px) {
  .open { display: block; }
}

上記のように指定すると、通常はメニューを開閉するボタンを非表示にしておいて、画面の横幅が480px以下の時だけ表示するようになります。
これはMedia Queries(メディアクエリ)という構文を使ってて、メディアの特性に合わせてスタイルを出し分けるための方法なのです。詳しくは後述

下のサンプルでは、Media Queriesを使って、ブラウザの横幅に合わせて、普通なメニューからドロワーメニューに切り替えています。
ブラウザの横幅を小さくしていくと、ヘッダーメニューがなくなって、引き出しボタンが現れると思います。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 画面の端からニュッと出るメニュー</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>
<div id="wrapper">
  <input type="checkbox" id="navTgl">

  <label for="navTgl" class="open">≡</label>
  <label for="navTgl" class="close"></label>
  <nav class="menu">
    <h2>menu</h2>
    <ul>
      <li><a href="#article1">なつかしくってあったかい、きりぎりす。</a></li>
      <li><a href="#article2">透明ノイズと紙テクスチャ。</a></li>
      <li><a href="#article3">Webサイトの作り方のまとめ!ブラウザチェック。</a></li>
      <li><a href="#article4">Photoshopのシェイプでできること。</a></li>
      <li><a href="#article5">CSSだけでスライドショーはつくれるよ。</a></li>
    </ul>
  </nav>

  <div class="contents">
    <header>
      <h1 class="logo">Lopan.jp</h1>
      <nav>
        <ul>
          <li><a href="#article1">LOVE FONT</a></li>
          <li><a href="#article2">透明ノイズ</a></li>
          <li><a href="#article3">ブラウザチェック</a></li>
          <li><a href="#article4">シェイプ</a></li>
          <li><a href="#article5">スライドショー</a></li>
        </ul>
      </nav>
    </header>

    <article>
      <h1>Sample</h1>
      <section id="article1">
        <h2>なつかしくってあったかい、きりぎりす。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2014/01/title.png">
          <figcaption>フォント好きな人がフォントについて熱く語る「LOVEFONT」という企画にあと乗りで、僕の好きなフォント「きりぎりす」について、語るってほどは語れませんが、記事にさせていただきます。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article2">
        <h2>透明ノイズと紙テクスチャ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/09/title.jpg">
          <figcaption>ちょっとざらざらした質感とか、手触りを感じるテクスチャって、背景にさりげなく敷くだけで、ほんのり暖かみが出ていいですよね。そんなざらざらノイズ画像を半透明にした「透明ノイズ」のつくり方についてまとめてみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article3">
        <h2>Webサイトの作り方のまとめ!ブラウザチェック。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/06/title.jpg">
          <figcaption>トップページのコーディングがひと通り完了したので、下層ページのコーディングに移る前に、一旦ブラウザチェックしてみようと思います:)。ブラウザチェックからIEでの表示崩れを整えるまでのまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article4">
        <h2>Photoshopのシェイプでできること。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/03/title.jpg">
          <figcaption>拡大しても劣化しないし、ダブルクリックでカンタンに色を変えられるし、もちろんIllustratorでも使い回せる、そんなPhotoshopの万能シェイプの機能や特長について、個人的なまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article5">
        <h2>CSSだけでスライドショーはつくれるよ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2012/12/title.jpg">
          <figcaption>CSS Programming Advent Calendar 2012、22日目のための記事です。前回の記事で作った、グローバルナビの下の大きめの画像のところを、CSSだけで実装してみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>
    </article>

    <footer>
      <p class="copyright"><small>© Lopan.jp</small></p>
    </footer>
  </div>
</div>
</body>
</html>
/* 略 */

/* :::::: nav :::::: */

header {
  height: auto;
}

header nav {
  max-width: 647px;
  margin: 0 auto;
}

header nav ul {
  display: table;
  width: 100%;
  margin: 0;
}

header nav li {
  display: table-cell;
  width: 20%;
  font-size: .8em;
  text-align: center;
  white-space: nowrap;
}

header nav li:not(:last-child) {
  border-right: 1px solid rgba(0,0,0,.1);
}

header nav li a {
  padding: 10px;
  color: white;
  background: lightSeaGreen;
  transition: background-color .3s;
}

header nav li a:hover {
  background: indianRed;
}

/* :::::: article :::::: */

/* 略 */

/* :::::: responsive :::::: */

.open {
  display: none;
}

/* smart phone */
@media screen and (max-width: 480px) {
  .open {
    display: block;
  }
  header nav {
    display: none;
  }
}

パッと切り替わるより、もうちょっと自然な感じに切り替わるようにしてみたいですね。CSSの指定を下記みたく変えてみました。

変えたところ(開閉するボタンのみ抜粋)

/* パッと切り替わる指定 */
.open {
  display: none;
}

@media screen and (max-width: 480px) {
  .open {
    display: block;
  }
}/* 自然な感じに切り替わる指定 */
.open {
  -webkit-transform: translate(0, -100%);
  transform: translate(0, -100%);
}
#navTgl:checked + .open {
  -webkit-transform: translate(250px, 0);
  transform: translate(250px, 0);
}

@media screen and (max-width: 480px) {
  .open {
    -webkit-transform: translate(0, 0);
    transform: translate(0, 0);
  }
}

display: noneじゃなくて、要素の透明度を変えたり、位置を移動するようにして、それぞれtransitionを指定してアニメーションしてみました。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 画面の端からニュッと出るメニュー</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述の参照 -->

</body>
</html>
/* 略 */

/* :::::: responsive :::::: */

.open {
  -webkit-transform: translate(0, -100%);
  transform: translate(0, -100%);
}

#navTgl:checked + .open {
  -webkit-transform: translate(250px, 0);
  transform: translate(250px, 0);
}

header nav {
  overflow: hidden;
  height: 2em;
  transition: height .6s, opacity .6s .4s;
}

/* smart phone */
@media screen and (max-width: 480px) {
  .open {
    -webkit-transform: translate(0, 0);
    transform: translate(0, 0);
  }
  header nav {
    height: 0;
    opacity: 0;
    transition-delay: .4s, 0s;
  }
}

目次に戻る

目次に戻る

パララックス

JavaScriptでパララックスな表現をする場合には、要素ごとにスクロールスピードを変えることで、視差効果を生み出してたと思いますが、CSSではtransformの3D表現を使って、要素を実際に画面の手前と奥に配置することで、パララックスを表現できます:)。※Internet Explorer、Firefoxでは確認できません…。

手前にパララックス

そんな訳で、要素を手前に配置して、パララックスしてみます!下図のような感じに、各要素を手前へ移動させることにしました。

手前から、アイキャッチ画像、ヘッダーナビ、リンクボタン、タイトルの順

手前への移動はtransformプロパティtranslateZ()を使います。
それから親要素には、遠近感を決めるためのperspectiveプロパティを指定します。ここでは200pxとして、200px離れたところから見てる感じにします。
遠近感の基準点(消失点)は、transform-originプロパティを指定してないので、初期値の親要素の中央になります。

.parallax #wrapper {
  perspective: 200px;
}

けど、下のサンプルは上手くいってませんねー…。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 手前にパララックス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body class="front parallax index">
<div id="wrapper">

  <div class="contents">
    <header>
      <h1 class="logo">Lopan.jp</h1>
      <nav>
        <ul>
          <li><a href="#article1">LOVE FONT</a></li>
          <li><a href="#article2">透明ノイズ</a></li>
          <li><a href="#article3">ブラウザチェック</a></li>
          <li><a href="#article4">シェイプ</a></li>
          <li><a href="#article5">スライドショー</a></li>
        </ul>
      </nav>
    </header>

    <article>
      <h1>Sample</h1>
      <section id="article1">
        <h2>なつかしくってあったかい、きりぎりす。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2014/01/title.png">
          <figcaption>フォント好きな人がフォントについて熱く語る「LOVEFONT」という企画にあと乗りで、僕の好きなフォント「きりぎりす」について、語るってほどは語れませんが、記事にさせていただきます。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article2">
        <h2>透明ノイズと紙テクスチャ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/09/title.jpg">
          <figcaption>ちょっとざらざらした質感とか、手触りを感じるテクスチャって、背景にさりげなく敷くだけで、ほんのり暖かみが出ていいですよね。そんなざらざらノイズ画像を半透明にした「透明ノイズ」のつくり方についてまとめてみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article3">
        <h2>Webサイトの作り方のまとめ!ブラウザチェック。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/06/title.jpg">
          <figcaption>トップページのコーディングがひと通り完了したので、下層ページのコーディングに移る前に、一旦ブラウザチェックしてみようと思います:)。ブラウザチェックからIEでの表示崩れを整えるまでのまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article4">
        <h2>Photoshopのシェイプでできること。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2013/03/title.jpg">
          <figcaption>拡大しても劣化しないし、ダブルクリックでカンタンに色を変えられるし、もちろんIllustratorでも使い回せる、そんなPhotoshopの万能シェイプの機能や特長について、個人的なまとめです。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>

      <section id="article5">
        <h2>CSSだけでスライドショーはつくれるよ。</h2>
        <figure>
          <img src="http://lopan.jp/wp/wp-content/uploads/2012/12/title.jpg">
          <figcaption>CSS Programming Advent Calendar 2012、22日目のための記事です。前回の記事で作った、グローバルナビの下の大きめの画像のところを、CSSだけで実装してみました。<a href="#">この記事を読む</a></figcaption>
        </figure>
      </section>
    </article>

    <footer>
      <p class="copyright"><small>© Lopan.jp</small></p>
    </footer>
  </div>

</div>
</body>
</html>
/* :::::: contents :::::: */

/* コンテンツ部分は「画面の端からニュッと出るメニュー」の項参照 */

/* :::::: parallax :::::: */

#wrapper {
  -webkit-perspective: 200px;
  perspective: 200px;
}

nav {
  -webkit-transform: translateZ(50px);
  transform: translateZ(50px);
}

h2 {
  -webkit-transform: translateZ(20px);
  transform: translateZ(20px);
}

figure img {
  -webkit-transform: translateZ(60px);
  transform: translateZ(60px);
}

figure figcaption a {
  -webkit-transform: translateZ(40px);
  transform: translateZ(40px);
}

要素は手前に移動してるみたいですけれど、遠近感の基準点がサイト全体の中心になってるので、全体的に縦に広がっちゃってますね。しかも基準点ごとスクロールしてるので、パララックスしないわけです…X(。
サイト全体の中心じゃなくて、下図みたく、常にウィンドウの中心が基準になるようにすれば、上手くパララックスする気がします…!

これを、こう

なので、親要素の#wrapperの大きさをウィンドウの大きさと同じになるよう、下記指定を加えます。
さらに#wrapperにはoverflowプロパティを指定してスクロールバーを出して、「#wrapperの中でコンテンツがスクロールする」ようにしてみました。

html, body, #wrapper {
  height: 100%;
}

#wrapper {
  overflow: auto;
}

これで、下図のような構造になりました。
#wrapperはウィンドウの大きさに固定で、その中身だけ、#wrapperの中でスクロールします。

#wrapperは動かない、中のコンテンツだけスクロール

ちゃんとパララックスするようになりましたー:D!

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 手前にパララックス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述と同じ -->

</body>
</html>
/* :::::: contents :::::: */

/* コンテンツ部分は「画面の端からニュッと出るメニュー」の項参照 */

/* :::::: parallax :::::: */

html, body, #wrapper {
  height: 100%;
}

#wrapper {
  overflow: auto;
  -webkit-perspective: 200px;
  perspective: 200px;
}

nav {
  -webkit-transform: translateZ(50px);
  transform: translateZ(50px);
}

h2 {
  -webkit-transform: translateZ(20px);
  transform: translateZ(20px);
}

figure img {
  -webkit-transform: translateZ(60px);
  transform: translateZ(60px);
}

figure figcaption a {
  -webkit-transform: translateZ(40px);
  transform: translateZ(40px);
}

手前のものほど大きくなっちゃってるので、できれば各要素の大きさは元通りにしたいですね。各要素にtransformプロパティscale()を指定して、調整してみたいと思います。

視点から要素までの距離と、大きさの関係は下図みたいになると思います。
距離が近づくほど、反比例して大きくなって見えるんですねー。

横から見た図と大きさの調整方法

例えば、400px離れたところにある要素は、実際の大きさの半分に見えてる事になるので、元の大きさに戻すには、2倍に拡大すればよいという事になります。
100pxのところにある要素なら、2倍の大きさに見えてるので、元の大きさに戻すには、2分の1に縮小(0.5倍)すればよいという事になります。
つまり「要素までの距離 / 基準の距離 = 拡大する値」ということになりますね!

アイキャッチ画像の場合なら、60px手前に移動してるから、要素までの距離は140pxなので、「140px / 200px = 0.7」。現在の大きさから「0.7」倍すれば元の見ための大きさに戻るということです。
transformの値にscale()を追記。

figure img {
  -webkit-transform: translateZ(60px) scale(0.7);
  transform: translateZ(60px) scale(0.7);
}

他の要素も同じ要領で、元の見た目の大きさになるように調整すれば、できあがりー:D!

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 手前にパララックス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述と同じ -->

</body>
</html>
/* :::::: contents :::::: */

/* コンテンツ部分は「画面の端からニュッと出るメニュー」の項参照 */

/* :::::: parallax :::::: */

html, body, #wrapper {
  height: 100%;
}

#wrapper {
  overflow: auto;
  -webkit-perspective: 200px;
  perspective: 200px;
}

nav {
  -webkit-transform: translateY(50px) translateZ(50px) scale(.75);
  transform: translateY(50px) translateZ(50px) scale(.75);
}

h2 {
  -webkit-transform: translateZ(20px) scale(.9);
  transform: translateZ(20px) scale(.9);
}

figure img {
  -webkit-transform: translateZ(60px) scale(.7);
  transform: translateZ(60px) scale(.7);
}

figure figcaption a {
  -webkit-transform: translateZ(40px) scale(.8);
  transform: translateZ(40px) scale(.8);
}

目次に戻る

奥にパララックス

手前に配置した要素は通常よりも早くスクロールしてましたが、奥に配置すれば、通常よりも遅くスクロールする事になります。
下のサンプルは、各要素が、上のサンプルとは逆順になるよう配置してます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 奥にパララックス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述と同じ -->

</body>
</html>
/* :::::: contents :::::: */

/* コンテンツ部分は「画面の端からニュッと出るメニュー」の項参照 */

/* :::::: parallax :::::: */

html, body, #wrapper {
  height: 100%;
}

#wrapper {
  overflow: auto;
  -webkit-perspective: 200px;
  perspective: 200px;
}

nav {
  -webkit-transform: translateY(-50px) translateZ(-50px) scale(1.25);
  transform: translateY(-50px) translateZ(-50px) scale(1.25);
}

h2 {
  -webkit-transform: translateZ(-20px) scale(1.1);
  transform: translateZ(-20px) scale(1.1);
}

figure img {
  position: relative;
  z-index: -1;
  -webkit-transform: translateZ(-60px) scale(1.3);
  transform: translateZ(-60px) scale(1.3);
}

figure figcaption a {
  z-index: -1;
  -webkit-transform: translateZ(-40px) scale(1.2);
  transform: translateZ(-40px) scale(1.2);
}

横スクロールバーが出ちゃいますね…。
translateX()で手前に移動させて大きく見える時には、要素自体の大きさは変わらないので、スクロールバーは出ませんでしたが、scale()拡大した時には、要素自体が大きくなるため、#wrapperからハミ出た分スクロールバーが出ちゃうんですね。

見た目は元のサイズだけど、要素自体は拡大してる

ここでは#wrapperoverflow-y: hiddenと指定して、横スクロールバーだけ出ないようにしました;P。
※該当CSSは13行め

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CSS Animation - 奥にパララックス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" href="../css/normalize.min.css">
<link rel="stylesheet" href="../css/sample.css">
</head>
<body>

<!-- HTMLは前述と同じ -->

</body>
</html>
/* :::::: contents :::::: */

/* コンテンツ部分は「画面の端からニュッと出るメニュー」の項参照 */

/* :::::: parallax :::::: */

html, body, #wrapper {
  height: 100%;
}

#wrapper {
  overflow: auto;
  overflow-x: hidden;
  -webkit-perspective: 200px;
  perspective: 200px;
}

nav {
  -webkit-transform: translateY(-50px) translateZ(-50px) scale(1.25);
  transform: translateY(-50px) translateZ(-50px) scale(1.25);
}

h2 {
  -webkit-transform: translateZ(-20px) scale(1.1);
  transform: translateZ(-20px) scale(1.1);
}

figure img {
  position: relative;
  z-index: -1;
  -webkit-transform: translateZ(-60px) scale(1.3);
  transform: translateZ(-60px) scale(1.3);
}

figure figcaption a {
  z-index: -1;
  -webkit-transform: translateZ(-40px) scale(1.2);
  transform: translateZ(-40px) scale(1.2);
}

で、できあがり!

目次に戻る

あとがき

記事を書いてる最中にもいろいろ新たな発見とかがあって紆余曲折しながらすごくすごく長くなっちゃいましたが、なんとかキリが着けれてよかったです;D(Chromeは次のバージョンアップでtransformにベンダープレフィックス要らなくなるみたいだし!)
たぶん今後もっとよりよい書き方に気付いたり、新しい技術が出てくると思うので、どんどん更新していきたいです。

最後に、動くCSSを使ってサンプルのサンプルサイトを作ってみましたー:D。
記事で紹介したCSSをいろいろ盛り込んでますので、ぜひ覗いて行ってくださいな。

CSS Animation - Lopan cafe

以上、動くCSSのためのメモでしたー。
最後まで読んでいただきありがとうございました!

  • このエントリーをはてなブックマークに追加
  • ツイート

Comment & Pingback

48 Comments! for 動くCSSのためのメモ。

  1. hiyashikyuri

    普段サーバーばっかりなので、フロントの表現力に感激しました!

    良い記事をありがとうございました。また参考にさせて頂きます!

    Reply

    • _watercolor

      > hiyashikyuriさん
      コメントありがとうございます!
      サーバーは苦手です…、けど、フロント楽しんでいただけてよかったです:D。
      今後とも、どうぞよろしくです!

      Reply

  2. ちゃっぴー

    こんにちは
    記事を拝見しました。
    勉強させてもらっています。

    質問なのですが、少し説明しづらいのですが、
    両サイドから画像がでてきて真ん中でぶつかって止まる →■■←
    みたいな事もアニメーションで可能なのでしょうか?

    メインイメージのスライド部分に使いたいなと思いまして
    お忙しいと思いますが、返信頂けると幸いです。

    よろしくお願い致します。

    Reply

    • _watercolor

      > ちゃっぴーさん

      コメントありがとうございます。
      両サイドから画像が出てくるスライドショー、できますよ;)!

      試しに作ってみましたので、見てみてくださいませ。こんな感じでよかったでしょうか…。

      http://sample.lopan.jp/css-animation/slideshow/sample-both.html

      HTMLの構造は、スライドショーのところで紹介しているものとほとんど同じで、section要素の中の画像を2つずつにして、それぞれ、left-imgright-imgというclass名を付けてます。

          <div class="slideContents">
            <section id="slide1">
              <img src="../img/pain_campagne.jpg" alt="" width="300" height="200" class="left-img">
              <img src="../img/pain_spandauer.jpg" alt="" width="300" height="200" class="right-img">
            </section>
            <section id="slide2">
              ...

      記事の中で紹介しているものは、チェックされている<input>が切り替わるたびに、.slideContentsをスライドさせてました。
      けれど上のサンプルでは、その中の2つの画像を動かすことにしてます。チェックされてない時は左右に配置しておいて、チェックされてる時だけ真ん中にくるようにしてるんです。
      詳しくは下記に、ファイルをまとめましたので、ダウンロードしてみてくださいませX)。

      「両側から出てくるスライドショー」のサンプルをダウンロードする

      上のサンプルだとぶつかってる感じがしないので、animationプロパティを使って、「ぶつかってる感じ」の動きも作ってみましたー:D。
      HTMLの構造は上のサンプルと同じなのですけれど、CSSが違って、スライドしてくる画像の動きを@keyframesで作って、それをanimationプロパティで指定してます。
      こちらのサンプルも、上のダウンロードファイルに入れてますので、見てみてくださいーX(。

      http://sample.lopan.jp/css-animation/slideshow/sample-both-2.html

      ではでは、今後ともLopan.jpをどうぞよろしくですXD!

      Reply

      • ちゃっぴー

        返信ありがとうございます。
        サンプルを作ってくださったのもそうですが、返信が来たことに感激です!!

        まさに、こんな感じですありがとうございました。
        スライドの部分でも紹介されいているようにオートプレイも可能なのでしょうか?
        また、分からなかったら参考にさせていただきたく思います!

        Reply

        • _watercolor

          > ちゃっぴーさん
          いえいえ、よかったー。お返事ありがとうございました。
          オートプレイもできますよ!すぐ見せれなくてごめんなさいですけれど…、
          お時間のあるときに作ってみようかなーと思いますーX)。
          ではではー!

          Reply

  3. eric88

    こんにちわ。いつも参考にさせて頂いてます。
    丁寧で可愛くて解りやすいです!

    1点質問よろしいでしょうか…
    「:targetを使ってタブコンテンツ」の実装をしたのですが、
    初めに1つ目のタブを表示させたいのですがうまくいきません。
    チェックボタンでやってみたものは大丈夫なのですが、
    targetをタブ1のどこかに記述しておくのでしょうか?
    cssで何か追記するのでしょうか?

    色々やってみてもうまくいかないので教えて頂けると嬉しいです…

    Reply

    • _watercolor

      > eric88さん
      こんにちわ!ブログ読んでくれてありがとうございます:D。

      :targetを使ってタブコンテンツのところですねー。
      ここは、:targetというセレクタを使って、表示するタブを選択しているので、
      CSSじゃなく、アドレスバーのURLの末尾に「#tab-1」とか、タブに付けているid属性を記述しておかないといけないんです。

      http://sample.lopan.jp/css-animation/tabs/sample-href.html#tab-1

      最初から一番めのタブが表示されるように指定しておけば、URLの末尾に何もなくても一番めのタブが表示されますけど、

      .tabBtn li [href="#tab-1"] {
        background-color: #cd5c5c;
      }
      .tabContents section:nth-child(1) {
        opacity: 1;
        background-color: #fff;
      }

      けどその場合、どれかが選択されたら非表示にするための指定も追加しないといけません。。

      .switch:target ~ .tabBtn li [href="#tab-1"] {
        background-color: lightSeaGreen;
      }
      .switch:target ~ .tabContents section:nth-child(1) {
        opacity: 0.1;
        background-color: transparent;
      }

      下記にサンプルを置いてみましたので見てみてくださいませ。

      http://sample.lopan.jp/css-animation/tabs/sample-href2.html

      ぜひ、いろいろ試してみてくださいーX)。
      ではでは、今後ともLopan.jpをどうぞよろしくです!

      Reply

      • eric88

        早急の返信ありがとうございます!
        丁寧な解説とサンプルのおかげで無事に実装することができました‼
        人気サイトなので数日は無理だと思っていたのですが…

        おかげ様で先ほどお客様に見て頂いたのですが、とても喜んで下さってました。
        できるだけjs使わないでほしいとの依頼だったので本当に感謝です!
        これからも色々勉強させて頂きます。
        ありがとうございました^^

        Reply

        • _watercolor

          > eric88さん
          お返事ありがとうございます!
          無事解決できたようで何よりですー;D。

          Reply

  4. りも子

    記事を拝見しました。
    参考にさせてもらっています。

    質問なのですが、「詳細はあとから表示する」の項目で、type2(画像がくるんと回るやつです)の裏面も画像にすることは可能ですか?
    もし可能であれば、教えていただけると嬉しいです!

    Reply

    • _watercolor

      > りも子さん
      コメントいただきありがとうございますー!

      さっそくさっそくご質問についてですが、くるんと裏返るやつ、もちろん両面とも画像にすることもできますよXD!
      記事で紹介しているサンプルは、img要素を表面、dl要素を裏面にしてますけれど、

      <li class="type2">
        <img src="img/image.png">
        <dl>... 中略 ...</dl>
      </li>

      そのdl要素のところをimg要素に変えればよいです。cssで指定する時のために、どっちが表でどっちが裏だか分かるように、class名をつけておくとわかりよいです:)。

      <li class="type2-2">
        <img src="img/image.png" class="front">
        <img src="img/image2.png" class="back">
      </li>

      記事中のサンプルと同じく、「表面だけ」、「裏面だけ」、「両面ある」のを並べてみました。
      http://sample.lopan.jp/css-animation/hover/sample-details-hidden-2.html

      詳しくは下記に、両面あるのだけをファイルにまとめましたので、ダウンロードしてみてくださいませー;)。

      「くるんと裏返っても画像」のサンプルをダウンロードする

      ではでは、今後ともLopan.jpをよろしくです!

      Reply

      • りも子

        ありがとうございます!
        無事実装できました!!

        もっと欲を言うと、このクルクルするヤツを横並びにしたいのですが…
        何度やっても縦に並んでしまいます…orz

        お手数かけますが、ぜひ横並びにする方法を教えていただければ、嬉しいです。

        何度もすいません

        Reply

        • りも子

          いろいろと試してるうちにできるようになりました!!
          本当にありがとうございました(*‘∀‘)

          Reply

          • _watercolor

            >りも子さん
            あわゎ、お返事遅くてごめんなさい…X(!
            横並びできてよかったです。
            コメントありがとうございますーXD♪!

  5. まさっく

    スライドショーを導入したら、スクロールするときにどこの画面にもついてくる要素(?)に被さってしまいました。
    解決法を教えてください!(実は初心者なので、ここはあまり立ち入ったことのない領域でした…)
    (その様子は「ウェブサイトで」貼らせて頂いたページを見て頂ければお分かりいただけるかと思います)

    Reply

    • _watercolor

      > まさっくさん
      コメントありがとうございます。

      サイト拝見させていただきましたー:)。
      さっそく、ご質問いただいた内容ですが、div#header-fixedという要素に、z-indexプロパティで「2」以上の値を指定すれば直ると思います!
      要素が重なってしまう場合はたいてい「z-index」というプロパティで解決することが多いです。
      ヘッダーなので、今後のことを考えてz-index: 100;とかにしておくとよいかも:D。

      z-indexプロパティについて詳しくは下記ページをご参照くださいー。

      z-index-スタイルシートリファレンス – HTMLクイックリファレンス

      ではでは、今後ともLopan.jpをよろしくです;)!

      Reply

      • まさっく

        ご返信ありがとうございます!無事直りました(笑)
        これからもこのサイトを参考にさせて頂きたいと思います、宜しくお願い致します。

        Reply

        • _watercolor

          > まさっくさん
          はーい、よかったー。
          今後ともよろしくです;D!

          Reply

  6. Pingback: hover時に素敵な動きを加えてくれるcss3アニメーション10選 | モノづくりブログ - 株式会社8bit

  7. masac225

    CSSの無限の可能性を体感しました!
    私がしたかったことがJS無しで再現が可能だったとは全く思っていませんでした(笑)
    上の方と同じように、ブックマークに登録させて頂きました。
    横スライドのタブメニューや、スライドショーなどが個人的には驚きました(^^)/

    Reply

    • _watercolor

      > masac225さん
      ありがとうございますー!
      CSSでアニメーションを表現できるようになったおかげで、今までJavaScriptで作っていた「動き」も簡単に実装できるようになりましたねー。
      ※ただし、記事ではinput要素などを使ってやってるところは、JavaScriptでclass名を書き換える方がよっぽどスマートなのであしからず…X)。

      Reply

  8. kannam_style

    cssでここまで出来ることに感動しました!
    学習の参考にさせていたただきます!

    Reply

    • _watercolor

      > kannam_styleさん
      はーい、コメントありがとうございますX)!
      どうぞご参考までに;)。

      Reply

  9. Pingback: [CSS]たった1行!サイト内のリンクを乱暴にふわっとかわいい感じにするカスタマイズ | たらハコ

  10. ぽんこつ

    CSS初心者なのですが、サンプルと丁寧な解説がとても勉強になりました!
    テクニックだけでなくサイト全体のデザインも素敵で参考になります。
    ありがとうございました!

    Reply

    • _watercolor

      > ぽんこつさん
      コメントありがとうございます!
      参考にしていただけて、記事もよろこんでおりますよーXD。

      Reply

  11. Pingback: CSS3アニメーションを使ったメニューやボタンのサンプル紹介【289種類+α】 | CreativeTips

  12. chicoro

    いつも勉強させて頂いております!
    スライドショーの部分なのですが、animation-delayとkey-frameで無事実装出来ました!
    しかし、IEとFirefoxでは動かず、、、-moz-やら-o-やら-ms-やら色々付け加えてやってみたんですけどダメでした。
    動きを見る限り、translateX(100%)の部分が、実際100%動いていない様子です。。。

    このサイトのCSSを見る限り同じ仕組みで、ただanimation-delayが「-」でないところと、translateがopacityなのですが、これだとIEでもうまく動作しています。
    http://codepen.io/leemark/pen/vzCdo

    スライドショーで何か解決策はないでしょうか??

    よろしくお願い致します。

    Reply

    • _watercolor

      > chicoroさん
      お返事が遅くなっちゃいまして申し訳ないです。
      もう解決しちゃってるかもしれないですが…、6秒おきに切り替わるのところですよね。
      …たしかにIEだとtranslateX(-100%)が10%くらいになっちゃってますね…(いま確認しました)!
      ご連絡くれてありがとうですX)!

      僕も結局わからずじまいだったので、translateX(-800px)にして、スライドした時だけ透明にしてごまかしてみましたX(!

      http://sample.lopan.jp/css-animation/slideshow/sample-timer-fix2.html

      @keyframes autoplay {
        0%, 16%, 100% { transform: translateX(0); opacity: 1; }
        20% { transform: translateX(-800px); opacity: 0; }
        20.001%, 96% { transform: translateX(800px); opacity: 0; }
      }

      もっとすてきな解決策などありましたらご教示いただけるとありがたいですー!
      どうぞよろしくお願いいたします。

      Reply

  13. もす

    細かいところまで分かりやすい解説がありめちゃくちゃタメになりました!!(*´艸`*)
    ありがとうございます☆

    Reply

    • _watercolor

      > もすさん
      お返事が遅くなっちゃいました、ごめんなさいX(。
      こちらこそ、読んでくださってありがとうございますです☆

      Reply

  14. Pingback: Direction-Aware Hover Effect | HAKONIWA

  15. ひろこ

    こんばんは。
    すごく為になる記事ありがとうございます。
    1点お伺いしたいのですが、こちらの「ボタンでございます」(押すとへこむ)のcssを入れると他の箇所に干渉しているのか、ホバー時に前後のスペースがブラックアウトしてしまいます。当方素人の為、テンプレートを使用しており、cssの知識が全くありません。他のコードを見ないともちろん分からないとは思いますが、思い当たる原因や、「これを付け加えたらいいよ」などの何かいい方法あったらご教示くださいませ。お手数をお掛けしますがよろしくお願いします。

    Reply

    • _watercolor

      > ひろこさん、こんばんは。
      コメントありがとうございます。
      うーん…、黒くなっちゃうんですか?
      もしかしたら、ホバー時に背景が黒くなるようなスタイルがどこかにあるのかもしれないですねー。
      「.btn a:hover」のところを、下記のように記述すると直るかもしれません。

      background-color: #3cc4bd !important;

      一度試してみてくださいー。。
      ではでは、今後ともLopan.jpをよろしくです:)!

      Reply

      • ひろこ

        早速のご返事ありがとうございます!一度試してみます。今後もよろしくお願い致します。

        Reply

  16. shige

    CSSでアニメーション、こんなのできないかな〜っと思って辿り着きました。
    とっても内容の濃い、素晴らしい記事で感動しました。
    良い勉強させていただきました\(^o^)/
    真似させていただいて、実際に作ってみたいなと^^
    ありがとうございました!

    Reply

    • _watercolor

      > shigeさん
      コメントありがたいですー!
      ぜひ、いろいろ試してみてくださいねー:D!

      Reply

  17. Joseph Kani

    とっても参考になりました^-^

    Reply

    • _watercolor

      > Joseph Kaniさん!
      ありがとうございます!
      よかった、うれしいです;D。

      Reply

  18. くまモン

    アニメーションの演出部分で構造が詳しく書いてあり、とても勉強になりました!
    今後の情報も楽しみにしております(´∀`)

    Reply

    • _watercolor

      > くまモンさん
      ありがとうございます!コメントいただけてうれしいです:)。
      CSSでもかんたんにアニメーションが作れるようになったし、GIFアニメとかSVGとかcanvasとかを使って、生き生きしたサイトが増えてきました。
      中でもCSSのアニメーションは割とかんたんに、(いつものHTML+CSSコーディングの流れで)使う事ができると思って、今回まとめてみました。
      今後Lopanもじゃんじゃん動いて(動かして)いきたいと思ってますので、どうぞよろしくお願いしますーX)!

      Reply

  19. Pingback: Twitter 人気のつぶやき 5/31~6/13 2014 | Webクリエイターボックス

  20. gonzalez

    すごいです! ありがとうございました。FBで紹介させていただきました。

    Reply

    • _watercolor

      > gonzalezさん
      紹介していただきありがとうございますー!
      励みになります:D!

      Reply

  21. Pingback: 先週(2014/06/02〜06)のオススメ記事「考える力の弱い人へ」他 | Select *

  22. 55cheese

    凄い!
    ボリュームも凄いし、まとめ方も分かりやすいし!
    永久保存版ブックマークしておきました!

    Reply

    • _watercolor

      > 55cheeseさん
      コメントありがとうございます!
      よかったー、そう言ってもらえると励みになるのですXD。
      ただ、メモなので、参考程度にどうぞー!
      情報ってどんどん古くなるので…X)。

      Reply

コメントを残す

*がついている欄は必須項目です。