【CSS】rotateの使い方:要素や画像の回転とアニメーション

css-rotate
ポートフォリオ向けサーバー
HTML/CSSスキルが活きる!
学んだ知識を活かして、
自分だけのブログを始めませんか?

WordPressブログなら、あなたのコーディング知識でデザインのカスタマイズが自由自在。
ブログデビューに最適な初心者向けサーバー環境を徹底比較しました。

CSSの回転は、かつてのtransform一括指定から独立したrotateプロパティへと進化し、直感的かつ安全な実装が可能になりました。

本記事では、角度や基準点の基本設定、立体的な3D表現、ホバーアニメーション、「効かない」時の解決策まで、実務で必須のテクニックを網羅して解説します。

HTML/CSS学習者の方へ
「学んだコード、自分のブログで試してみませんか?」
多くのブロガーがデザインでつまずく中、コードが読めるあなたは圧倒的に有利です。
自由自在なサイト構築の第一歩となる、初心者向けサーバーを分かりやすく比較しました。

\ スキルを活かして情報発信 / ブログ向けレンタルサーバー4選を読む▶︎
目次

要素を回転!rotateとtransformの違い

Webデザインにおいて、アイコンの向きを変えたり、カードを少し傾けて配置したりする際に欠かせないのが「要素の回転」です。

CSSで要素を回転させる方法として、これまではtransformプロパティを使うのが常識でしたが、現代のCSSでは独立したrotateプロパティが追加され、直感的に記述できるようになりました。

ここでは、rotatetransformの書き方の違い、角度・軸の指定方法を解説します。

要素を回転!rotateとtransformの違い
  • 独立したrotateプロパティとtransform: rotate()の違い
  • 90度・180度など角度の指定方法
  • X軸・Y軸・Z軸での回転と逆回転(マイナス値)

独立したrotateプロパティとtransform: rotate()の違い

かつて要素を回転させるには、transform: rotate(45deg);と記述するしかありませんでした。

しかし現在では、シンプルにrotate: 45deg;と記述できる独立したプロパティが主要ブラウザでサポートされています。

この2つの最大の違いは、「他の変形プロパティ(移動や拡大縮小)と競合するかどうか」です。

変形を扱うには、「移動・拡大・回転を組み合わせる実務では、競合事故を防ぐためにtransformにまとめるのではなく、独立したtranslatescalerotateプロパティに分けて記述すること」です。

⭕️ ホバーしてみよう!独立プロパティなら移動(translate)を邪魔せずに回転できる!

❌ 罠
(元の位置に戻る)
⭕️ 成功
(その場で回転)
/* ❌ 罠:ホバー時に transform を丸ごと上書きしてしまう */
.box-fail {
  transform: translateX(50px); /* 💡 右に50px移動させている */
}
.box-fail:hover {
  transform: rotate(10deg); /* 🚨 translateXが消え、元の位置に戻ってしまう! */
}

/* ⭕️ 独立した rotate プロパティを使う! */
.box-success {
  translate: 50px 0; /* 💡 独立プロパティで移動 */
}
.box-success:hover {
  rotate: 10deg; /* 💡 translate を保持したまま、その場で安全に回転する! */
}
HTMLコード表示
<div class="rot-basic-wrapper">
  
  <p class="rot-basic-caption">⭕️ ホバーしてみよう!独立プロパティなら移動(translate)を邪魔せずに回転できる!</p>

  <div class="rot-basic-demo-area">
    
    <div class="rot-box-container">
      <div class="rot-box is-trap-transform">
        ❌ 罠<br>(元の位置に戻る)
      </div>
    </div>

    <div class="rot-box-container">
      <div class="rot-box is-success-rotate">
        ⭕️ 成功<br>(その場で回転)
      </div>
    </div>

  </div>

  <div class="rot-basic-code-area">
    <span class="hl-comment">/* ❌ 罠:ホバー時に transform を丸ごと上書きしてしまう */</span><br>
    <span class="hl-blue">.box-fail</span> {<br>
      <span class="hl-green">transform:</span> <span class="hl-red">translateX(50px);</span> <span class="hl-comment">/* 💡 右に50px移動させている */</span><br>
    }<br>
    <span class="hl-blue">.box-fail:hover</span> {<br>
      <span class="hl-green">transform:</span> <span class="hl-red">rotate(10deg);</span> <span class="hl-comment">/* 🚨 translateXが消え、元の位置に戻ってしまう! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 独立した rotate プロパティを使う! */</span><br>
    <span class="hl-blue">.box-success</span> {<br>
      <span class="hl-green">translate:</span> <span class="hl-red">50px 0;</span> <span class="hl-comment">/* 💡 独立プロパティで移動 */</span><br>
    }<br>
    <span class="hl-blue">.box-success:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">10deg;</span> <span class="hl-comment">/* 💡 translate を保持したまま、その場で安全に回転する! */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-basic-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-basic-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-basic-demo-area {
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 30px;
  align-items: center;
}

.rot-box-container {
  width: 100%;
  max-width: 300px;
  border-left: 2px dashed #adb5bd; /* 元の位置の目印 */
  padding-bottom: 10px;
}

.rot-box {
  width: 120px;
  height: 80px;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  text-align: center;
  line-height: 1.4;
  cursor: pointer;
  transition: all 0.3s ease;
}

/* === ❌ 罠:transformの上書き === */
.is-trap-transform {
  background-color: #dc3545;
  /* 初期位置:右に50px移動 */
  transform: translateX(50px);
}
.is-trap-transform:hover {
  /* 🚨 transformを上書きしたため、translateX(50px)が消去される */
  transform: rotate(15deg);
}

/* === ⭕️ 成功:独立rotateプロパティ === */
.is-success-rotate {
  background-color: #0d6efd;
  /* 独立したtranslateで移動 */
  translate: 50px 0;
}
.is-success-rotate:hover {
  /* 💡 translateはそのままに、rotateだけが適用される */
  rotate: 15deg;
}

/* =コード解説エリア= */
.rot-basic-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

transformの使い方を詳しく知りたい人は「【CSS】transformの使い方:移動・回転・拡大と効かない時の対策」を一読ください。

90度・180度など角度の指定方法

回転をさせる際、よく使われるのが「度数」を指定するdegです。

直角に曲げる90degや上下をひっくり返す180deg、さらには斜めのデザインを作る45degなど、あらゆる角度を数値で指定できます。

また、1周させたい時などには、「回転数」を表すturn(例:1turn= 360度、0.5turn= 180度)や数学的な radという単位も利用可能です。

角度を指定するには、「数値と単位(degturn)を隙間なくピッタリくっつけて記述することです。

そして、アニメーション等で何周も回転させる場合は、720degと書くよりも2turnと書いた方がコードの意図が伝わりやすいため、単位を使い分けることです。

⭕️ ホバーしてみよう!deg(度数)やturn(回転数)を使って要素を回せ!

45deg

斜め

90deg

直角(右向き)

180deg
(0.5turn)

上下反転

360deg
(1turn)

1回転

/* ❌ 罠:単位がない、またはスペースが空いていると無効になる */
.box-fail {
  rotate: 90; /* 🚨 単位(deg)がないためエラー */
  rotate: 45 deg; /* 🚨 スペースがあるためエラー */
}

/* ⭕️ 隙間なく単位を付け、状況に応じて deg と turn を使い分ける! */
.box-45 {
  rotate: 45deg; /* 💡 css rotate 45 degrees */
}
.box-180 {
  rotate: 180deg; /* 💡 css rotate 180 degrees (0.5turnでも可) */
}
.box-360 {
  rotate: 1turn; /* 💡 1周以上回す時は turn の方が直感的 */
}
HTMLコード表示
<div class="rot-deg-wrapper">
  
  <p class="rot-deg-caption">⭕️ ホバーしてみよう!deg(度数)やturn(回転数)を使って要素を回せ!</p>

  <div class="rot-deg-demo-area">
    
    <div class="deg-item">
      <div class="deg-box is-45deg">45deg</div>
      <p class="deg-desc">斜め</p>
    </div>

    <div class="deg-item">
      <div class="deg-box is-90deg">90deg</div>
      <p class="deg-desc">直角(右向き)</p>
    </div>

    <div class="deg-item">
      <div class="deg-box is-180deg">180deg<br>(0.5turn)</div>
      <p class="deg-desc">上下反転</p>
    </div>

    <div class="deg-item">
      <div class="deg-box is-1turn">360deg<br>(1turn)</div>
      <p class="deg-desc">1回転</p>
    </div>

  </div>

  <div class="rot-deg-code-area">
    <span class="hl-comment">/* ❌ 罠:単位がない、またはスペースが空いていると無効になる */</span><br>
    <span class="hl-blue">.box-fail</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">90;</span> <span class="hl-comment">/* 🚨 単位(deg)がないためエラー */</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">45 deg;</span> <span class="hl-comment">/* 🚨 スペースがあるためエラー */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 隙間なく単位を付け、状況に応じて deg と turn を使い分ける! */</span><br>
    <span class="hl-blue">.box-45</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">45deg;</span> <span class="hl-comment">/* 💡 css rotate 45 degrees */</span><br>
    }<br>
    <span class="hl-blue">.box-180</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">180deg;</span> <span class="hl-comment">/* 💡 css rotate 180 degrees (0.5turnでも可) */</span><br>
    }<br>
    <span class="hl-blue">.box-360</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">1turn;</span> <span class="hl-comment">/* 💡 1周以上回す時は turn の方が直感的 */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-deg-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-deg-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-deg-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: space-around;
}

.deg-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
}

.deg-box {
  width: 80px;
  height: 80px;
  background-color: #0d6efd;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  border-top: 4px solid #ffc107; /* 回転が分かりやすいように上に黄色い線を引く */
  transition: rotate 0.5s ease;
  cursor: pointer;
}

.deg-desc {
  margin: 0;
  font-size: 13px;
  color: #333;
  font-weight: bold;
}

/* === 💡 角度・単位の指定 === */
.deg-item:hover .is-45deg {
  rotate: 45deg;
}

.deg-item:hover .is-90deg {
  rotate: 90deg;
}

.deg-item:hover .is-180deg {
  /* 0.5turn と書いても 180deg と全く同じ意味になる */
  rotate: 0.5turn; 
}

.deg-item:hover .is-1turn {
  /* 360deg は 1turn と書くとスマート */
  rotate: 1turn; 
}

/* =コード解説エリア= */
.rot-deg-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

X軸・Y軸・Z軸での回転と逆回転(マイナス値)

平面的な回転だけでなく、要素を奥行きや横方向にくるっと裏返すような3D回転も可能です。

独立したrotateプロパティでは、軸の指定を前につけてrotate: x 45deg;rotate: y 180deg;、標準の平面回転であるrotate: z 90deg;のように記述します。(複合も可能です。)

また、回転方向を制御したい場合、正の数値なら時計回り、マイナスの数値(例:-90deg)を指定すれば反時計回りになります。

3D回転を実装するには、「X軸やY軸で回転させて立体感を出したい場合は、要素の『親要素』に対してperspective: 1000px;(遠近感)を指定すること」です。

これにより、手前が大きく奥が小さく見えるリアルな3D回転が実現します。

⭕️ ホバーしてみよう!3D回転(X・Y)は親要素に遠近感(perspective)を持たせろ!

反時計回り
(-90deg)
Y軸(遠近感なし)
潰れて見える
Y軸(遠近感あり)
立体的に回る
/* 💡 方向(direction)の制御:マイナスをつければ反時計回り */
.box-counter-clockwise {
  rotate: -90deg;
}

/* ❌ 罠:perspective(遠近感)を指定せずに3D回転させる */
.box-y-flat:hover {
  rotate: y 60deg; /* 🚨 平面的に幅が縮んだようにしか見えない! */
}

/* ⭕️ 3D回転させる要素の「親」に perspective を指定する! */
.parent-wrapper {
  perspective: 800px; /* 💡 カメラからの距離感を設定 */
}
.box-y-3d:hover {
  rotate: y 60deg; /* 💡 手前が大きく、奥が小さく立体的に回る! */
}
HTMLコード表示
<div class="rot-axis-wrapper">
  
  <p class="rot-axis-caption">⭕️ ホバーしてみよう!3D回転(X・Y)は親要素に遠近感(perspective)を持たせろ!</p>

  <div class="rot-axis-demo-area">
    
    <div class="axis-item">
      <div class="axis-box is-minus">
        反時計回り<br>(-90deg)
      </div>
    </div>

    <div class="axis-item">
      <div class="axis-box is-y-flat">
        Y軸(遠近感なし)<br>潰れて見える
      </div>
    </div>

    <div class="axis-item has-perspective">
      <div class="axis-box is-y-3d">
        Y軸(遠近感あり)<br>立体的に回る
      </div>
    </div>

  </div>

  <div class="rot-axis-code-area">
    <span class="hl-comment">/* 💡 方向(direction)の制御:マイナスをつければ反時計回り */</span><br>
    <span class="hl-blue">.box-counter-clockwise</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">-90deg;</span><br>
    }<br><br>

    <span class="hl-comment">/* ❌ 罠:perspective(遠近感)を指定せずに3D回転させる */</span><br>
    <span class="hl-blue">.box-y-flat:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">y 60deg;</span> <span class="hl-comment">/* 🚨 平面的に幅が縮んだようにしか見えない! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 3D回転させる要素の「親」に perspective を指定する! */</span><br>
    <span class="hl-blue">.parent-wrapper</span> {<br>
      <span class="hl-green">perspective:</span> <span class="hl-red">800px;</span> <span class="hl-comment">/* 💡 カメラからの距離感を設定 */</span><br>
    }<br>
    <span class="hl-blue">.box-y-3d:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">y 60deg;</span> <span class="hl-comment">/* 💡 手前が大きく、奥が小さく立体的に回る! */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-axis-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-axis-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-axis-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: space-around;
}

.axis-item {
  /* ベースの親要素 */
}

/* 💡 親要素にperspective(遠近感)を設定する */
.has-perspective {
  perspective: 800px;
}

.axis-box {
  width: 120px;
  height: 120px;
  background-color: #6f42c1;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  border-top: 4px solid #ffc107;
  transition: rotate 0.5s ease;
  cursor: pointer;
  line-height: 1.5;
}

/* === 💡 マイナス値で反時計回り === */
.axis-item:hover .is-minus {
  rotate: -90deg; /* css rotate counter clockwise */
}

/* === ❌ 罠:遠近感のないY軸回転 === */
.axis-item:hover .is-y-flat {
  rotate: y 60deg; /* 立体感がなく潰れて見える */
}

/* === ⭕️ 成功:遠近感のあるY軸回転 === */
.axis-item:hover .is-y-3d {
  rotate: y 60deg; /* perspectiveのおかげで扉のように立体的に開く */
}

/* =コード解説エリア= */
.rot-axis-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

回転の中心を操る!transform-origin(基準点)

要素を回転させる際、「どこを中心にして回るか」はデザインの仕上がりを大きく左右します。

画鋲を真ん中に刺して回すのか、それとも端に刺して振り子のように回すのかを決めるのが、transform-originプロパティです。

単なる回転から「開閉するドア」や「揺れるベル」のような高度なアニメーションへと表現の幅が広がります。

回転の中心を操る!transform-origin(基準点)
  • デフォルトの中央から基準点をずらす
  • 指定した座標や要素の端を中心に回転させる

デフォルトの中央から基準点をずらす

CSSで要素を回転させると、初期設定では要素の「中央」を基準に回転します。

ただし、「時計の針」や「メニューのドロップダウンアイコン」を作りたい場合、中心で回ってしまうと意図した動きになりません。

このような時にtransform-originを使って基準点をずらします。

回転の基準点を扱うには、「回転によって周囲のレイアウトに干渉するリスクがある場合、デフォルトの『中央』に頼らず、transform-origin: bottom center;のように安全な位置へ基準点をずらし、回転時の軌道をコントロールすること」です。

⭕️ ホバーしてみよう!基準点(画鋲の位置)が違うだけで、回る軌道が全く変わる!

デフォルト
(中央)
下部中央
(bottom)
/* ❌ 罠(または初期値):中央を軸にするため、四隅が大きくはみ出す */
.box-center {
  /* 💡 指定しなくても transform-origin: 50% 50%;(center)が適用されている */
  transition: rotate 0.3s ease;
}
.box-center:hover {
  rotate: 45deg;
}

/* ⭕️ 必要に応じて基準点をずらし、回転の軌道を制御する! */
.box-bottom {
  transform-origin: bottom center; /* 💡 基準点(画鋲)を「下部の中央」に刺す */
  transition: rotate 0.3s ease;
}
.box-bottom:hover {
  rotate: 45deg; /* 💡 ワイパーのように下を軸にして回る! */
}
HTMLコード表示
<div class="origin-basic-wrapper">
  
  <p class="origin-basic-caption">⭕️ ホバーしてみよう!基準点(画鋲の位置)が違うだけで、回る軌道が全く変わる!</p>

  <div class="origin-basic-demo-area">
    
    <div class="origin-item">
      <div class="origin-box is-center">
        <span class="pin pin-center"></span>
        デフォルト<br>(中央)
      </div>
    </div>

    <div class="origin-item">
      <div class="origin-box is-bottom">
        <span class="pin pin-bottom"></span>
        下部中央<br>(bottom)
      </div>
    </div>

  </div>

  <div class="origin-basic-code-area">
    <span class="hl-comment">/* ❌ 罠(または初期値):中央を軸にするため、四隅が大きくはみ出す */</span><br>
    <span class="hl-blue">.box-center</span> {<br>
      <span class="hl-comment">/* 💡 指定しなくても transform-origin: 50% 50%;(center)が適用されている */</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span><br>
    }<br>
    <span class="hl-blue">.box-center:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">45deg;</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 必要に応じて基準点をずらし、回転の軌道を制御する! */</span><br>
    <span class="hl-blue">.box-bottom</span> {<br>
      <span class="hl-green">transform-origin:</span> <span class="hl-red">bottom center;</span> <span class="hl-comment">/* 💡 基準点(画鋲)を「下部の中央」に刺す */</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span><br>
    }<br>
    <span class="hl-blue">.box-bottom:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">45deg;</span> <span class="hl-comment">/* 💡 ワイパーのように下を軸にして回る! */</span><br>
    }
  </div>

</div>
CSSコード表示
.origin-basic-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.origin-basic-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.origin-basic-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 50px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.origin-item {
  position: relative;
  width: 120px;
  height: 120px;
  border: 1px dashed #adb5bd; /* 元の位置のガイド */
  display: flex;
  align-items: center;
  justify-content: center;
}

.origin-box {
  position: absolute;
  width: 120px;
  height: 120px;
  background-color: #0d6efd;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  cursor: pointer;
  transition: rotate 0.4s ease;
  line-height: 1.5;
}

/* 画鋲(基準点)の視覚的表現 */
.pin {
  position: absolute;
  width: 10px;
  height: 10px;
  background-color: #ffc107;
  border-radius: 50%;
  border: 2px solid #333;
  z-index: 10;
}

/* === 💡 1. デフォルト(中央) === */
.is-center {
  /* transform-origin: center; が暗黙的に適用されている */
}
.is-center:hover {
  rotate: 45deg;
}
.pin-center {
  top: 50%;
  left: 50%;
  translate: -50% -50%;
}

/* === 💡 2. 基準点を下にずらす === */
.is-bottom {
  /* 基準点を「下側の中央」に指定 */
  transform-origin: bottom center;
}
.is-bottom:hover {
  rotate: 45deg;
}
.pin-bottom {
  bottom: 0;
  left: 50%;
  translate: -50% 50%;
}

/* =コード解説エリア= */
.origin-basic-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

指定した座標や要素の端を中心に回転させる

transform-originは、top leftなどのキーワードだけでなく、20px 50pxのような具体的な座標や0% 100%のようなパーセンテージを使って、任意の点を中心にした回転を細かく制御できます。

例えば、看板が片方のネジだけでぶら下がって揺れるようなアニメーションは、基準点を要素の左上(top leftまたは0% 0%)に設定することで実現します。

このように、中心から離れた点を指定することで、物理法則に則ったリアルな動きを表現できます。

座標を指定するには、「数値で指定する際は『X軸(横)、Y軸(縦)』の順番を厳守すること。また、要素の四隅や辺の中央を指定するだけであれば、順番の入れ替えエラーが起きないキーワード指定(top leftbottom right)を優先して使用すること」です。

⭕️ ホバーしてみよう!端(角)を基準点(anchor)にすると、リアルな物理アニメーションが作れる!

左上
(top left)
右下
(100% 100%)
/* ❌ 罠:X軸とY軸の順番を勘違いして指定する */
.box-fail {
  transform-origin: 100% 0%; /* 🚨 「下側・左端」のつもりで書くと、「右端・上側」になってしまう! */
}

/* ⭕️ 安全なキーワード指定か、「X軸(横) + Y軸(縦)」の順で書く! */
.box-top-left {
  transform-origin: top left; /* 💡 左上の角をピボットポイントにする */
}
.box-top-left:hover {
  rotate: 45deg; /* 💡 看板がぶら下がるように回る */
}

.box-bottom-right {
  transform-origin: 100% 100%; /* 💡 X軸が100%(右)、Y軸が100%(下) = bottom right と同じ意味 */
}
.box-bottom-right:hover {
  rotate: -45deg;
}
HTMLコード表示
<div class="origin-adv-wrapper">
  
  <p class="origin-adv-caption">⭕️ ホバーしてみよう!端(角)を基準点(anchor)にすると、リアルな物理アニメーションが作れる!</p>

  <div class="origin-adv-demo-area">
    
    <div class="origin-item">
      <div class="origin-box is-top-left">
        <span class="pin pin-top-left"></span>
        左上<br>(top left)
      </div>
    </div>

    <div class="origin-item">
      <div class="origin-box is-bottom-right">
        <span class="pin pin-bottom-right"></span>
        右下<br>(100% 100%)
      </div>
    </div>

  </div>

  <div class="origin-adv-code-area">
    <span class="hl-comment">/* ❌ 罠:X軸とY軸の順番を勘違いして指定する */</span><br>
    <span class="hl-blue">.box-fail</span> {<br>
      <span class="hl-green">transform-origin:</span> <span class="hl-red">100% 0%;</span> <span class="hl-comment">/* 🚨 「下側・左端」のつもりで書くと、「右端・上側」になってしまう! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 安全なキーワード指定か、「X軸(横) + Y軸(縦)」の順で書く! */</span><br>
    <span class="hl-blue">.box-top-left</span> {<br>
      <span class="hl-green">transform-origin:</span> <span class="hl-red">top left;</span> <span class="hl-comment">/* 💡 左上の角をピボットポイントにする */</span><br>
    }<br>
    <span class="hl-blue">.box-top-left:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">45deg;</span> <span class="hl-comment">/* 💡 看板がぶら下がるように回る */</span><br>
    }<br>
    <br>
    <span class="hl-blue">.box-bottom-right</span> {<br>
      <span class="hl-green">transform-origin:</span> <span class="hl-red">100% 100%;</span> <span class="hl-comment">/* 💡 X軸が100%(右)、Y軸が100%(下) = bottom right と同じ意味 */</span><br>
    }<br>
    <span class="hl-blue">.box-bottom-right:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">-45deg;</span><br>
    }
  </div>

</div>
CSSコード表示
.origin-adv-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.origin-adv-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.origin-adv-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 50px;
  background-color: #e9ecef;
  padding: 60px 20px; /* 回転時のゆとりを持たせる */
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.origin-item {
  position: relative;
  width: 120px;
  height: 120px;
  border: 1px dashed #adb5bd; /* 元の位置のガイド */
  display: flex;
  align-items: center;
  justify-content: center;
}

.origin-box {
  position: absolute;
  width: 120px;
  height: 120px;
  background-color: #6f42c1;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  cursor: pointer;
  transition: rotate 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); /* 少し跳ねるような動き */
  line-height: 1.5;
}

/* 画鋲(基準点)の視覚的表現 */
.pin {
  position: absolute;
  width: 10px;
  height: 10px;
  background-color: #ffc107;
  border-radius: 50%;
  border: 2px solid #333;
  z-index: 10;
}

/* === 💡 1. 左上(top left) === */
.is-top-left {
  /* 基準点を左上に指定 */
  transform-origin: top left;
}
.is-top-left:hover {
  rotate: 45deg;
}
.pin-top-left {
  top: 0;
  left: 0;
  translate: -50% -50%;
}

/* === 💡 2. 右下(100% 100%) === */
.is-bottom-right {
  /* 基準点を右下(X軸100%, Y軸100%)に指定 */
  transform-origin: 100% 100%;
}
.is-bottom-right:hover {
  rotate: -45deg;
}
.pin-bottom-right {
  bottom: 0;
  right: 0;
  translate: 50% 50%;
}

/* =コード解説エリア= */
.origin-adv-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

要素別!画像・テキスト・背景を回転させる

独立したrotateプロパティの基本を理解したところで、実際のWeb制作現場で遭遇する「要素別の回転」を解説します。

CSSの回転は、対象が画像なのか、テキストなのか、あるいは背景だけなのかによって、最適なアプローチや注意すべきバグが異なります。

ここでは、実務で知っておくべき要素別の注意点と解決するための実践的なコードを紹介します。

要素別!画像・テキスト・背景を回転させる
  • 画像やSVG・アイコンの回転
  • テキストを縦書き風やテーブルセル内で回す
  • 背景画像やグラデーションのみを回す

画像やSVG・アイコンの回転

矢印アイコンの向きを変えたり、ユーザーがアップロードした写真の向きを補正したりする際、画像やアイコンの回転は頻繁に使用されます。

横向きの画像を縦にする、逆さまの画像を直す、インタラクティブに動くSVGやアイコンなど、あらゆるオブジェクトに適用可能です。

画像やアイコンを回転させるには、「display: block;またはinline-block;を指定してから回転させること。そして、長方形の画像を90度回転させる場合は、親要素に適切な余白を設けて、はみ出た部分が他の要素を隠さないように設計すること」です。

⭕️ ホバーしてみよう!インラインブロックにしてから回せ!

⬆️

css rotate icon
(ホバーで180度)

横長画像

css rotate picture
(ホバーで90度)

/* ❌ 罠:インライン要素のまま回転させようとする */
.icon-fail {
  display: inline;
  rotate: 180deg; /* 🚨 インライン要素は回転できないため無視される! */
}

/* ⭕️ inline-block にして回し、被らないよう余白を確保する! */
.demo-icon {
  display: inline-block; /* 💡 これで回転が可能になる */
  transition: rotate 0.3s ease;
}
.demo-icon.is-180:hover {
  rotate: 180deg; /* 💡 css rotate image 180 degrees */
}

.demo-picture.is-90:hover {
  rotate: 90deg; /* 💡 css rotate image 90 degrees */
}
HTMLコード表示
<div class="rot-img-wrapper">
  
  <p class="rot-img-caption">⭕️ ホバーしてみよう!インラインブロックにしてから回せ!</p>

  <div class="rot-img-demo-area">
    
    <div class="img-box">
      <span class="demo-icon is-180">⬆️</span>
      <p class="img-desc">css rotate icon<br>(ホバーで180度)</p>
    </div>

    <div class="img-box has-spacing">
      <div class="demo-picture is-90">横長画像</div>
      <p class="img-desc">css rotate picture<br>(ホバーで90度)</p>
    </div>

  </div>

  <div class="rot-img-code-area">
    <span class="hl-comment">/* ❌ 罠:インライン要素のまま回転させようとする */</span><br>
    <span class="hl-blue">.icon-fail</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">inline;</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">180deg;</span> <span class="hl-comment">/* 🚨 インライン要素は回転できないため無視される! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ inline-block にして回し、被らないよう余白を確保する! */</span><br>
    <span class="hl-blue">.demo-icon</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">inline-block;</span> <span class="hl-comment">/* 💡 これで回転が可能になる */</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span><br>
    }<br>
    <span class="hl-blue">.demo-icon.is-180:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">180deg;</span> <span class="hl-comment">/* 💡 css rotate image 180 degrees */</span><br>
    }<br>
    <br>
    <span class="hl-blue">.demo-picture.is-90:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">90deg;</span> <span class="hl-comment">/* 💡 css rotate image 90 degrees */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-img-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-img-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-img-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.img-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  width: 150px;
}

/* 90度回転で縦長になるため、上下に余白を確保するプロの配慮 */
.has-spacing {
  padding-top: 30px;
  padding-bottom: 30px;
}

.img-desc {
  margin: 0;
  font-size: 12px;
  color: #333;
  text-align: center;
  font-weight: bold;
}

/* === 💡 1. アイコンの回転 === */
.demo-icon {
  font-size: 40px;
  /* 💡 必須:インライン要素(spanなど)は必ず inline-block にする */
  display: inline-block;
  transition: rotate 0.3s ease;
  cursor: pointer;
}
.img-box:hover .is-180 {
  rotate: 180deg; /* css rotate 180 */
}

/* === 💡 2. 長方形画像(を模した箱)の回転 === */
.demo-picture {
  width: 120px;
  height: 60px;
  background-color: #0dcaf0;
  color: #000;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  transition: rotate 0.3s ease;
  cursor: pointer;
}
.img-box:hover .is-90 {
  rotate: 90deg; /* css rotate 90 */
}

/* =コード解説エリア= */
.rot-img-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

displayの使い方を詳しく知りたい人は「【CSS】displayの種類は?flexやinline-blockの違い」を一読ください。

テキストを縦書き風やテーブルセル内で回す

デザインのアクセントとして、見出しやラベルテキストを縦向きに配置することは効果的です。

日本語の「縦書き」にしたい場合はwriting-mode: vertical-rl;を使いますが、英語のラベルや「NEW!」といった短いバッジを横倒しに配置したい場合は、90 degrees(または180 degrees)を使用します。

特に、データ量の多い表組みにおいて、見出しセルの中身を縦にすることは実務で頻出します。

テキストを回転させるには、「white-space: nowrap;を指定して、回転前の意図しないテキストの折り返しを強制的に禁止すること。そして、回転させた後の高さに合わせて、親要素に適切なheightまたはpaddingを確保すること」です。

⭕️ テキストを回す時は「折り返し禁止(nowrap)」と「十分な高さ(height)」をセットで使え!

長いカテゴリ名長いカテゴリ名 ❌ nowrap未指定(文字が折り返されてから回るため完全に崩れる)
長いカテゴリ名長いカテゴリ名 ⭕️ nowrap指定(1行のまま美しく縦に配置される)
/* ⭕️ 回すテキストの長さに合わせて、親の「高さ」を確保する! */
.demo-table th {
  width: 50px;
  height: 250px; /* 💡 修正:長い文字がはみ出ないよう、高さを十分に確保! */
  text-align: center;
  vertical-align: middle;
}

/* ⭕️ white-space: nowrap; で1行を強制維持する! */
.txt-success {
  display: inline-block;
  white-space: nowrap; /* 💡 絶対に改行させない */
  rotate: -90deg; /* 💡 下から上へ読む美しい縦ラベルになる */
}
HTMLコード表示
<div class="rot-txt-wrapper">
  
  <p class="rot-txt-caption">⭕️ テキストを回す時は「折り返し禁止(nowrap)」と「十分な高さ(height)」をセットで使え!</p>

  <div class="rot-txt-demo-area">
    
    <table class="demo-table">
      <tbody>
        <tr>
          <th class="th-fail">
            <span class="txt-fail">長いカテゴリ名長いカテゴリ名</span>
          </th>
          <td>❌ nowrap未指定(文字が折り返されてから回るため完全に崩れる)</td>
        </tr>
        <tr>
          <th class="th-success">
            <span class="txt-success">長いカテゴリ名長いカテゴリ名</span>
          </th>
          <td>⭕️ nowrap指定(1行のまま美しく縦に配置される)</td>
        </tr>
      </tbody>
    </table>

  </div>

  <div class="rot-txt-code-area">
    <span class="hl-comment">/* ⭕️ 回すテキストの長さに合わせて、親の「高さ」を確保する! */</span><br>
    <span class="hl-blue">.demo-table th</span> {<br>
      <span class="hl-green">width:</span> <span class="hl-red">50px;</span><br>
      <span class="hl-green">height:</span> <span class="hl-red">250px;</span> <span class="hl-comment">/* 💡 修正:長い文字がはみ出ないよう、高さを十分に確保! */</span><br>
      <span class="hl-green">text-align:</span> <span class="hl-red">center;</span><br>
      <span class="hl-green">vertical-align:</span> <span class="hl-red">middle;</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ white-space: nowrap; で1行を強制維持する! */</span><br>
    <span class="hl-blue">.txt-success</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">inline-block;</span><br>
      <span class="hl-green">white-space:</span> <span class="hl-red">nowrap;</span> <span class="hl-comment">/* 💡 絶対に改行させない */</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">-90deg;</span> <span class="hl-comment">/* 💡 下から上へ読む美しい縦ラベルになる */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-txt-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-txt-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-txt-demo-area {
  background-color: #e9ecef;
  padding: 30px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
}

/* === 💡 テーブルと親要素(th)の装飾 === */
.demo-table {
  border-collapse: collapse;
  width: 100%;
  max-width: 450px;
  background-color: #fff;
}

.demo-table th, .demo-table td {
  border: 1px solid #ced4da;
  padding: 15px;
}

.demo-table th {
  background-color: #0d6efd;
  color: #fff;
  width: 60px; /* 見出し列をあえて狭くする(改行を誘発) */
  
  /* 💡 修正:回転した文字がはみ出ないよう、高さを十分(250px)に確保する */
  height: 250px; 
  
  /* 💡 中央に配置するための設定 */
  vertical-align: middle;
  text-align: center;
}

.demo-table td {
  font-size: 13px;
  color: #333;
  text-align: left;
  vertical-align: middle;
}

/* === ❌ 罠:nowrapなし === */
.txt-fail {
  display: inline-block;
  /* 狭いthの幅に負けて、不格好に改行されたブロックごと回転してしまう */
  rotate: -90deg;
  font-weight: bold;
}

/* === ⭕️ 成功:nowrapあり === */
.txt-success {
  display: inline-block;
  /* 💡 どんなに親が狭くても、1行を強制する */
  white-space: nowrap; 
  /* 💡 css rotate text 90 degrees(-90で下から上へ) */
  rotate: -90deg;
  font-weight: bold;
  letter-spacing: 2px;
}

/* =コード解説エリア= */
.rot-txt-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

white-spaceの使い方を詳しく知りたい人は「【CSS】white-spaceの使い方とnowrap・pre・pre-wrapの使い分け」を一読ください。

背景画像やグラデーションのみを回す

「箱の中の文字はそのままに、背景の模様だけを回したい」という要望はデザイン上よくあります。

例えば、グラデーションの角度を変えるのであればlinear-gradient(90deg, ...)のように数値を直接書き換えれば済みます。

しかし、写真やパターン柄の背景画像を回したい場合は厄介です。

背景画像だけを回転させるには、「要素本体に背景を設定するのではなく、::beforeなどの『疑似要素』に背景画像を持たせ、疑似要素だけをrotateで回転させて、z-index: -1で文字の後ろに配置すること」です。

⭕️ 背景「だけ」を回したいなら、疑似要素(::before)を作って裏で回せ!

❌ 罠の指定
(文字まで回る)

⭕️ 成功の指定
(背景だけが回る!)

/* ❌ 罠:background-rotateというプロパティは存在しないため全体を回すミス */
.box-fail {
  background-image: url(‘pattern.png’);
  rotate: 15deg; /* 🚨 中身のテキストも一緒に傾いて読めなくなる! */
}

/* ⭕️ 背景専用の疑似要素を作り、それだけを回転させる! */
.box-success {
  position: relative;
  z-index: 0; /* 💡 必須:疑似要素が背景の裏に抜け落ちるのを防ぐ */
  overflow: hidden; /* 💡 回転してはみ出た背景をカットする */
}
.box-success::before {
  content: “”;
  position: absolute;
  inset: -50%; /* 💡 回転しても隙間ができないよう、あらかじめ巨大に広げておく */
  background-image: url(‘pattern.png’);
  rotate: 15deg; /* 💡 背景だけを回す! */
  z-index: -1; /* 💡 文字の裏へ */
}
HTMLコード表示
<div class="rot-bg-wrapper">
  
  <p class="rot-bg-caption">⭕️ 背景「だけ」を回したいなら、疑似要素(::before)を作って裏で回せ!</p>

  <div class="rot-bg-demo-area">
    
    <div class="bg-box-fail">
      <p class="bg-text">❌ 罠の指定<br>(文字まで回る)</p>
    </div>

    <div class="bg-box-success">
      <p class="bg-text">⭕️ 成功の指定<br>(背景だけが回る!)</p>
    </div>

  </div>

  <div class="rot-bg-code-area">
    <span class="hl-comment">/* ❌ 罠:background-rotateというプロパティは存在しないため全体を回すミス */</span><br>
    <span class="hl-blue">.box-fail</span> {<br>
      <span class="hl-green">background-image:</span> <span class="hl-red">url('pattern.png');</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">15deg;</span> <span class="hl-comment">/* 🚨 中身のテキストも一緒に傾いて読めなくなる! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 背景専用の疑似要素を作り、それだけを回転させる! */</span><br>
    <span class="hl-blue">.box-success</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">relative;</span><br>
      <span class="hl-green">z-index:</span> <span class="hl-red">0;</span> <span class="hl-comment">/* 💡 必須:疑似要素が背景の裏に抜け落ちるのを防ぐ */</span><br>
      <span class="hl-green">overflow:</span> <span class="hl-red">hidden;</span> <span class="hl-comment">/* 💡 回転してはみ出た背景をカットする */</span><br>
    }<br>
    <span class="hl-blue">.box-success::before</span> {<br>
      <span class="hl-green">content:</span> <span class="hl-red">"";</span><br>
      <span class="hl-green">position:</span> <span class="hl-red">absolute;</span><br>
      <span class="hl-green">inset:</span> <span class="hl-red">-50%;</span> <span class="hl-comment">/* 💡 回転しても隙間ができないよう、あらかじめ巨大に広げておく */</span><br>
      <span class="hl-green">background-image:</span> <span class="hl-red">url('pattern.png');</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">15deg;</span> <span class="hl-comment">/* 💡 背景だけを回す! */</span><br>
      <span class="hl-green">z-index:</span> <span class="hl-red">-1;</span> <span class="hl-comment">/* 💡 文字の裏へ */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-bg-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-bg-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-bg-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

/* パターン画像(デモ用のストライプ) */
:root {
  --demo-pattern: repeating-linear-gradient(0deg, #fd7e14, #fd7e14 10px, #ffc107 10px, #ffc107 20px);
}

.bg-text {
  margin: 0;
  font-weight: bold;
  font-size: 14px;
  color: #fff;
  text-shadow: 1px 1px 3px rgba(0,0,0,0.8);
  text-align: center;
  line-height: 1.5;
  background-color: rgba(0,0,0,0.5);
  padding: 10px;
  border-radius: 4px;
}

/* === ❌ 罠:全体を回す === */
.bg-box-fail {
  width: 150px;
  height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 背景を直接指定 */
  background-image: var(--demo-pattern);
  /* 🚨 全体を回すので文字も斜めになる */
  rotate: 20deg;
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
}

/* === ⭕️ 成功:疑似要素だけ回す === */
.bg-box-success {
  position: relative;
  
  /* 💡 修正箇所:スタッキングコンテキストを生成し、疑似要素を箱の中に留める */
  z-index: 0; 
  
  width: 150px;
  height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 💡 箱からはみ出た背景を切り取る */
  overflow: hidden;
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
  /* 箱自体は回さない! */
}

/* 💡 これが背景専用の疑似要素 */
.bg-box-success::before {
  content: "";
  position: absolute;
  /* 💡 回転すると角に隙間ができるため、親要素よりかなり大きく広げておく */
  top: -50%;
  left: -50%;
  right: -50%;
  bottom: -50%;
  /* 疑似要素に背景を持たせる */
  background-image: var(--demo-pattern);
  /* 💡 背景だけを回す! */
  rotate: 20deg;
  /* 文字の裏へ配置 */
  z-index: -1;
}

/* =コード解説エリア= */
.rot-bg-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

アニメーションとホバーの実装

静的なデザインに動きを加えることで、ユーザーの直感的な操作を助け、Webサイトのクオリティは格段に上がります。

回転エフェクトを用いた回転アニメーションは、ローディング画面からインタラクティブなボタンまで幅広く使われます。

ここでは、実務で使えるアニメーションの実装例として、マウスホバー時の滑らかな回転、キーフレームによる無限ループ、クリック操作や移動と組み合わせたテクニックを解説します。

アニメーションとホバーの実装
  • transitionを使ったホバー時の滑らかな回転
  • @keyframesで無限ループする回転アニメーション
  • クリック時の動作とtranslate(移動)との併用

transitionを使ったホバー時の滑らかな回転

ボタンやカードにマウスを乗せた時に要素を傾ける表現は、ユーザーに「これはクリックできる要素だ」と伝える基本テクニックです。

特に、サムネイル画像などに適用するホバーは頻出の実装です。

この滑らかな動きを作るには、状態変化をアニメーションさせるtransitionを使用します。

ホバー時の変化を滑らかにするには、「transitionプロパティは、変化後(:hover)ではなく、『変化前(通常状態のベース要素)』に記述すること」です。

これにより、マウスを乗せた時も外した時も両方滑らかにアニメーションが行われます。

⭕️ ホバーしてみよう!transitionは必ず「通常状態」の方に書け!

❌ 罠
(外すとパチッと戻る)
⭕️ 成功
(外しても滑らか)
/* ❌ 罠::hover 側に transition を書いてしまう */
.box-fail:hover {
  rotate: 15deg;
  transition: rotate 0.3s ease; /* 🚨 マウスを外した時の設定がないため一瞬で戻る! */
}

/* ⭕️ プロの鉄則:通常状態(変化前)に transition を書く! */
.box-success {
  rotate: 0deg;
  transition: rotate 0.3s ease; /* 💡 これで行きも帰りも滑らかになる */
}
.box-success:hover {
  rotate: 15deg;
}
HTMLコード表示
<div class="anim-hover-wrapper">
  
  <p class="anim-hover-caption">⭕️ ホバーしてみよう!transitionは必ず「通常状態」の方に書け!</p>

  <div class="anim-hover-demo-area">
    
    <div class="hover-box is-trap-transition">
      ❌ 罠<br>(外すとパチッと戻る)
    </div>

    <div class="hover-box is-success-transition">
      ⭕️ 成功<br>(外しても滑らか)
    </div>

  </div>

  <div class="anim-hover-code-area">
    <span class="hl-comment">/* ❌ 罠::hover 側に transition を書いてしまう */</span><br>
    <span class="hl-blue">.box-fail:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">15deg;</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span> <span class="hl-comment">/* 🚨 マウスを外した時の設定がないため一瞬で戻る! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ プロの鉄則:通常状態(変化前)に transition を書く! */</span><br>
    <span class="hl-blue">.box-success</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">0deg;</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span> <span class="hl-comment">/* 💡 これで行きも帰りも滑らかになる */</span><br>
    }<br>
    <span class="hl-blue">.box-success:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">15deg;</span><br>
    }
  </div>

</div>
CSSコード表示
.anim-hover-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.anim-hover-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.anim-hover-demo-area {
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  display: flex;
  gap: 40px;
  justify-content: center;
}

.hover-box {
  width: 140px;
  height: 140px;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  cursor: pointer;
  line-height: 1.5;
}

/* === ❌ 罠::hover側にtransitionを書く === */
.is-trap-transition {
  background-color: #dc3545;
  /* ここにtransitionがない */
}
.is-trap-transition:hover {
  rotate: 15deg;
  /* 🚨 罠:ホバー時のみ滑らかに動くが、外すと一瞬で戻る */
  transition: rotate 0.3s ease;
}

/* === ⭕️ 成功:通常状態にtransitionを書く === */
.is-success-transition {
  background-color: #0d6efd;
  /* 💡 通常状態に書くことで往復のアニメーションを担保 */
  transition: rotate 0.3s ease;
}
.is-success-transition:hover {
  rotate: 15deg;
}

/* =コード解説エリア= */
.anim-hover-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

transitionの使い方を詳しく知りたい人は「【CSS】transitionの使い方:animationやtransformとの違い」を一読ください。

@keyframesで無限ループする回転アニメーション

ローディングアイコンなど、常に回り続ける回転アニメーションの表現を作るには、@keyframesanimationプロパティを組み合わせて無限ループを実装します。

1周回る表現や振り子のように左右に揺れる表現は、実務でデザインのアクセントとしてよく使われます。

無限に回り続けるアニメーションを作るには、「ローディングのように一定速度で回り続ける場合は、linearを指定して等速運動にすること。逆に、振り子のように左右に揺れる場合は、重力を感じるようにease-in-outを指定すること」です。

⭕️ 無限ループは「等速(linear)」と「加減速(ease-in-out)」を使い分けろ!

⚙️

❌ 罠の設定(ease)
1周ごとに減速してカクつく

⚙️

⭕️ 等速回転(linear)
滑らかに回り続ける

🔔

⭕️ 振り子(ease-in-out)
重力を感じる自然な揺れ

/* ❌ 罠:デフォルト(ease)のままだと、等速で回らない */
.icon-fail {
  animation: spin 2s infinite; /* 🚨 1周ごとにブレーキがかかる */
}

/* ⭕️ 一定に回すなら linear、揺らすなら ease-in-out を使う! */
.icon-spinner {
  animation: spin 2s linear infinite; /* 💡 一定の速度(linear)で無限回転 */
}
.icon-pendulum {
  transform-origin: top center; /* 💡 基準点を上にずらす */
  animation: swing 1.5s ease-in-out infinite alternate; /* 💡 行って戻る(alternate) */
}

@keyframes spin {
  100% { rotate: 1turn; } /* 💡 1周(360deg)回す */
}
HTMLコード表示
<div class="anim-loop-wrapper">
  
  <p class="anim-loop-caption">⭕️ 無限ループは「等速(linear)」と「加減速(ease-in-out)」を使い分けろ!</p>

  <div class="anim-loop-demo-area">
    
    <div class="loop-item">
      <div class="loop-icon is-trap-loop">⚙️</div>
      <p class="loop-desc">❌ 罠の設定(ease)<br>1周ごとに減速してカクつく</p>
    </div>

    <div class="loop-item">
      <div class="loop-icon is-success-loop">⚙️</div>
      <p class="loop-desc">⭕️ 等速回転(linear)<br>滑らかに回り続ける</p>
    </div>

    <div class="loop-item">
      <div class="pendulum-icon is-pendulum">🔔</div>
      <p class="loop-desc">⭕️ 振り子(ease-in-out)<br>重力を感じる自然な揺れ</p>
    </div>

  </div>

  <div class="anim-loop-code-area">
    <span class="hl-comment">/* ❌ 罠:デフォルト(ease)のままだと、等速で回らない */</span><br>
    <span class="hl-blue">.icon-fail</span> {<br>
      <span class="hl-green">animation:</span> <span class="hl-red">spin 2s infinite;</span> <span class="hl-comment">/* 🚨 1周ごとにブレーキがかかる */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 一定に回すなら linear、揺らすなら ease-in-out を使う! */</span><br>
    <span class="hl-blue">.icon-spinner</span> {<br>
      <span class="hl-green">animation:</span> <span class="hl-red">spin 2s linear infinite;</span> <span class="hl-comment">/* 💡 一定の速度(linear)で無限回転 */</span><br>
    }<br>
    <span class="hl-blue">.icon-pendulum</span> {<br>
      <span class="hl-green">transform-origin:</span> <span class="hl-red">top center;</span> <span class="hl-comment">/* 💡 基準点を上にずらす */</span><br>
      <span class="hl-green">animation:</span> <span class="hl-red">swing 1.5s ease-in-out infinite alternate;</span> <span class="hl-comment">/* 💡 行って戻る(alternate) */</span><br>
    }<br>
    <br>
    <span class="hl-blue">@keyframes spin</span> {<br>
      <span class="hl-blue">100%</span> { <span class="hl-green">rotate:</span> <span class="hl-red">1turn;</span> } <span class="hl-comment">/* 💡 1周(360deg)回す */</span><br>
    }
  </div>

</div>
CSSコード表示
.anim-loop-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.anim-loop-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.anim-loop-demo-area {
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  justify-content: center;
}

.loop-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  width: 140px;
}

.loop-desc {
  margin: 0;
  font-size: 12px;
  color: #333;
  text-align: center;
  font-weight: bold;
  line-height: 1.4;
}

.loop-icon, .pendulum-icon {
  font-size: 50px;
  display: inline-block; /* 必須:インラインブロック化 */
}

/* === @keyframesの定義 === */
@keyframes spin {
  100% {
    rotate: 1turn; /* 360degと同じ */
  }
}

@keyframes swing {
  0% {
    rotate: -20deg;
  }
  100% {
    rotate: 20deg;
  }
}

/* === ❌ 罠:easeによるカクつき === */
.is-trap-loop {
  /* タイミング関数を省略するとデフォルトのeaseになる */
  animation: spin 2s infinite; 
}

/* === ⭕️ 成功:linearによる等速回転 === */
.is-success-loop {
  /* 💡 linearを指定することで一定速度になる */
  animation: spin 2s linear infinite; 
}

/* === ⭕️ 成功:ease-in-outによる振り子 === */
.is-pendulum {
  /* 画鋲を上に刺す */
  transform-origin: top center; 
  /* 💡 ease-in-outで重力を持たせ、alternateで行って戻るループにする */
  animation: swing 1s ease-in-out infinite alternate;
}

/* =コード解説エリア= */
.anim-loop-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

様々な要素に対するアニメーションの作り方を詳しく知りたい人は「【CSS】アニメーションの作り方:コピペで使えるおしゃれサンプル集」を一読ください。

クリック時の動作とtranslate(移動)との併用

要素をクリックした際に回転させるには、アコーディオンメニューの開閉アイコン(+が×になるなど)で必須の技術です。

かつてはjquery css rotateのようにjQueryを使ってJavaScript側で直接スタイルを操作していましたが、現代では「クリックでクラス(is-activeなど)を付与し、回転自体はCSSに任せる」のが最もパフォーマンスが良い実装です。

また、クリックしてメニューが開く際に、要素を回転させながら移動させる場面も多々あります。

クリック時のアニメーションや移動と回転を組み合わせる際は、「古いtransform一括指定は捨て、独立したtranslaterotateプロパティを使うこと。これにより、書く順番に依存せず、移動と回転を同時並行させることができる」ようになります。

⭕️ クリックして確認!移動と回転の同時指定は「独立プロパティ」で安全に行え!

クリックで「+」が「×」に回転(css rotate on click)します。jQueryは不要です。

独立プロパティを使っているため、計算の順序バグを気にせず直感的に操作できます。

/* ❌ 罠:古い transform 指定だと、書く順番で軸が狂う */
.box-fail.is-active {
  transform: rotate(90deg) translateX(50px); /* 🚨 X軸自体が傾くため、右ではなく下へ移動してしまう! */
}

/* ⭕️ 独立プロパティなら順番に依存せず完璧に動く! */
.move-btn {
  translate: 0px 0px;
  rotate: 0deg;
  transition: all 0.4s ease;
}
.move-btn.is-moved {
  translate: 30px -10px; /* 💡 確実に見かけ上の右上へ移動 */
  rotate: 15deg; /* 💡 確実にその場で回転 */
}
HTMLコード表示
<div class="anim-click-wrapper">
  
  <p class="anim-click-caption">⭕️ クリックして確認!移動と回転の同時指定は「独立プロパティ」で安全に行え!</p>

  <div class="anim-click-demo-area">
    
    <div class="click-item">
      <button class="toggle-btn" onclick="this.classList.toggle('is-active')">
        <span class="toggle-icon">+</span> クリックで開閉
      </button>
      <p class="click-desc">クリックで「+」が「×」に回転(css rotate on click)します。jQueryは不要です。</p>
    </div>

    <div class="click-item">
      <button class="move-btn" onclick="this.classList.toggle('is-moved')">
        クリックで移動&回転
      </button>
      <p class="click-desc">独立プロパティを使っているため、計算の順序バグを気にせず直感的に操作できます。</p>
    </div>

  </div>

  <div class="anim-click-code-area">
    <span class="hl-comment">/* ❌ 罠:古い transform 指定だと、書く順番で軸が狂う */</span><br>
    <span class="hl-blue">.box-fail.is-active</span> {<br>
      <span class="hl-green">transform:</span> <span class="hl-red">rotate(90deg) translateX(50px);</span> <span class="hl-comment">/* 🚨 X軸自体が傾くため、右ではなく下へ移動してしまう! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 独立プロパティなら順番に依存せず完璧に動く! */</span><br>
    <span class="hl-blue">.move-btn</span> {<br>
      <span class="hl-green">translate:</span> <span class="hl-red">0px 0px;</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">0deg;</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">all 0.4s ease;</span><br>
    }<br>
    <span class="hl-blue">.move-btn.is-moved</span> {<br>
      <span class="hl-green">translate:</span> <span class="hl-red">30px -10px;</span> <span class="hl-comment">/* 💡 確実に見かけ上の右上へ移動 */</span><br>
      <span class="hl-green">rotate:</span> <span class="hl-red">15deg;</span> <span class="hl-comment">/* 💡 確実にその場で回転 */</span><br>
    }
  </div>

</div>
CSSコード表示
.anim-click-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.anim-click-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.anim-click-demo-area {
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  gap: 40px;
  align-items: center;
}

.click-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  width: 100%;
  max-width: 300px;
}

.click-desc {
  margin: 0;
  font-size: 12px;
  color: #333;
  line-height: 1.5;
}

/* === 💡 1. 開閉アイコン(+が×になる) === */
.toggle-btn {
  background-color: #343a40;
  color: #fff;
  border: none;
  padding: 12px 25px;
  border-radius: 30px;
  font-size: 15px;
  font-weight: bold;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  outline: none;
}

.toggle-icon {
  display: inline-block;
  font-size: 18px;
  /* 💡 ベース状態でtransitionを指定 */
  transition: rotate 0.3s ease;
}

/* JSでクラスが付与された時のスタイル */
.toggle-btn.is-active .toggle-icon {
  /* 💡 +を45度回して×にする */
  rotate: 45deg;
}

/* === 💡 2. 移動と回転の複合アニメーション === */
.move-btn {
  background-color: #fd7e14;
  color: #fff;
  border: none;
  padding: 15px 25px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
  
  /* 💡 独立プロパティで初期値を設定 */
  translate: 0 0;
  rotate: 0deg;
  transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

/* JSでクラスが付与された時のスタイル */
.move-btn.is-moved {
  /* 💡 古いtransformを使わないため、順番バグを気にせず直感的に指定できる */
  translate: 20px -20px;
  rotate: 15deg;
  background-color: #e8590c;
}

/* =コード解説エリア= */
.anim-click-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

立体感を作る!3D回転と遠近感

CSSの回転は、2D(平面)だけにとどまりません。

現代のWebデザインでは、rotate3dを駆使して画面の奥へと続くような本物の立体感を演出することが可能です。

3D空間を表現するには、単に要素を回すだけでなく、カメラからの距離を設定するrotate 3d perspectiveの理解が不可欠です。

実務において、複雑な斜め軸の3D回転を作る際はrotate3d generatorなどのツールを頼るのが賢明ですが、基本的な軸(X/Y/Z)の回転やカードフリップの仕組みは、制作者として理解しておくべき必須スキルです。

立体感を作る!3D回転と遠近感
  • rotateX/Y/Zperspective(奥行き)の使い方
  • カードの裏返しや3Dキューブ(cube)エフェクト

rotateX/Y/Zとperspective(奥行き)の使い方

3D空間での回転は、どの軸(パイプ)を基準にして回すかで決まります。

鉄棒のように縦に回転するrotatex、回転ドアのように横に回転するrotatey、車のハンドルのように平面的に回るrotatezの3つが基本です。

※これまで解説してきた単なるrotateは、rotateZと同じ動きをします。

3D回転を表現するには、「rotateXrotateYを使う際は、『親要素』に対してperspective: 1000px;(遠近感)を設定すること」です。

数値が小さいほどカメラが近く(変形がキツく)なり、大きいほど遠く(自然に)なります。

実務では800px1000px程度が美しく見えます。

⭕️ ホバーしてみよう!3D回転(X軸・Y軸)は親要素にperspectiveを指定しろ!

❌ 罠(X軸)
ただ潰れるだけ
⭕️ 成功(X軸)
奥に倒れ込む!
⭕️ 成功(Y軸)
ドアのように開く!
/* ❌ 罠:perspective(遠近感)を指定せずにX軸を回す */
.box-fail:hover {
  rotate: x 60deg; /* 🚨 平面的に縦幅が縮んだようにしか見えない! */
}

/* ⭕️ 3D回転させる要素の「親」に perspective を指定する! */
.parent-wrapper {
  perspective: 1000px; /* 💡 カメラからの距離感を設定する(必須) */
}
.box-success-x:hover {
  rotate: x 60deg; /* 💡 上部が奥へ、下部が手前へリアルに倒れ込む! */
}
.box-success-y:hover {
  rotate: y 60deg; /* 💡 左が手前、右が奥へとドアのように開く! */
}
HTMLコード表示
<div class="rot-3d-wrapper">
  
  <p class="rot-3d-caption">⭕️ ホバーしてみよう!3D回転(X軸・Y軸)は親要素にperspectiveを指定しろ!</p>

  <div class="rot-3d-demo-area">
    
    <div class="axis3d-item">
      <div class="axis3d-box is-trap-x">
        ❌ 罠(X軸)<br>ただ潰れるだけ
      </div>
    </div>

    <div class="axis3d-item has-perspective">
      <div class="axis3d-box is-success-x">
        ⭕️ 成功(X軸)<br>奥に倒れ込む!
      </div>
    </div>

    <div class="axis3d-item has-perspective">
      <div class="axis3d-box is-success-y">
        ⭕️ 成功(Y軸)<br>ドアのように開く!
      </div>
    </div>

  </div>

  <div class="rot-3d-code-area">
    <span class="hl-comment">/* ❌ 罠:perspective(遠近感)を指定せずにX軸を回す */</span><br>
    <span class="hl-blue">.box-fail:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">x 60deg;</span> <span class="hl-comment">/* 🚨 平面的に縦幅が縮んだようにしか見えない! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 3D回転させる要素の「親」に perspective を指定する! */</span><br>
    <span class="hl-blue">.parent-wrapper</span> {<br>
      <span class="hl-green">perspective:</span> <span class="hl-red">1000px;</span> <span class="hl-comment">/* 💡 カメラからの距離感を設定する(必須) */</span><br>
    }<br>
    <span class="hl-blue">.box-success-x:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">x 60deg;</span> <span class="hl-comment">/* 💡 上部が奥へ、下部が手前へリアルに倒れ込む! */</span><br>
    }<br>
    <span class="hl-blue">.box-success-y:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">y 60deg;</span> <span class="hl-comment">/* 💡 左が手前、右が奥へとドアのように開く! */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-3d-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-3d-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-3d-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: space-around;
}

.axis3d-item {
  width: 130px;
  height: 130px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 💡 親要素にperspective(遠近感)を設定する */
.has-perspective {
  perspective: 1000px;
}

.axis3d-box {
  width: 100%;
  height: 100%;
  color: #fff;
  font-weight: bold;
  font-size: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border-radius: 8px;
  transition: rotate 0.5s ease;
  cursor: pointer;
  line-height: 1.5;
  box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}

/* === ❌ 罠:遠近感のないX軸回転 === */
.is-trap-x {
  background-color: #dc3545;
}
.axis3d-item:hover .is-trap-x {
  rotate: x 60deg; /* 立体感がなく潰れて見える */
}

/* === ⭕️ 成功:遠近感のあるX軸回転 === */
.is-success-x {
  background-color: #0d6efd;
}
.axis3d-item:hover .is-success-x {
  rotate: x 60deg; /* スターウォーズのオープニングのように奥へ倒れる */
}

/* === ⭕️ 成功:遠近感のあるY軸回転 === */
.is-success-y {
  background-color: #198754;
}
.axis3d-item:hover .is-success-y {
  rotate: y 60deg; /* 扉のように立体的に開く */
}

/* =コード解説エリア= */
.rot-3d-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

カードの裏返しや3Dキューブ(cube)エフェクト

3D回転の集大成とも言えるのが、ホバーすると表裏がひっくり返るカードフリップやサイコロのように面が回転する 3Dキューブ、画像を立体的に見せるアニメーションです。

これらは単に要素を回すだけでなく、「表の面」と「裏の面」を別々に用意し、立体空間で組み合わせてから回転させるというテクニックを必要とします。

カードフリップや3Dキューブを実装には以下の3点です。

  1. 親(空間)
    perspectiveで遠近感を作る。
  2. 回転する箱(コンテナ)
    transform-style: preserve-3d;を指定し、子要素がペタンコに潰れるのを防いで3D空間を維持する。
  3. 表と裏の面(フェイス)
    backface-visibility: hidden;を指定し、面が裏返った時に中身が透けて見えないように隠す。

⭕️ ホバーしてみよう!preserve-3d と backface-visibility の組み合わせが鍵!

Hover Me!

表の面です

Success!

裏の面です!
見事に裏返りました。

/* ⭕️ 大枠に遠近感を設定する */
.card-scene {
  perspective: 1000px;
}

/* ⭕️ 回転する箱は「3D空間を維持(preserve-3d)」する! */
.card-object {
  position: relative;
  transition: rotate 0.6s ease-in-out;
  transform-style: preserve-3d; /* 🚨 これがないと裏面が潰れて表示されない! */
}
.card-scene:hover .card-object {
  rotate: y 180deg; /* 💡 ホバーで箱ごとY軸で180度裏返す */
}

/* ⭕️ 表と裏の面は、裏返った時に見えないよう隠す! */
.card-face {
  position: absolute;
  backface-visibility: hidden; /* 🚨 これがないと鏡文字が透けて見えてしまう! */
}
.card-back {
  rotate: y 180deg; /* 💡 最初から裏面は背中合わせに180度回して貼り付けておく */
}
HTMLコード表示
<div class="rot-card-wrapper">
  
  <p class="rot-card-caption">⭕️ ホバーしてみよう!preserve-3d と backface-visibility の組み合わせが鍵!</p>

  <div class="rot-card-demo-area">
    
    <div class="card-scene">
      
      <div class="card-object">
        
        <div class="card-face card-front">
          <div class="card-title">Hover Me!</div>
          <p class="card-text">表の面です</p>
        </div>
        
        <div class="card-face card-back">
          <div class="card-title">Success!</div>
          <p class="card-text">裏の面です!<br>見事に裏返りました。</p>
        </div>
        
      </div>
    </div>

  </div>

  <div class="rot-card-code-area">
    <span class="hl-comment">/* ⭕️ 大枠に遠近感を設定する */</span><br>
    <span class="hl-blue">.card-scene</span> {<br>
      <span class="hl-green">perspective:</span> <span class="hl-red">1000px;</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 回転する箱は「3D空間を維持(preserve-3d)」する! */</span><br>
    <span class="hl-blue">.card-object</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">relative;</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.6s ease-in-out;</span><br>
      <span class="hl-green">transform-style:</span> <span class="hl-red">preserve-3d;</span> <span class="hl-comment">/* 🚨 これがないと裏面が潰れて表示されない! */</span><br>
    }<br>
    <span class="hl-blue">.card-scene:hover .card-object</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">y 180deg;</span> <span class="hl-comment">/* 💡 ホバーで箱ごとY軸で180度裏返す */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 表と裏の面は、裏返った時に見えないよう隠す! */</span><br>
    <span class="hl-blue">.card-face</span> {<br>
      <span class="hl-green">position:</span> <span class="hl-red">absolute;</span><br>
      <span class="hl-green">backface-visibility:</span> <span class="hl-red">hidden;</span> <span class="hl-comment">/* 🚨 これがないと鏡文字が透けて見えてしまう! */</span><br>
    }<br>
    <span class="hl-blue">.card-back</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">y 180deg;</span> <span class="hl-comment">/* 💡 最初から裏面は背中合わせに180度回して貼り付けておく */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-card-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-card-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-card-demo-area {
  display: flex;
  justify-content: center;
  background-color: #e9ecef;
  padding: 50px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

/* === 💡 1. 大枠(カメラの遠近感) === */
.card-scene {
  width: 220px;
  height: 280px;
  perspective: 1000px;
}

/* === 💡 2. 回転する箱本体 === */
.card-object {
  width: 100%;
  height: 100%;
  position: relative;
  /* スムーズに裏返るアニメーション */
  transition: rotate 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  
  /* 🚨 超重要:子要素(表裏の面)の3D位置を維持する */
  transform-style: preserve-3d;
}

/* ホバーで箱自体を180度回す */
.card-scene:hover .card-object {
  rotate: y 180deg;
}

/* === 💡 3. 表と裏の各面(共通設定) === */
.card-face {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 20px rgba(0,0,0,0.2);
  
  /* 🚨 超重要:裏返った時にその面を見えなくする(鏡文字防止) */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* 表の面のデザイン */
.card-front {
  background-color: #fff;
  border: 2px solid #0d6efd;
  color: #0d6efd;
}

/* 裏の面のデザイン */
.card-back {
  background: linear-gradient(135deg, #fd7e14, #ffc107);
  color: #fff;
  
  /* 💡 裏面はあらかじめ180度回して「背中合わせ」にしておく */
  rotate: y 180deg;
}

.card-title {
  margin-top: 0;
  margin-bottom: 15px;
  font-size: 24px;
}

.card-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  text-align: center;
}

/* =コード解説エリア= */
.rot-card-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

効かない時の解決策と応用

要素の回転は直感的な一方で、CSS特有の仕様による思わぬ落とし穴が存在します。

「コードは合っているはずなのに、どうしても効かない」と何時間も悩むケースは、初心者から中級者まで後を絶ちません。

ここでは、実務で直面する「効かない」原因のトップであるインライン要素の原因、色そのものを回転させるhue-rotateなどの応用テクニックまでを網羅します。

効かない時の解決策と応用
  • rotateが効かない原因とインライン要素の罠
  • hue-rotate(色相回転)や枠線・影の回転

rotateが効かない原因とインライン要素の罠

rotateが効かない」と検索してこの記事にたどり着いた方の9割は、ある1つの初歩的なミスを犯しています。

それは、「回転させようとしている対象が『インライン要素』であること」です。

回転が効かない時は、「要素が回らない時は、ブラウザの開発者ツールで要素のdisplay値を確認すること。もしinlineであれば、display: inline-block;(またはblock)を追加してから回転させること」です。

⭕️ ホバーしてみよう!インライン要素は回らない(形も崩れる)!「inline-block」にしろ!

❌ 罠(inline)
幅も高さも効かず、回らない

⭕️ 成功(inline-block)
丸みを保ち、ホバーで上を向く

/* ❌ 罠:spanタグ(デフォルトはinline)にそのまま回転を指定する */
.icon-fail:hover {
  rotate: -90deg; /* 🚨 変形が無効化されているため効かない! */
}

/* ⭕️ 必ず display: inline-block; を指定してから回す! */
.icon-success {
  display: inline-block; /* 💡 これで高さや変形を受け付けるようになる */
  transition: rotate 0.3s ease;
}
.icon-success:hover {
  rotate: -90deg; /* 💡 完璧に回る! */
}
HTMLコード表示
<div class="rot-err-wrapper">
  
  <p class="rot-err-caption">⭕️ ホバーしてみよう!インライン要素は回らない(形も崩れる)!「inline-block」にしろ!</p>

  <div class="rot-err-demo-area">
    
    <div class="err-item">
      <span class="err-icon is-trap-inline">➔</span>
      <p class="err-desc">❌ 罠(inline)<br>幅も高さも効かず、回らない</p>
    </div>

    <div class="err-item">
      <span class="err-icon is-success-block">➔</span>
      <p class="err-desc">⭕️ 成功(inline-block)<br>丸みを保ち、ホバーで上を向く</p>
    </div>

  </div>

  <div class="rot-err-code-area">
    <span class="hl-comment">/* ❌ 罠:spanタグ(デフォルトはinline)にそのまま回転を指定する */</span><br>
    <span class="hl-blue">.icon-fail:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">-90deg;</span> <span class="hl-comment">/* 🚨 変形が無効化されているため効かない! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ 必ず display: inline-block; を指定してから回す! */</span><br>
    <span class="hl-blue">.icon-success</span> {<br>
      <span class="hl-green">display:</span> <span class="hl-red">inline-block;</span> <span class="hl-comment">/* 💡 これで高さや変形を受け付けるようになる */</span><br>
      <span class="hl-green">transition:</span> <span class="hl-red">rotate 0.3s ease;</span><br>
    }<br>
    <span class="hl-blue">.icon-success:hover</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">-90deg;</span> <span class="hl-comment">/* 💡 完璧に回る! */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-err-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-err-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-err-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.err-item {
  /* 💡 修正:Flexboxをやめて、標準の中央揃えに変更(インライン要素を維持するため) */
  display: block;
  text-align: center;
  width: 150px;
}

.err-icon {
  font-size: 40px;
  color: #0d6efd;
  background-color: #fff;
  /* ↓ 罠(inline)の方は、これらのサイズ指定も無視されるため形が崩れます */
  width: 60px;
  height: 60px;
  line-height: 60px;
  border-radius: 50%;
  box-shadow: 0 4px 10px rgba(0,0,0,0.1);
  cursor: pointer;
}

.err-desc {
  /* 💡 修正:アイコンとの間に余白を作るため、ブロック要素にする */
  display: block;
  margin-top: 15px; 
  margin-bottom: 0;
  font-size: 13px;
  color: #333;
  font-weight: bold;
  line-height: 1.5;
}

/* === ❌ 罠:インライン要素のまま === */
.is-trap-inline {
  /* spanのデフォルト(display: inline;)のまま */
  /* inlineなので、widthもheightも効かず、背景が文字にピタッとくっついた不格好な形になります */
  transition: rotate 0.3s ease; 
}
.is-trap-inline:hover {
  rotate: -90deg; /* 🚨 回転も効かない */
}

/* === ⭕️ 成功:inline-blockを指定 === */
.is-success-block {
  /* 💡 必須:変形とサイズ指定を許可する */
  display: inline-block; 
  transition: rotate 0.3s ease;
}
.is-success-block:hover {
  rotate: -90deg; /* 💡 正しく回る */
}

/* =コード解説エリア= */
.rot-err-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

displayの使い方を詳しく知りたい人は「【CSS】displayの種類は?flexやinline-blockの違い」を一読ください。

hue-rotate(色相回転)や枠線・影の回転

CSSの「回転」は、要素そのものの角度だけでなく、色や影の回転にも応用できます。

例えば、画像やボタンの色味をガラッと変えたい時は、要素を回すのではなく、フィルター機能の色相回転を使用します。

これをアニメーションさせれば、ゲーミングPCのように色が無限に変化するアニメーションが実装できます。

また、要素は回さずに「影だけを回したい」場合や、「枠線だけを回したい」といった高度な装飾も、疑似要素と組み合わせることで可能になります。

色相や影を回転させるには、「色はfilter: hue-rotate(度数);で回すこと。影や枠線だけを回したい場合は、要素自体に影をつけるのではなく、同じ大きさの『疑似要素(::before)』に影をつけ、疑似要素だけをrotateで回して背後(z-index: -1)に隠すこと」です。

⭕️ ホバーしてみよう!色(hue)、影(shadow)、そして枠線(border)の回転トリック!

css filter hue rotate
ホバーで色が虹色に変化!

Shadow

css rotate box shadow
箱は止まったまま影が回る!

Border

css rotate border
ホバーで枠線が無限回転!

/* ⭕️ トリック1:色は filter: hue-rotate() で回す! */
.btn-hue:hover {
  animation: rainbow 2s linear infinite;
}

/* ⭕️ トリック2:影だけを回すなら、裏に置いた疑似要素を回す! */
.box-shadow {
  z-index: 0; /* 💡 必須:影が完全に裏へ抜け落ちるのを防ぐ */
}
.box-shadow::before {
  box-shadow: 12px 12px 0px rgba(0, 0, 0, 0.3); /* 💡 疑似要素に影をつける */
  z-index: -1; /* 箱の裏へ */
}
.box-shadow:hover::before {
  rotate: 90deg; /* 💡 ホバーで影(疑似要素)だけを回す! */
}

/* ⭕️ トリック3:枠線の回転は「回るグラデーション」を中身でフタをする! */
.box-border::before {
  background-image: linear-gradient(45deg, #ff007f, #00d2ff); /* 下地になるグラデ */
}
.box-border::after {
  inset: 4px; /* 💡 枠線の太さ分だけ内側にフタ(単色背景)を被せる */
}
.box-border:hover::before {
  animation: spin 1.5s linear infinite; /* 💡 下地を回すことで枠線が回って見える! */
}
HTMLコード表示
<div class="rot-app-wrapper">
  
  <p class="rot-app-caption">⭕️ ホバーしてみよう!色(hue)、影(shadow)、そして枠線(border)の回転トリック!</p>

  <div class="rot-app-demo-area">
    
    <div class="app-item">
      <button class="app-btn is-hue">Hue Rotate</button>
      <p class="app-desc">css filter hue rotate<br>ホバーで色が虹色に変化!</p>
    </div>

    <div class="app-item">
      <div class="app-box is-shadow-rotate">Shadow</div>
      <p class="app-desc">css rotate box shadow<br>箱は止まったまま影が回る!</p>
    </div>

    <div class="app-item">
      <div class="app-box is-border-rotate">
        <span class="border-text">Border</span>
      </div>
      <p class="app-desc">css rotate border<br>ホバーで枠線が無限回転!</p>
    </div>

  </div>

  <div class="rot-app-code-area">
    <span class="hl-comment">/* ⭕️ トリック1:色は filter: hue-rotate() で回す! */</span><br>
    <span class="hl-blue">.btn-hue:hover</span> {<br>
      <span class="hl-green">animation:</span> <span class="hl-red">rainbow 2s linear infinite;</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ トリック2:影だけを回すなら、裏に置いた疑似要素を回す! */</span><br>
    <span class="hl-blue">.box-shadow</span> {<br>
      <span class="hl-green">z-index:</span> <span class="hl-red">0;</span> <span class="hl-comment">/* 💡 必須:影が完全に裏へ抜け落ちるのを防ぐ */</span><br>
    }<br>
    <span class="hl-blue">.box-shadow::before</span> {<br>
      <span class="hl-green">box-shadow:</span> <span class="hl-red">12px 12px 0px rgba(0, 0, 0, 0.3);</span> <span class="hl-comment">/* 💡 疑似要素に影をつける */</span><br>
      <span class="hl-green">z-index:</span> <span class="hl-red">-1;</span> <span class="hl-comment">/* 箱の裏へ */</span><br>
    }<br>
    <span class="hl-blue">.box-shadow:hover::before</span> {<br>
      <span class="hl-green">rotate:</span> <span class="hl-red">90deg;</span> <span class="hl-comment">/* 💡 ホバーで影(疑似要素)だけを回す! */</span><br>
    }<br><br>

    <span class="hl-comment">/* ⭕️ トリック3:枠線の回転は「回るグラデーション」を中身でフタをする! */</span><br>
    <span class="hl-blue">.box-border::before</span> {<br>
      <span class="hl-green">background-image:</span> <span class="hl-red">linear-gradient(45deg, #ff007f, #00d2ff);</span> <span class="hl-comment">/* 下地になるグラデ */</span><br>
    }<br>
    <span class="hl-blue">.box-border::after</span> {<br>
      <span class="hl-green">inset:</span> <span class="hl-red">4px;</span> <span class="hl-comment">/* 💡 枠線の太さ分だけ内側にフタ(単色背景)を被せる */</span><br>
    }<br>
    <span class="hl-blue">.box-border:hover::before</span> {<br>
      <span class="hl-green">animation:</span> <span class="hl-red">spin 1.5s linear infinite;</span> <span class="hl-comment">/* 💡 下地を回すことで枠線が回って見える! */</span><br>
    }
  </div>

</div>
CSSコード表示
.rot-app-wrapper {
  background-color: #f8f9fa;
  padding: 30px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.rot-app-caption {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.rot-app-demo-area {
  display: flex;
  flex-wrap: wrap;
  gap: 40px;
  background-color: #e9ecef;
  padding: 50px 20px;
  border-radius: 8px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
  justify-content: center;
}

.app-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 25px; /* 要素とテキストの余白 */
  width: 150px;
}

.app-desc {
  margin: 0;
  font-size: 12px;
  color: #333;
  text-align: center;
  font-weight: bold;
  line-height: 1.5;
}

/* ボックスの共通スタイル */
.app-box {
  width: 100px;
  height: 100px;
  font-weight: bold;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}


/* === 💡 トリック1:色相回転(hue-rotate) === */
.app-btn {
  background-color: #fd7e14; /* ベースのオレンジ色 */
  color: #fff;
  border: none;
  padding: 15px 25px;
  font-size: 15px;
  font-weight: bold;
  border-radius: 30px;
  cursor: pointer;
  box-shadow: 0 4px 10px rgba(0,0,0,0.2);
  margin-top: 25px; /* 高さを揃えるための調整 */
}

@keyframes rainbow {
  100% {
    /* 色相環を360度回転(一周)させる */
    filter: hue-rotate(360deg);
  }
}

.is-hue:hover {
  /* ホバー時にアニメーション発動 */
  animation: rainbow 2s linear infinite;
}


/* === 💡 トリック2:影だけの回転 === */
.is-shadow-rotate {
  position: relative;
  /* 💡 修正箇所:z-index: 0; で重なりの基準を作り、影が背景の裏に消えるのを防ぐ */
  z-index: 0; 
  background-color: #6f42c1;
  color: #fff;
}

/* 影専用の疑似要素 */
.is-shadow-rotate::before {
  content: "";
  position: absolute;
  /* 本体と全く同じサイズにする */
  inset: 0;
  border-radius: inherit;
  
  /* 💡 疑似要素に対して濃い目の影をつける */
  box-shadow: 12px 12px 0px rgba(0, 0, 0, 0.3);
  
  /* 箱の裏側に隠す */
  z-index: -1;
  transition: rotate 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.is-shadow-rotate:hover::before {
  /* 💡 ホバー時に影(疑似要素)だけを回す! */
  rotate: 90deg;
}


/* === 💡 トリック3:枠線の回転(新規追加) === */
.is-border-rotate {
  position: relative;
  z-index: 0;
  background-color: #343a40; /* 万が一のための下地色 */
  /* はみ出た回転グラデーションをカットする */
  overflow: hidden; 
}

/* 下地となるグラデーション(これを回す) */
.is-border-rotate::before {
  content: "";
  position: absolute;
  /* 角に隙間ができないよう箱より大きくする */
  width: 150%;
  height: 150%;
  background-image: linear-gradient(45deg, #ff007f, #00d2ff);
  z-index: -2; /* 一番後ろへ */
  transition: rotate 0.3s ease;
}

/* 内側をくり抜くためのフタ(背景色) */
.is-border-rotate::after {
  content: "";
  position: absolute;
  /* 💡 ここで枠線の太さを決める(上下左右から4px内側にフタをする) */
  inset: 4px; 
  background-color: #f8f9fa; /* 白いフタ */
  border-radius: 4px; /* フタの角丸 */
  z-index: -1; /* グラデーションの上、文字の下へ */
}

/* テキストを一番上に持ってくる */
.border-text {
  position: relative;
  z-index: 1;
  color: #333;
}

/* ホバーで無限回転アニメーションを発動 */
.is-border-rotate:hover::before {
  animation: spin-border 1.5s linear infinite;
}

@keyframes spin-border {
  100% { rotate: 1turn; } /* 1回転(360度) */
}


/* =コード解説エリア= */
.rot-app-code-area {
  background-color: #282c34;
  color: #abb2bf;
  padding: 20px;
  border-radius: 6px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
  overflow-x: auto;
  text-align: left;
}
.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • 独立プロパティの使用
    transformの上書き事故を防ぐため、現在は独立したrotateプロパティを使用するのが主流である。
  • 角度の単位
    deg(度数)やturn(回転数)を使用し、数値と単位の間にスペースは入れない。
  • インライン要素の罠
    spanaなどのインライン要素は回転しないため、display: inline-blockなどを指定する。
  • テキストの回転
    折り返しによる崩れを防ぐため、white-space: nowrapと親要素の高さ(height)確保をセットで行う。
  • 基準点の操作
    transform-originで回転の軸(画鋲の位置)をずらし、周囲のレイアウトとの干渉やアニメーションの軌道を制御する。
  • 3D回転と遠近感
    X軸・Y軸の回転で立体感を出すには、親要素にperspective(遠近感)を指定する。
  • 3D空間の維持
    カードの裏返し等を行う場合、回転する親要素にtransform-style: preserve-3d、裏面を隠すためにbackface-visibility: hidden を指定する。
  • ホバーアニメーション
    滑らかに変化させるtransitionは、変化後(:hover)ではなく、通常状態(変化前)に記述する。
  • 無限ループの等速回転
    ローディングなどの無限回転は、animationのタイミング関数にlinearを指定してカクつきを防ぐ。
  • 影・背景のみの回転
    要素本体を回さず、背景画像や影(box-shadow)だけを回す場合は、疑似要素を作成して裏側で回転させる。
  • 色相の回転
    要素の色を虹色などに変化させる場合は、rotateではなくfilter: hue-rotate()を使用する。

よくある質問(FAQ)

rotateプロパティとtransform: rotate()の違いは何ですか?

どちらも要素を回転させますが、「他の変形プロパティとの競合」が異なります。

以前はtransform: rotate(45deg);と記述するのが一般的でしたが、現在は独立したrotate: 45deg;プロパティが主流です。

独立プロパティを使えば、translate(移動)や scale(拡大縮小)を同時に指定した際に、お互いの設定を上書きして打ち消してしまう事故を防ぐことができます。

CSSに記述したのに要素が回転しない(効かない)のはなぜですか?

最も多い原因は、回転させようとしている対象が<span><a>などの「インライン要素」になっていることです。

CSSの仕様上、インライン要素はrotateをはじめとする変形プロパティを一切受け付けません。

解決するには、対象の要素にdisplay: inline-block;(またはdisplay: block;)を追加してください。

これで正常に回転するようになります。

要素の真ん中ではなく、端(左上など)を軸にして回転させるにはどうすればいいですか?

回転の基準点(画鋲を刺す位置)を変更するには、transform-originプロパティを使用します。

デフォルトでは要素の中心(center)が軸になっていますが、これをtransform-origin: top left;(左上)やtransform-origin: bottom center;(下部中央)などに変更することで、振り子やワイパーのような軌道で回転させることができます。

ホバーした時にパチッと変わるのではなく、滑らかに回転させるには?

transitionプロパティを使用してアニメーションさせます。

ここでの最大の注意点は、transition: rotate 0.3s ease;という指定を「:hover(ホバー時)」のブロックではなく、「通常状態(変化前)」のブロックに記述することです。

通常状態に記述することで、マウスを乗せた時だけでなく、外した時も滑らかに元の角度に戻るようになります。

要素を平面ではなく、立体的に(奥へ倒すように)回転させることはできますか?

はい、X軸やY軸を指定することで3D回転が可能です。

rotate: x 60deg;(奥へ倒れる)やrotate: y 60deg;(ドアのように開く)と記述します。

ただし、立体的に見せるためには、回転させる要素の親要素に対してperspective: 1000px;などの「遠近感」を設定してください。

これを忘れると、ただ要素がペタンコに潰れたように見えてしまいます。

CONTACT

サイト制作でお困りの人はお気軽にご連絡ください。
どんなお悩み事も丁寧に返信させて頂きます。

WordPress移行
Webサイトを公開しよう!

「どのサーバーを選べばいいか分からない…」そんな悩みを解決!
WordPressデビューに最適なサーバーを徹底比較しました。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次