1. ホーム
  2. css

[解決済み] 親要素の高さに影響を与えるCSSの回転要素

2022-06-09 03:19:45

質問

いくつかのカラムがあり、そのうちのいくつかは値を回転させたいとします。

http://jsfiddle.net/MTyFP/1/

<div class="container">
    <div class="statusColumn"><span>Normal</span></div>
    <div class="statusColumn"><a>Normal</a></div>
    <div class="statusColumn"><b>Rotated</b></div>
    <div class="statusColumn"><abbr>Normal</abbr></div>
</div>

このCSSで

.statusColumn b {
  writing-mode: tb-rl;
  white-space: nowrap;
  display: inline-block;
  overflow: visible;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}

最終的にはこのようになります。

テキストが他の要素に重ならないように、回転した要素が親の高さに影響を与えるようなCSSを書くことは可能でしょうか?以下のようなものです。

どのように解決するのですか?

90 度回転させたいと仮定すると、これはテキスト以外の要素でも可能です。しかし、CSS の多くの興味深い事柄と同様に、少し狡猾さが必要です。そのため、Chrome、Firefox、Safari、および Edge で動作することをテストして確認しましたが、将来のブラウザのリリースで壊れないことを約束することはできません。

短い回答

このようなHTMLがあったとして、回転させたい場合 .element-to-rotate ...

<div id="container">
  <something class="element-to-rotate">bla bla bla</something>
</div>

... 紹介 ラッパー要素を導入します。

<div id="container">
  <div class="rotation-wrapper-outer">
    <div class="rotation-wrapper-inner">
      <something class="element-to-rotate">bla bla bla</something>
    </div>    
  </div>
</div>

...そして、反時計回りに回転させるために、以下のCSSを使用します(または、コメントアウトされた transform を使えば、時計回りに回転させることができます)。

.rotation-wrapper-outer {
  display: table;
}
.rotation-wrapper-inner {
  padding: 50% 0;
  height: 0;
}
.element-to-rotate {
  display: block;
  transform-origin: top left;
  /* Note: for a CLOCKWISE rotation, use the commented-out
     transform instead of this one. */
  transform: rotate(-90deg) translate(-100%);
  /* transform: rotate(90deg) translate(0, -100%); */
  margin-top: -50%;

  /* Not vital, but possibly a good idea if the element you're rotating contains
     text and you want a single long vertical line of text and the pre-rotation
     width of your element is small enough that the text wraps: */
  white-space: nowrap;
}

スタック・スニペット・デモ

p {
  /* Tweak the visuals of the paragraphs for easier visualiation: */
  background: pink;
  margin: 1px 0;
  border: 1px solid black;
}
.rotation-wrapper-outer {
  display: table;
}
.rotation-wrapper-inner {
  padding: 50% 0;
  height: 0;
}
.element-to-rotate {
  display: block;
  transform-origin: top left;
  /* Note: for a CLOCKWISE rotation, use the commented-out
     transform instead of this one. */
  transform: rotate(-90deg) translate(-100%);
  /* transform: rotate(90deg) translate(0, -100%); */
  margin-top: -50%;

  /* Not vital, but possibly a good idea if the element you're rotating contains
     text and you want a single long vertical line of text and the pre-rotation
     width of your element is small enough that the text wraps: */
  white-space: nowrap;
}
<div id="container">
  <p>Some text</p>
  <p>More text</p>
  <div class="rotation-wrapper-outer">
    <div class="rotation-wrapper-inner">
      <p class="element-to-rotate">Some rotated text</p>
    </div>    
  </div>
  <p>Even more text</p>
  <img src="https://i.stack.imgur.com/ih8Fj.png">
  <div class="rotation-wrapper-outer">
    <div class="rotation-wrapper-inner">
      <img class="element-to-rotate" src="https://i.stack.imgur.com/ih8Fj.png">
    </div>
  </div>
  <img src="https://i.stack.imgur.com/ih8Fj.png">
</div>

どのように動作するのですか?

私が上で使った呪文を前にして混乱するのは当然です。多くのことが行われており、全体的な戦略は単純ではなく、理解するためにはCSSの豆知識が必要です。それでは、順を追って説明しましょう。

私たちが直面している問題の核心は、要素に適用される変換がその transform CSS プロパティを使用して要素に適用される変換は、すべてレイアウトが行われた後に発生することです。言い換えれば transform を使用しても、その親要素や他の要素のサイズや位置には全く影響を与えません。この事実を変更する方法は全くありません。 transform が機能するという事実を変更する方法は全くありません。したがって、要素を回転させ、その親の高さが回転を尊重する効果を生み出すには、次のことを行う必要があります。

  1. 何らかの方法で、いくつかの その他の 要素の高さが .element-to-rotate
  2. トランスフォームを .element-to-rotate に、ステップ 1 の要素に正確に重なるように変形を記述します。

ステップ1からの要素は .rotation-wrapper-outer . しかし、どのようにしてその の高さ と等しくなるように .element-to-rotate 's の幅 ?

この戦略における重要なコンポーネントは padding: 50% 0 にあります。 .rotation-wrapper-inner . このエクスプロイトの の仕様の風変りな部分です。 padding の仕様で、パーセンテージのパディングは padding-toppadding-bottom のパーセンテージで定義されます。 要素のコンテナの幅 . これにより、以下の2段階のトリックを実行することができます。

  1. 私たちは display: table.rotation-wrapper-outer . これによって に合わせた幅に縮小 を持つことになります。これは、その幅がそのコンテンツの固有幅に基づいて設定されることを意味します。 .element-to-rotate . (サポートされているブラウザでは width: max-content を使用することもできますが、2017年12月時点では max-content はまだ Edge でサポートされていません。 .)
  2. を設定します。 height.rotation-wrapper-inner を0に設定し、そのパディングを 50% 0 に設定します (つまり、上 50%、下 50%)。これにより、親の幅の100%に相当する垂直方向のスペースを取るようになります。これは、手順 1 のトリックにより .element-to-rotate .

次に残っているのは、子要素の実際の回転と位置決めを行うことです。当然ながら transform: rotate(-90deg) は回転を行います。 transform-origin: top left; を使用して、回転した要素の左上隅を中心に回転するようにしています。これにより、回転した要素が他の方法で描画されたであろう場所の真上に残るため、その後の移動について簡単に説明できます。次に translate(-100%) で、回転前の幅と同じ距離だけ要素を下方にドラッグします。

の 50% の上部パディングをオフセットする必要があるため、これはまだ正しい位置決めにはなっていません。 .rotation-wrapper-outer . これを実現するには .element-to-rotate には display: block (余白が正しく機能するように)そして、-50%の margin-top - なお、パーセントマージンは でも定義されます。

で、終わりです!

なぜこれは完全な仕様準拠ではないのですか?

なぜなら のため、仕様のパーセンテージのパディングとマージンの定義から次のような注記があります。 (となります(太字は私)。

<ブロッククオート

を基準にしてパーセンテージを算出します。 を基準に計算されます。 を含むブロック の場合であっても 'パディングトップ' 'パディングボトム' . 含むブロックの幅がこの要素に依存する場合、結果のレイアウトはCSS 2.1では未定義となります。

全体のトリックは、内側のラッパー要素のパディングを、順番にその子の幅に依存しているそのコンテナの幅に相対的にすることに展開されるので、この条件にヒットし、未定義の動作を呼び出しています。これは現在、4つの主要なブラウザすべてで動作していますが、私が試した、一見仕様に準拠したアプローチの調整、たとえば .rotation-wrapper-inner の兄弟であるように .element-to-rotate の兄弟になります。