サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

CSS3: 画像をクロスフェードで切替えるインターフェイス

ID: FN1501005 Technique: HTML5 and CSS Library: Prefix free

CSS3のtransitionプロパティを使うと、ふたつの画像をクロスフェードで切替えることができます。CSSDeckの作例「Solitary CSS3 Slider (Fade Transition)」は、さらに切替えボタンなどのインターフェイスもCSSでつくっていました。そこで、このコードの行数をわかりやすいように減らし、手直ししたサンプルで仕組みをご説明します(サンプル001)。JavaScriptコードは書きません。

サンプル001■CSS3: Crossfading images with the transition


01 画面の基本デザイン

アニメーションやインタラクションは後回しにして、まずは画面とインターフェイスの土台となるデザインから始めます。body要素には、つぎのようにid属性("gallery")が与えられたdiv要素を加え、その中に切替えボタンのインターフェイスをリスト(ul要素とli要素)で定めます。切替える画像(img要素)は後でdiv要素に含めます。なお、ボタンにするli要素の中のa要素には、href属性が仮で与えてあります。

<div id="gallery">
  <ul>
    <li>
      <a href="#"></a>
    </li>
    <li>
      <a href="#"></a>
    </li>
    <li>
      <a href="#"></a>
    </li>
    <li>
      <a href="#"></a>
    </li>
    <li>
      <a href="#"></a>
    </li>
  </ul>
</div>

このbody要素に後に掲げるコード001のCSSを適用すると、画像の領域とボタンのインターフェイスが表示されます(図001)[*1]。ボタンをかたちづくったCSSの定めについて、少し補っておきましょう。

図001■画像の領域とインターフェイスのボタンがCSSで定められた
図001

ボタンにしたli要素の中のa要素は、以下の抜書きのようにdisplayプロパティblockを与えてブロック要素ボックスとしました(第28行目)。なお、コードの頭に添えた行数は後掲コード001にもとづきます。さらに、border-radiusプロパティで円形に見えるように角を丸めました(第31行目)。

ボタンをへこんだように見せるために用いたのが、box-shadowプロパティです。第1に、左上の影を内側に落とします。第2に、右下の影は白いハイライトにして外側に加えるのです(図002)。内側につけたい影は、insetキーワードで始めます。また、影はカンマ区切りでいくつでも定められます(第30行目)。

box-shadow: [inset] 水平のずれ 垂直のずれ ぼかしの大きさ 影色

図002■内側の影と外側のハイライトでへこんだように見える
図002

  1. #gallery ul li a {
  2.   width: 12px;
  3.   height: 12px;
  4.   display: block;
  1.   box-shadow:
        inset 0 1px 1px 0px rgba(0, 0, 0, 0.6),
        0px 1px 1px 0px white;
  2.   border-radius: 50%;
  3. }

style要素の定めをまとめたのが、以下のコード001です。これで、前掲図001のように、画像の領域とインターフェイスのボタンが表示されます。ここまでは、アニメーションもインタラクションも加えていません。

コード001■画像の領域とインターフェイスのボタンを定めるCSS
  1. body {
  2.   padding: 0;
  3.   margin: 0;
  4.   background: lightgrey;
  5. }
  6. #gallery {
  7.   width: 640px;
  8.   height: 427px;
  9.   margin: 35px auto 0;
  10.   position: relative;
  11.   background: white;
  12.   box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
  13. }
  14. #gallery ul {
  15.   height: 40px;
  16.   position: absolute;
  17.   list-style: none;
  18.   bottom: -60px;
  19. }
  20. #gallery ul li {
  21.   float: left;
  22.   margin-right: 12px;
  23.   margin-top: 14px;
  24. }
  25. #gallery ul li a {
  26.   width: 12px;
  27.   height: 12px;
  28.   display: block;
  29.   background: silver;
  30.   box-shadow:
        inset 0 1px 1px 0px rgba(0, 0, 0, 0.6),
        0px 1px 1px 0px white;
  31.   border-radius: 50%;
  32. }

[*1] CSS3の機能は、ブラウザとそのバージョンによってベンダー接頭辞を加えなければなりません。たとえば、WebKit系なら-webkit-、Mozilla系は-moz-などです。本稿では、JavaScriptライブラリ「Prefix free」を用いることにより、ベンダー接頭辞は省きました(図003)。ベンダー接頭辞は、Prefix freeが自動的につけてくれるのです(「CSS3: 3次元空間に立方体をつくって回す ー transformプロパティ」02「CSSプロパティのベンダー接頭辞と『Prefix free』」参照)。

<script src="lib/prefixfree.min.js"></script>

図003■Prefix freeサイト
図003


02 ボタンのアニメーションとインタラクション

つぎに、ボタンのインタラクティブな動きをCSSで定めます。このとき、ターゲット要素を使いますので、src属性のない仮のimg要素にid属性を与えて、div要素につぎのように加えます。また、ボタンのa要素にも、それぞれ対応したターゲットをhref属性に定めました。

<div id="gallery">
  <img id="no_01">
  <img id="no_02">
  <img id="no_03">
  <img id="no_04">
  <img id="no_05">
  <ul>
    <li>
      <a href="#no_01"></a>
    </li>
    <li>
      <a href="#no_02"></a>
    </li>
    <li>
      <a href="#no_03"></a>
    </li>
    <li>
      <a href="#no_04"></a>
    </li>
    <li>
      <a href="#no_05"></a>
    </li>
  </ul>
</div>

手を加えたCSSは、後にコード002としてまとめました。ボタンにマウスポインタが重なったときの設定は、お約束どおり:hover疑似クラスに定めます(第33〜35行目)。backgroundプロパティで色を変えました。

  1. #gallery ul li a:hover {
  2.   background: darkgray;
  3. }

ボタンをクリックすると、そのa要素のhref属性に定めたターゲットに移動します。そして、URL(URI)にはそのターゲットが識別子として加わります。このとき、識別子の示す要素は、:target擬似クラスで表せるのです。そして、つぎのようにidごとに:target擬似クラスを定めたので、そのidと同じhref属性のa要素が選ばれて、backgroundプロパティで色が変わります(第36〜42行目)。

  1. #no_01:target ~ ul li a[href="#no_01"],
  2. #no_02:target ~ ul li a[href="#no_02"],
  3. #no_03:target ~ ul li a[href="#no_03"],
  4. #no_04:target ~ ul li a[href="#no_04"],
  5. #no_05:target ~ ul li a[href="#no_05"] {
  6.   background: gray;
  7. }

これで、ボタンへのマウスポインタの重なりと、クリックによる選択の動きができました(図004)。style要素をまとめたのが、以下のコード002です。後は、画像を加えて、クロスフェードのアニメーションを定めればよいでしょう。

図004■マウスポインタの重なりとクリックでボタンの色が変わる
図004

コード002■マウスインタラクションによるインターフェイスの動きを定めたCSS
  1. body {
  2.   padding: 0;
  3.   margin: 0;
  4.   background: lightgrey;
  5. }
  6. #gallery {
  7.   width: 640px;
  8.   height: 427px;
  9.   margin: 35px auto 0;
  10.   position: relative;
  11.   background: white;
  12.   box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
  13. }
  14. #gallery ul {
  15.   height: 40px;
  16.   position: absolute;
  17.   list-style: none;
  18.   bottom: -60px;
  19. }
  20. #gallery ul li {
  21.   float: left;
  22.   margin-right: 12px;
  23.   margin-top: 14px;
  24. }
  25. #gallery ul li a {
  26.   width: 12px;
  27.   height: 12px;
  28.   display: block;
  29.   background: silver;
  30.   box-shadow: inset 0 1px 1px 0px rgba(0, 0, 0, 0.6), 0px 1px 1px 0px white;
  31.   border-radius: 50%;
  32. }
  33. #gallery ul li a:hover {
  34.   background: darkgray;
  35. }
  36. #no_01:target ~ ul li a[href="#no_01"],
  37. #no_02:target ~ ul li a[href="#no_02"],
  38. #no_03:target ~ ul li a[href="#no_03"],
  39. #no_04:target ~ ul li a[href="#no_04"],
  40. #no_05:target ~ ul li a[href="#no_05"] {
  41.   background: gray;
  42. }

03 transitionプロパティでふたつのイメージをクロスフェードする

では、img要素に画像のsrc属性をつぎのように加えます。ボタンのリストについては、前掲のコードのまま変えていません。

<div id="gallery">
  <img id="no_01" src="images/photo_01.jpg" />
  <img id="no_02" src="images/photo_02.jpg" />
  <img id="no_03" src="images/photo_03.jpg" />
  <img id="no_04" src="images/photo_04.jpg" />
  <img id="no_05" src="images/photo_05.jpg" />
  <ul>
    <li>
      <a href="#no_01"></a>
    </li>
    <li>
      <a href="#no_02"></a>
    </li>
    <li>
      <a href="#no_03"></a>
    </li>
    <li>
      <a href="#no_04"></a>
    </li>
    <li>
      <a href="#no_05"></a>
    </li>
  </ul>
</div>

イメージのフェードインやフェードアウトは、transitionプロパティのアニメーションでopacityプロパティの値を変えます。transitionに定めるもっとも基本的な値は、つぎのようにアニメーションの時間、および変化のタイミング関数のふたつです(「CSS transition の使用」参照)。タイミング関数は値の変わり方を決め、キーワードから選べます(図005)。

transition: 時間 タイミング関数
図005■タイミング関数のキーワードと値の変化
linear 図005linear   ease
(デフォルト)
図005ease
ease-in 図005ease-in   ease-in-out 図005ease-in-out
ease-out 図005ease-out   step-start 図005step-start
step-end 図005step-end      

新たなstyle要素の定めは、後にコード003としてまとめました。img要素に関わるコードを以下に抜書きしました。opacityプロパティの値は0が基本となり、transitionプロパティを定めました(第18〜19行目)。

ボタンがクリックされてターゲットが選ばれると、そのimg要素はopacityプロパティの値1にフェードインします(第21および第23行目)。なお、初めに表示しておくimg要素は、opacityプロパティに1を与えてあります(第22〜24行目)。

他方、ターゲット以外のimg要素は、:not()疑似クラスopacityプロパティの値が0にフェードアウトされます(第25〜27行目)。もともと透明の要素はそのまま変わりませんので、前に選ばれていたimg要素と新たに選ばれたimg要素とがクロスフェードすることになります。

  1. #gallery img {
  2.   position: absolute;
  3.   left: 0;
  4.   top: 0;
  5.   opacity: 0;
  6.   transition: 0.5s ease;
  7. }
  8. #gallery img:target,
  9. #gallery img#no_01 {
  10.   opacity: 1;
  11. }
  12. #gallery img:not(:target) {
  13.   opacity: 0;
  14. }

ここまで手を加えたstyle要素は、つぎにまとめたコード003のとおりです。ボタンのインターフェイスで選んだイメージが、クロスフェードのアニメーションで切替わります。お題は、基本的にはこれででき上がりです。

コード003■ボタンで選択したイメージにクロスフェードさせるアニメーションを定めたCSS
  1. body {
  2.   padding: 0;
  3.   margin: 0;
  4.   background: lightgrey;
  5. }
  6. #gallery {
  7.   width: 640px;
  8.   height: 427px;
  9.   margin: 35px auto 0;
  10.   position: relative;
  11.   background: white;
  12.   box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
  13. }
  14. #gallery img {
  15.   position: absolute;
  16.   left: 0;
  17.   top: 0;
  18.   opacity: 0;
  19.   transition: 0.5s ease;
  20. }
  21. #gallery img:target,
  22. #gallery img#no_01 {
  23.   opacity: 1;
  24. }
  25. #gallery img:not(:target) {
  26.   opacity: 0;
  27. }
  28. #gallery ul {
  29.   height: 40px;
  30.   position: absolute;
  31.   list-style: none;
  32.   bottom: -60px;
  33. }
  34. #gallery ul li {
  35.   float: left;
  36.   margin-right: 12px;
  37.   margin-top: 14px;
  38. }
  39. #gallery ul li a {
  40.   width: 12px;
  41.   height: 12px;
  42.   display: block;
  43.   background: silver;
  44.   box-shadow:
        inset 0 1px 1px 0px rgba(0, 0, 0, 0.6),
        0px 1px 1px 0px white;
  45.   border-radius: 50%;
  46. }
  47. #gallery ul li a:hover {
  48.   background: darkgray;
  49. }
  50. #no_01:target ~ ul li a[href="#no_01"],
  51. #no_02:target ~ ul li a[href="#no_02"],
  52. #no_03:target ~ ul li a[href="#no_03"],
  53. #no_04:target ~ ul li a[href="#no_04"],
  54. #no_05:target ~ ul li a[href="#no_05"] {
  55.   background: gray;
  56. }

04 影を加える

お題の前掲サンプル001には、画像を表示する領域にもうひと手間デザインの手が加えられています。それを補って、この解説を閉じましょう。加えたのはふたつの影です(図006)。これらは、疑似要素 :before:afterで定めました。要素を傾斜してz-indexプロパティにより画像領域の背面に送ることで、傾いた影だけが下側の両端に表れます。画像を重ねれば、下の両角が少し浮き上がって見えることでしょう。

図006■画像領域の下に加えたふたつの影の疑似要素
図006

transformプロパティを用いると、要素の伸縮や回転、移動、あるいは傾斜などの変形ができます。プロパティには、つぎのように変換関数を与えて座標変換します(表001)。回転はrotate()、x軸やy軸に対する傾斜は、それぞれskewX()skewY()を用います。なお、回転と伸縮を使った作例は、「CSS3: transitionを使った回転と伸縮のアニメーション」をご覧ください。

transform 変換関数
表001■おもなCSS変換関数
変換関数 変換
rotate(angle) 時計回りに引数の角度回す。
scale(sx[, sy]) 引数の比率だけ水平および垂直に伸縮する。引数がひとつのときは、水平と垂直は同じ比率とされる。
translate(tx[, ty]) 引数の値だけ水平および垂直に移動する。引数がひとつのときは、垂直の移動値は0とされる。
skewX(angle)[*2]
skewY(angle)
x軸もしくはy軸に対して引数の角度傾斜させる。

ふたつの影の要素を加えて仕上げたstyle要素は、後にコード004にまとめて掲げました。疑似要素:before:afterを定めているのがつぎの抜書きです。ふたつの疑似要素にtransformプロパティを使って、左右対称になるように傾けています(第26および第30行目)。

  1. #gallery:before,
  2. #gallery:after {
  3.   content: '';
  4.   position: absolute;
  5.   width: 60%;
  6.   height: 20px;
  7.   box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
  8.   bottom: 13px;
  9.   z-index: -1;
  10. }
  11. #gallery:before {
  12.   left: 10px;
  13.   transform: skewY(-4deg);
  14. }
  15. #gallery:after {
  16.   right: 10px;
  17.   transform: skewY(4deg);
  18. }

つぎのコード004が、前掲サンプル001に定めたCSSです。影を活かしてつくったインターフェイスで、画像がクロスフェードして切替わります。

コード004■画像をクロスフェードで切替えるインターフェイスのCSS定義
  1. body {
  2.   padding: 0;
  3.   margin: 0;
  4.   background: lightgrey;
  5. }
  6. #gallery {
  7.   width: 640px;
  8.   height: 427px;
  9.   margin: 35px auto 0;
  10.   position: relative;
  11.   background: white;
  12.   box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.2);
  13. }
  14. #gallery:before,
  15. #gallery:after {
  16.   content: '';
  17.   position: absolute;
  18.   width: 60%;
  19.   height: 20px;
  20.   box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
  21.   bottom: 13px;
  22.   z-index: -1;
  23. }
  24. #gallery:before {
  25.   left: 10px;
  26.   transform: skewY(-4deg);
  27. }
  28. #gallery:after {
  29.   right: 10px;
  30.   transform: skewY(4deg);
  31. }
  32. #gallery img {
  33.   position: absolute;
  34.   left: 0;
  35.   top: 0;
  36.   opacity: 0;
  37.   transition: 0.5s ease;
  38. }
  39. #gallery img:target,
  40. #gallery img#no_01 {
  41.   opacity: 1;
  42. }
  43. #gallery img:not(:target) {
  44.   opacity: 0;
  45. }
  46. #gallery ul {
  47.   height: 40px;
  48.   position: absolute;
  49.   list-style: none;
  50.   bottom: -60px;
  51. }
  52. #gallery ul li {
  53.   float: left;
  54.   margin-right: 12px;
  55.   margin-top: 14px;
  56. }
  57. #gallery ul li a {
  58.   width: 12px;
  59.   height: 12px;
  60.   display: block;
  61.   background: silver;
  62.   box-shadow:
        inset 0 1px 1px 0px rgba(0, 0, 0, 0.6),
        0px 1px 1px 0px white;
  63.   border-radius: 50%;
  64. }
  65. #gallery ul li a:hover {
  66.   background: darkgray;
  67. }
  68. #no_01:target ~ ul li a[href="#no_01"],
  69. #no_02:target ~ ul li a[href="#no_02"],
  70. #no_03:target ~ ul li a[href="#no_03"],
  71. #no_04:target ~ ul li a[href="#no_04"],
  72. #no_05:target ~ ul li a[href="#no_05"] {
  73.   background: gray;
  74. }

[*2] x軸とy軸に対する傾斜をふたつの引数として渡せるskew()関数が、かつての草案に含まれていて、実装されている環境もあります。けれど、現在は除かれているため、使うことは避けるのがよいでしょう。



作成者: 野中文雄
作成日: 2015年1月24日


Copyright © 2001-2015 Fumio Nonaka.  All rights reserved.