CSS / animation

transition を使ってアニメーションを実装する 2

─ Guide to page sections ─

アニメーションを組み立てる場合に於いても、CSS が複雑に且つ秀逸な機能を伴って絡み合ってくる。より複雑なものは整理して簡潔化が求められる。新しい方式を日常の中でさっらっとフィックスしてアップデートしていかねばならないのが現状である。

object-position: left
CSS変数を使ったアニメーションの例

First

2 つのセレクターの接続

セレクターを接続すれば、面白いギミックを仕掛けることができる。それが顕著な働きをするのが、前回のページに掲載した「:checked」をトリガーにした仕掛けである。

CSS のセレクタは次の4種類の結合子を使って階層指定を行うことができる。

一般兄弟結合子 ~

一般兄弟結合子 (general sibling combinator, ~) は 2 個のセレクターを結びつけ、 1 つ目の要素の後に 2 つ目の要素のがあり(直後である必要はない)、かつ両者が同じ親要素の子であるすべてのパターンに一致する。

A
B

上のように、A ボタンにマウスポインターを乗せると、B ボタンの色が変化する。こういうときは、一般兄弟結合子(~)を使う。

<div class="box-A">
A
</div>
<div class="box-B">
B
</div>
.box-A{
  background-color: lightblue;
  width: 50px;
  height: 50px;
}
.box-B{
  background-color: lightpink;
  width: 50px;
  height: 50px;
  transition: all .3s;
}
.box-A:hover ~ .box-B {
   background-color: lightgreen;
}

隣接兄弟結合子 +

隣接兄弟結合子 (adjacent sibling combinator, +) は 2 つのセレクターを接続し、 2 つ目の要素が 1 つ目の要素の直後にあって、両者が同じ親要素の子同士である場合に一致する。セレクタを「+(プラス)」で繋げる階層指定である。

以下のように、C ボタンにマウスポインターを乗せると、D ボタンの色が変化する。こういうときは、隣接兄弟結合子(+)も使うことができる。

C
D
<div class="box-C">
C
</div>
<div class="box-D">
D
</div>
.box-C{
  background-color: lightblue;
  width: 50px;
  height: 50px;
}
.box-D{
  background-color: lightpink;
  width: 50px;
  height: 50px;
  transition: all .3s;
}
.box-A:hover + .box-B {
   background-color: steelblue;
}

子結合子 >

子結合子 (child combinator) 「>」 は 2 つの CSS セレクターの間に配置される。 半角スペース区切り(子孫セレクタ)だと、子要素の中の要素(孫要素)にまでスタイルが適用されるが、「>」をつけることで1つ下の階層の子要素にのみ CSSが適用される

First layer

Second layer

First layer

Second layer

<main>
  <p>First layer</p>
  <div>
    <p>Second layer</p>
  </div>
  <p>First layer</p>
  <div>
    <p>Second layer</p>
  </div>
</main>
main p {
  color: #333;;
  line-height: 30px;
}
main > p {
  color: white;
  background-color: lightpink;
}

子孫結合子 半角スペース

セレクタを半角スペースで繋ぐ結合子であり、階層指定である。例えば第一階層と第二階層のリストマークを違う形に指定したのが以下の例である。

  • Item 1
    • Subitem A
    • Subitem B
  • Item 2
    • Subitem A
    • Subitem B
<ul class="descendant">
  <li>
    <div>Item 1</div>
    <ul>
      <li>Subitem A</li>
      <li>Subitem B</li>
    </ul>
  </li>
  <li>
    <div>Item 2</div>
    <ul>
      <li>Subitem A</li>
      <li>Subitem B</li>
    </ul>
  </li>
</ul>
ul.descendant li {
  list-style-type: disc;
}

ul.descendant li li {
  list-style-type: circle;
}

Second

CSS変数(CSS variables:カスタムプロパティ)はとても便利

CSS変数は、文書全体で再利用可能な特定の識別可能な要素(エンティティ)である。変数を宣言し、値を代入することだけだと覚えている諸君、ちょっと待ってくれ!この先からが新世界の展開が待っている。

CSS 変数の構文はたとえば --main-color: black; というように設定する。変数名を定義するには「--」で始まる必要がある。そしてcolor: var(--main-color); でアクセスする。

CSSのスコープ(影響範囲)で取り扱う

特定のスコープ(セレクタ内)に限定して変数を定義したい場合は、以下のように書くことができる。

:root {
  --primary-color: darkorange;
}
.selector-A {
  --primary-color: cadetblue;
  color: var(--primary-color); // cadetblue が適用される
}

そして、次の場合。これを理解して使いまわせることが重要。

カスタムプロパティ記法で特定のふたつのスコープに(--clr:darkorange;)と(--clr:cadetblue;)を設定する。つまりここで別々のリストタグの色をそれぞれ指定した。

var() 関数を次(-webkit-text-stroke: 1px var(--clr);)のように CSS 内に記述してアクセスするストロークする色を定義した。

こうすると、視覚的にストロークする色を指定することができるし、ひとつの CSS(-webkit-text-stroke: 1px var(--clr); )を使い回せるという利点が出来上がる。

<ul>
  <li style="--clr:darkorange;">
  Jaco&nbsp;Pastorius
  </li>
</ul>
<ul>
  <li style="--clr:cadetblue;">
  Joe&nbsp;Sample
  </li>
</ul>

これが結果である。

  • Jaco Pastorius
  • Joe Sample
ul {
  position: relative;
}
ul li {
  list-style: none;
  position: relative;
}

ul li {
  position: relative; 
  text-decoration: none;
  font-size: 2em;
  font-weight: 900;
  line-height: 2em;
  letter-spacing: 2px;
  color:transparent; 
  -webkit-text-stroke: 1px var(--clr); 
}

Third

スクロールで発火させる「inview.js」

以前、「段落にアニメーションを常備する」というページを作った。このセクションはそのページに付加する内容である。

その内容は、スクロールしたとき、ある特定の領域にトリガーを仕込むというものだが、とても簡単な方法なので追加でご紹介しよう。

スクロールすると、jQueryプラグインの「inview.js」で定義した領域に入ると、発火しアニメーションを開始する。上から、下からも「inview.js」で定義した領域に入ると発火する。

「inview.js」の設定は簡単である。むしろ、どういうアニメーションを展開させるか、というのが問題になるだろう。実際に「inview.js」を動かしたデモページを制作したのでご覧いただこう。尚、「inview.js」の設定については詳しくは説明していないが、デモページをご覧いただければ、大概は察しが付く筈である。

CSS のネスト

尚、この場面で気づきを得て CSS のネストを使い始めるきっかけとなる(ソースをご覧ください)。CSS のネストはセレクタを繰り返す必要性を減らし、関連する要素のスタイルルールを同じ場所に配置することで、誤記も減り整理がとても容易くなる。

参考:CSSのネストがついにブラウザで使用できるようになった! 基礎知識、便利な使い方を詳しく解説


Fourth

アニメーション

CSS変数を使ったアニメーション

特定の領域に入ると起動するのが以下のようなアニメーションである。セクション Third のデモページで使ったものだが、少し難しい。

上のアニメーションを応用して、特定領域にスクロールされるとあるクラス名が付与されるというのが inview.js なので、その仕様に併せて CSS を追加・修正することになる。

CSS アニメーションまたは CSS トランジションを使用すると、特定の CSS プロパティをアニメーションさせることができ、そのプロパティはこんなにも多く存在する

CSS トランジションを使用したアニメーションは、いくつもの試作を通して、たとえば transition-duration(変化の時間の指定)、たとえばtransition: width 1s (1秒かけてwidthプロパティを変更する)などの時間をいくつか変更を試してみるだけでも大きく異なる結果になるので、体感的な作り方を身に付けることが肝心である。

その他アニメーションの例

Are U experienced?

width: fit-content;
    Are U experienced?    

Let it be

When I find myself in times of trouble Mother Mary comes to me Speaking words of wisdom Let it be


Fifth

data属性

「content:attr(data-text);」という馴染みのない記述がある。 CSS の擬似要素(::beforeや::after)の中に入る要素は、CSS の content で指定することができ、attr() を使用すると htmlから属性を取得することができるというものだ。contentには color や background-color などのプロパティも併せて記述できる。

data属性を使った例 1

  • Goods A
  • Goods B
  • Goods C
  • Goods D
  • Goods E
<ul class="stock">
  <li data-stock="5">Goods A</li>
  <li data-stock="3">Goods B</li>
  <li data-stock="0">Goods C</li>
  <li data-stock="3">Goods D</li>
  <li data-stock="0">Goods E</li>
</ul>
.stock li[data-stock="0"] {
  color: #ccc;
}

attr(data-text)を使った例 2

  • 本格的なアニメーションは、複数のアニメーションを「:checked」をトリガーにして多重構造で動かす。これを実行するには速度を操作する「transition」が最適である。
  • flex プロパティの省略、デフォルト、initial、など総当たりで検証を進めて flex プロパティの内容の理解を確定させる。
  • Intersection Observer でスクロール中のビューポートを検知し、索引キーワードを捕捉する。モバイルでの解説はBootstrap v5 のモーダルを設置してボタンをタップするとモーダルがフルスクリーンで開く。
<ul id="makingDate">
  <li data-post-date="2023-08-07";>本格的な…最適である。</li>
  <li data-post-date="2023-08-07";>flex プロパティの…確定させる。</li>
  <li data-post-date="2023-07-08";>Intersection Observer …で開く。</li>
</ul>
#makingDate li:before{
	content:attr(data-post-date);
	color: #fff;
	padding: 0 4px;
	background-color: #4ca9f7;
	border-radius: 4px;
	margin-right:1em;
}

attr(data-text)を使った例 3

IAEA は、軍事利用と直接関係のない「原発の安全性」について、強制力を伴う指示や勧告はできない。

<p class="verification" data-text="(ここに data-text でアクセスされた内容が入る)" style="margin-bottom: 1em;">IAEA は、軍事利用と直接関係のない「原発の安全性」について、強制力を伴う指示や勧告はできない。</p>
p.verification:after {
  content: attr(data-text)"";
  background-color: #4ca9f7;
  color: #fff;
  padding: 0 4px;
}

以下文字の「The IAEA」の部分にマウスを載せるか、ロングタップすると、文字列がチェンジする。

The official name is The IAEA

<p style="border: 1px dashed rgba(0 0 0 / 0.2); padding: 0.5rem; background: url(images/stripe_green.svg) center;">The official name is <a class="defined" href="#" id="style-2" data-replace="The International Atomic Energy Agency"><span>The IAEA</span></a></p>

以下 CSS にはネストを含んでいる。

a.defined {
  overflow: hidden;
  position: relative;
  display: inline-block;

  &::before, &::after {
    content: "";
    position: absolute;
    width: 100%;
    left: 0;
  }

  &::before {
    height: 2px;
    bottom: 0;
    transform-origin: 100% 50%;
    transform: scaleX(0);
    transition: transform 0.6s cubic-bezier(0.76, 0, 0.24, 1);
  }

  &::after {
    content: attr(data-replace);
    height: 100%;
    top: 0;
    transform-origin: 100% 50%;
    transform: translate3d(200%, 0, 0);
    transition: transform 0.5s cubic-bezier(0.76, 0, 0.24, 1);
    color: dodgerblue;
  }
}

a.defined:hover {
  &::before {
    transform-origin: 0% 50%;
    transform: scaleX(1);
  }

  &::after {
    transform: translate3d(0, 0, 0);
  }
}

a.defined span {
  display: inline-block;
  transition: transform 0.5s cubic-bezier(0.76, 0, 0.24, 1);
}
a.defined:hover span {
  transform: translate3d(-200%, 0, 0);
}
/* Presentational Styles */
a.defined {
  font-weight: 700;
  text-align: left;
  color: dodgerblue;
  text-decoration: none;
}
.defined {
  width: 100%;
}