CSS Animation
html / CSS

からくり CSS で 複数のアニメーション を走らせる


First

複数のアニメーションを走らせるメカニズム

巧妙なからくりの中身とは?

要点は、ラジオボタンと、データ属性と、CSS 変数と、ありとあらゆる限りのセレクタの手法が絡み合って対象を選択するというシロモノである。特定の条件を満たす要素にスタイルやアニメーションを適用するのだ。

今回の、ワンアクションで複数のアニメーションを走らせることができるケーススタディをここに用意した

ワンアクションで複数のアニメーションを走らせる CSS
ワンアクションで複数のアニメーションを走らせる CSS

ページのレイアウトはグリッドデザインで組む。テキストベースの為、レスポンシブ対応に対して position: absolute; で微調整をした。

ページ捲りにはラジオボタンを使う。クリックするとページ表示が次のページナンバーに変わると同時に次のテキストがアニメーションで出現する。前のテキストは移動して消える。

Second

ラジオボタン

ラジオボタンからはじまる

HTML文書にラジオボタンを配置するには、「input」タグを使用して以下の属性を指定する。

  1. 「type属性」"radio"を指定する事で「ラジオボタン」を表示する事ができる。
  2. 「neme属性」同じ name属性を付与することでグループ化して定義できる。
  3. 「value属性」グループ内のどのラジオボタンが選択されているかを識別するために使用される。value プロパティを取得すると、現在 checked 状態になっているラジオボタンの value が文字列として返されるという重要な働きをする。

ラジオボタンで切り替える

今回のケーススタディでは、5 ページ構成なので、ラジオボタンを 5 個作り、ページの捲り先をid で次のように設定する。ラジオボタンを押す度に連動するテキストがアニメーションする。

  • id="scene-1"
  • id="scene-2"
  • id="scene-3"
  • id="scene-4"
  • id="scene-5"

<label> 要素と <input> 要素を明示的に関連付ける

<label> 要素と <input> 要素を明示的に関連付けるには、最初に id 属性を <input> 要素に追加する。次に、for 属性を <label> 要素に追加する。for の値は <input> 要素の id と同じにする

何故このようなことをするのか、それは、input 要素に label 要素が視覚的に紐付けられ、input 要素にフォーカスが当たった際にlabel 要素を読み上げできる、label要素をクリックしてもフォームがアクティブ化できる、というユーザビリティに大きく貢献する為である。

そこで以下のように設定した。

<nav class="slide-nav">
  <div class="nav-button -prev">
    <span style="color: #ffffff;"><i class="fas fa-angle-left fa-2x"></i></span>
  
    <label class="nav-toggle" for="scene-1">1</label>
    <label class="nav-toggle" for="scene-2">2</label>
    <label class="nav-toggle" for="scene-3">3</label>
    <label class="nav-toggle" for="scene-4">4</label>
    <label class="nav-toggle" for="scene-5">5</label>
  </div>

ラジオグループを作成する

固有の name を持っている限り、好きなだけの数のラジオグループを作成することができる。ここでは 5 個作る。

<input type="radio" name="scene" id="scene-1" value="1" checked />
<input type="radio" name="scene" id="scene-2" value="2" />
<input type="radio" name="scene" id="scene-3" value="3" />
<input type="radio" name="scene" id="scene-4" value="4" />
<input type="radio" name="scene" id="scene-5" value="5" />

ケーススタディのページ部分を別ページに用意した。

Third

data 属性

data 属性をセレクタとして使う

data 属性により、標準外の属性や DOM の追加プロパティなどの特殊な方法に頼らずに、標準的な意味のある HTML 要素に追加情報を格納することができる。命名のルールとしては、必ず「data-」というプレフィックス(prefix/接頭辞、接頭語)をつける。

/* CSS */
#date-publication li{
  color: #333;
  padding: 0.2rem;
  margin: 4px;
  border-radius: 4px;
  display: block;
}
#date-publication li:before {
  content:attr(date-post);
  font-size: 0.8rem;
  backround-color: red;
}
li[data-type="special"] {
  background: #fcf2c5;
}
li[data-type="session"] {
  background: #c5fcfc;
}
<!-- HTML -->
<ul id="date-publication">
  <li date-post="2025-02-25" data-type="session"> Session at the Yoyogi studio </li>
  <li date-post="2025-02-26" data-type="session"> Session at a studio in Ebisu </li>
  <li date-post="2025-02-27" data-type="session"> Preparation</li>
  <li date-post="2025-02-28" data-type="special"> anniversary</li>
</ul>

カスタムデータ属性(data 属性)を使って、特定のデータ属性を持つ要素を選択することができ、これにより、カスタムデータを使ったスタイリングが可能になる。

div[data-color="tomato"] {
  background-color: tomato; /* data-color 属性が tomato の場合に要素の背景色を tomato 色にする */
}

ここでは、[data-属性名]という書き方でセレクタとして使うことが重要だ。例えば、こんな感じ。

.philosophy-text[data-statement-1] {
  color: red;
}
Fourth

CSS 変数

ラジオボタンの value に併せて CSS 変数を追加する

CSS 変数(カスタムプロパティ)について

接頭辞 -- が付いたプロパティ名、例えば「 --scene 」は、カスタムプロパティを表し、 var() 関数を用いて他の宣言の中で使用することができる値を持つ。本編ではこういう定義をしている。

#site {
  --total: 5;
  --scene: 1;
  --percentage: calc(var(--scene) / var(--total));
}
  1. ダブルハイフン(--)をつけ、とりあえず:rootまたは<html> 要素で変数を定義する。。
  2. 使いたい箇所で var(--変数名) と記述すると、定義した値を当てはめられる。
  3. CSS の変数で便利な点は、スコープを設定できることだ。以下、変数--primary-colorは:root要素で定義されているのでグローバルで、ドキュメント内のすべての要素でアクセスできる。さらに.section-subtitle の宣言ブロックのスコープ内で再定義すると、その新しい値は.section-subtitle 内でのみ機能する。
    :root {
      --primary-color: blue;
    }
     
    .section-subtitle {
      --primary-color: green;
      color: var(--primary-color);
    }

本編では、ページ捲りボタンを押す度に変動する value の値に併せて、CSS 変数を定義してある。

input[value="1"]:checked~#site {
  --scene: 1;
}
input[value="2"]:checked~#site {
  --scene: 2;
}
input[value="3"]:checked~#site {
  --scene: 3;
}
input[value="4"]:checked~#site {
  --scene: 4;
}
input[value="5"]:checked ~ #site {
  --scene: 5;
}
Fifth

セレクタ(1)

クラスセレクタまたは ID セレクタの設定方法

class="" もしくは id=""
使用できる文字は、アルファベットで始め、半角の英数字、ハイフン( - )、アンダーバー( _ )。
クラス名を複数指定の場合
<p class="example2 example3">文字色は blue</p>

CSS の基本構文

selector(セレクタ) { properties(プロパティ) :value(); }
「セレクタ」「プロパティ」「値」を設定すると CSS が利用できる。

隣接セレクタ

h3 + p
2 つのセレクタを接続し、 2 つ目の要素が 1 つ目の要素の 隣りにある要素のひとつだけ にあって、両者が同じ親要素の子同士である場合に一致する。
構文は、直前の要素 + 対象の要素 { スタイルプロパティ }

事例

/* CSS */
h3 + p {
  background-color: red;
  color: #fff;
}

h3 + p 隣接セレクタの結果

  • <div>
    • <h3>One
    • <p>Two
    • <p>Three
    • <div>
      • <p>Four

直下セレクタ

div > p
2 つの CSS セレクターの間に配置される。 2 つ目のセレクターが 1 つ目のセレクターの直接の子要素の場合にのみ一致する。
構文は、セレクタ 1 > セレクタ 2 { スタイルプロパティ }

事例

/* CSS */
div > p {
  background-color: red;
  color: #fff;
  line-height: 1;
  padding: 4px 6px;
  margin: 0;
  display: inline-block;
  border-radius: 6px;
}

直下セレクタ div > p の結果

  • <div>
    • <span>One
    • <p>Two
    • <main>
      • <p>Three

間接セレクタ

h3 ~ p
要素同士を結合子 「~」 で結ぶと、指定した要素の後にあるすべての兄弟要素(同じ階層の要素が対象となる要素(複数も可能))を選択することができる。
構文は、セレクター1 ~ セレクター2 { スタイルプロパティ }

事例

/* CSS */
h3 ~ p {
  background-color: red;
  color: #fff;
}

間接セレクタh3 ~ p の結果

  • <div>
    • <h3>One
    • <p>Two
    • <p>Three
    • <div>
      • <p>Four
Sixth

セレクタ(2)

否定擬似クラス

:not()
CSS上で特定の要素やクラス以外のものを適用させたい場合に使う疑似クラスである。
構文は、:not(除外したいセレクタ){ カッコで指定したもの以外に適用するCSS }

事例

/* CSS */
div.example-1 :not(p.exclude) {
  color: #fe001a;
}

結果

  • <div>
    • <p class="exclude">One
    • <p>Two
    • <p class="exclude">Three
    • <p>Four

全称セレクタ

*
全称セレクタはアスタリスク (*) で示す。これは文書内のすべての要素を選択する。例えば、 p * は <p> 要素内のすべての子要素を選択する。
* {
  font-weight: 16px;
}

marginとpaddingの指定は、bodyにpaddingがついているブラウザ(Opera)や、リスト要素などmarginの値が異なるため、このような初期化の設定にする。

*{
  margin:0;
  padding:0;

* の応用例

.example-b * { } の場合、要素セレクタのあとに全称セレクタを使用すると 任意の要素内の全ての要素に適用させることができる。

:root

:root {
  --main-color: hotpink;
  --pane-padding: 5px 42px;
}

:root は CSS の擬似クラスで、文書を表すツリーのルート要素を選択する。 HTML では :root は <html> 要素を表し、詳細度が高いことを除けば html セレクターと同等である。:root はグローバル(すべてのHTML要素で共通の属性や、CSSの変数などの CSS 変数を宣言するのに便利だ。

記号 「# , > + ~ * ^ $」

CSSで使われる記号も触れておこう。特定の文字列を含む属性値を持つ要素を選択する場合に使われる記号である。Markus Gabriel 氏のページでは、こういうのが出てくる。これは何だろう?

input[value="1"]:checked ~ * [data-scene]:not([data-scene="1"]) .heading {
  -webkit-transform: translateX(-25%);
          transform: translateX(-25%);
  opacity: 0;
}

「:not()」と「~」は、セッション First で出てくるものだ。後は「*」だ。

「~」は、同じ階層の要素が対象となる要素であり、対象になるのは「全ての[data-scene]について[data-scene="1"]ではないもの」で、「class="heading"」が設定されているものということになる。

その他 記号

部分一致する場合

a[href*="https"] {/* hrefのすぐあとに * を記述する */
  color: green; 
}

前方一致する場合

a[href^="example"] {
  color: green;
}

後方一致する場合

a[href$=".jp"] {
  color: orange;
}