Webページに息吹を吹き込む:`transform-style`で実現する3Dアニメーションとインタラクション


舞台を整える:用語解説

  • 平面化
    変換コンテキスト内の要素を2D平面に投影することです。
  • 変換コンテキスト
    3D変換が適用される要素とその子要素を含む領域のことです。
  • 3D空間
    奥行きのある空間のことです。Webページでは、通常2D空間(高さ、幅のみ)で表現されますが、transform-style を使用すると、要素を3D空間で配置したり、回転させたりすることができます。

主な演出家:transform-style の値

  • inherit: 親要素の transform-style を継承します。
  • preserve-3d: 変換コンテキスト内の要素は3D空間で保持されます。つまり、子要素は個別に3D空間で配置したり、回転させたりすることができます。
  • flat: デフォルト値です。変換コンテキスト内の要素は平面化され、3D空間での配置や回転は行われません。

実践:transform-style の使い道

  • 透視投影
    perspective プロパティと組み合わせて、奥行きのある3D空間を表現することができます。
  • カードエフェクト
    transform と組み合わせて、カードをめくるようなアニメーションを作成することができます。
  • 3Dキューブの作成
    preserve-3d を使用して親要素を3D空間で保持し、子要素を回転させて、まるでキューブが回転しているように見せることができます。
  • transform-style を使用して、魅力的な視覚効果やインタラクティブな要素を作成することができます。
  • transform-style は一部の古いブラウザではサポートされていない場合があります。
  • transform-style はパフォーマンスに影響を与える可能性があります。複雑な3Dアニメーションを使用する場合は、パフォーマンスを考慮する必要があります。


例1:3Dキューブ

.cube {
  width: 100px;
  height: 100px;
  perspective: 400px; /* 奥行きを調整 */
  transform-style: preserve-3d; /* 子要素を3D空間に配置 */
}

.face {
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #ccc;
  border: 1px solid #000;
}

.face.front {
  transform: translateZ(50px); /* 正面を前面へ配置 */
}

.face.back {
  transform: translateZ(-50px) rotateY(180deg); /* 背面を背面へ配置し、回転 */
}

.face.top {
  transform: translateY(-50px) rotateX(90deg); /* 上面を上面へ配置し、回転 */
}

.face.bottom {
  transform: translateY(50px) rotateX(-90deg); /* 底面を下面へ配置し、回転 */
}

.face.left {
  transform: translateX(-50px) rotateY(-90deg); /* 左面を左面へ配置し、回転 */
}

.face.right {
  transform: translateX(50px) rotateY(90deg); /* 右面を右面へ配置し、回転 */
}

このコードを実行すると、ブラウザ上に回転する3Dキューブが表示されます。各面には異なる色が設定されています。

例2:カードエフェクト

この例では、transformtransition を組み合わせて、カードをめくるようなアニメーションを作成します。

.card {
  width: 200px;
  height: 150px;
  background-color: #ccc;
  border: 1px solid #000;
  position: relative; /* 絶対配置にして、子要素を配置できるようにする */
  transform-style: preserve-3d; /* 子要素を3D空間に配置 */
  transition: transform 0.5s ease-in-out; /* アニメーション設定 */
}

.card-front,
.card-back {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  backface-visibility: hidden; /* 裏面を非表示にする */
}

.card-front {
  background-color: #f9f9f9;
  z-index: 2; /* 正面を前面へ配置 */
}

.card-back {
  background-color: #000;
  transform: rotateY(180deg); /* 背面を背面へ配置し、回転 */
  z-index: 1; /* 背面を背面へ配置 */
}

.card:hover {
  transform: rotateY(-90deg); /* カードを回転させる */
}

このコードを実行すると、ブラウザ上にカードが表示されます。マウスカーソルをカードの上に置くと、カードが回転して裏面が表示されます。

この例では、transform-styleperspective を組み合わせて、奥行きのある3D空間を表現します。

.container {
  width: 300px;
  height: 300px;
  perspective: 400px; /* 奥行きを調整 */
  transform-style: preserve-3d; /* 子要素を3D空間に配置 */
}

.item {
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: #ccc;
  border: 1px solid #000;
  transform: translateZ(calc(n * -100px)); /* 奥行き方向に配置 */
}

.item:nth-child(1) {
  transform: translateZ(0); /* 最前面に配置 */
}

このコードを実行すると、ブラウザ上に3つのアイテムが奥行きを持って配置されます。



単純な2D変換

  • transform プロパティのみを使用して、要素を2D空間で回転、移動、スケーリングすることができます。これは、3D効果が不要な場合や、パフォーマンスが問題となる場合に有効です。

例:

.element {
  transform: rotate(45deg) translate(20px, 30px);
}

疑似要素と position プロパティ

  • 疑似要素と position プロパティを組み合わせて、疑似3D効果を作成することができます。これは、比較的単純な3D効果が必要な場合に有効です。
.box {
  position: relative;
  width: 100px;
  height: 100px;
  background-color: #ccc;
}

.box::before,
.box::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #ccc;
  transform: perspective(400px); /* 奥行きを調整 */
}

.box::before {
  transform: rotateY(45deg); /* 正面を回転 */
  z-index: 2; /* 正面を前面へ配置 */
}

.box::after {
  transform: rotateY(-45deg); /* 背面を回転 */
  z-index: 1; /* 背面を背面へ配置 */
}
  • Three.jsなどのJavaScriptライブラリを使用すると、より高度な3Dグラフィックとアニメーションを作成することができます。これは、複雑な3D表現が必要な場合に有効です。
  • アクセシビリティ: 3D効果は、視覚障害を持つユーザーにとって理解しにくい場合があります。アクセシビリティを考慮する場合は、代替テキストなどの補助手段を提供する必要があります。
  • パフォーマンス: 複雑な3D効果は、パフォーマンスに影響を与える可能性があります。パフォーマンスが問題となる場合は、transform-style の使用を控え、代替方法を検討する必要があります。
  • ブラウザサポート: 上記の代替方法はすべて、すべてのブラウザで完全にサポートされているわけではありません。古いブラウザとの互換性を考慮する必要がある場合は、注意が必要です。