Kazuma Labolatory's

Nothing is Impossible. ✿

Menu

【CSS】「アスペクト比一定 + サイズ変化するBox」と、そのカラクリ

(かなり書きかけ感満載ですが、投稿できる見込みが( ³ω³ ).。o なので、とりあえず投稿しておきます。

関係が複雑なものを「分かりやすく」説明するのは、難しい、難しぃ~0(:3 )~ ('、3_ヽ)_ )

1:1
2:1
1:2
4:3
16:9

 

画面幅を変えてみて下さい。タブレットやスマホなら画面を横にしてみて下さい。boxサイズは変わっても、横縦比(アスペクト比)は変わらないはずです。

CSS
/*-------- 2:1 ------*/
.ratio2_1 {
	position: relative;
	width: 300px; /* 設定したい横幅 */
	}
.ratio2_1::before {
	content: "";
	display: block;
	padding-top: 50%;
	}

/*--------------*/
.content {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	/* --- デモ用 スタイリング --- */
	background: #33302e;
	color: #fff;
	font-size: 1.25rem;
	padding: 0.75rem 0 0 1.5rem;
	}
HTML
<div class="ratio2_1"> 
	<div class="content">2:1
	</div>
</div>

Aspect-Ratio

【元記事】--- A List Apar(2009.5)

http://alistapart.com/d/creating-intrinsic-ratios-for-video/example2.html

【改良版記事】--- Made My Day.de(2013.6)

http://www.mademyday.de/css-height-equals-width-with-pure-css.html

 

このCSSが活用できるケース

●(画像のように)デフォルトの大きさが存在しないもので…

●中身に依らない比率維持ボックスを作る時

 

ちょっと抽象的すぎて分かりにくいですね?

一例を挙げれば、このブログのトップページのような感じです(このブログの場合はカードサイズが固定ですが)。


テキストの有無に関係なく2カラムカード表示にしたい + 視聴デバイスによってボックスサイズは変化させたいが、比率は維持したい場合 ( overflow-y :hidden; ) 等に活用できる。

注意⚠️ 他のWebサイトでも指摘されてありましが、Flex box内ではうまく機能しないようです。Browserによるものなのかは僕もまだ検証していません。ただ、試してみましたか(safari/ iOS10) うまくいきませんでした。


?ポイント?

❸親要素のheight自動伸縮

❶Paddingで%を使う( %の基準元 )

❷コンテイニング・ブロック

 

振り番号は間違いではありませんw

要となるのは、横幅の変化に伴い縦幅が自動伸縮する所❸にあります。そして、このために2レイヤー(親子要素)必要になってきます。

ただそこにたどり着くために必ず押さえておかなければいけない事があります。それこそが、このボックスの真骨頂とも言えるトリックであり、❶paddingの%指定 と ❷コンテイニング・ブロックなのです。

 

それでは説明していきます。

カラクリ解説

❶「paddingの%指定」と「%の基準元」



CSS 2.2 - W3C

8.4 Padding properties:

...

...

<percentage>

The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.2.

- CSS2.2/ 8.Box Model/ 8.4 Padding Property

https://www.w3.org/TR/CSS22/box.html#padding-properties

CSS 2.2 - W3C

8.4 Padding プロパティ:

...

...

%は、「作成予定のボックスのコンテイニング・ブロックの横幅」を基準に計算されます。%を使うのがpadding-topやpadding-bottomであってもです。コンテイニング・ブロックの横幅がこの作成予定の要素によって決定される場合は、未定義のレイアウトになります。

要約すると、「paddingに%を用いた際基準になる要素は、コンテイニング・ブロックの横幅」 ということ。

❷Containing Block(コンテイニング・ブロック) とは

CSS 2.2 - W3C

...

...

10.1 Definition of "containing block"

The position and size of an element's box(es) are sometimes calculated relative to a certain rectangle, called the containing block of the element. The containing block of an element is defined as follows:

1. The containing block in which the root element lives is a rectangle called the initial containing block. For continuous media, it has the dimensions of the viewport and is anchored at the canvas origin; it is the page area for paged media. The 'direction' property of the initial containing block is the same as for the root element.

2. For other elements, if the element's position is 'relative' or 'static', the containing block is formed by the content edge of the nearest ancestor box that is a block container or which establishes a formatting context.

...

4. If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed', in the following way:

1. In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.2, if the inline element is split across multiple lines, the containing block is undefined.

2. Otherwise, the containing block is formed by the padding edge of the ancestor.

5. If there is no such ancestor, the containing block is the initial containing block.

- 10-1. Definition of "Containing Block"/ -W3C - CSS2.2/ 10. Visual formatting model details

https://www.w3.org/TR/CSS22/visudet.html#containing-block-details

CSS 2.2 - W3C

...

...

10.1 「コンテイニング・ブロック」の定義

しばしば、ある要素内のボックスの大きさやポジションは、ある四角形を基準に計算されることがあり、その基準となる四角形を、その要素のコンテイニング・ブロック(含みブロック)と言います。要素のコンテイニング・ブロックは以下のように定義されます:

1.ルート要素が有効な場合の、コンテイニング・ブロックは、イニシャルコンテイニング・ブロックと言います。様々な視聴媒体において、それは、ビューポートの次元を持っており、キャンバスの始点にアンカーされています; それは表示メディア用のページ・エリアです。イニシャルコンテイニング・ブロックの"direction"プロパティは、ルート要素(html要素)と同じです。

2.他の場合において。もし作成予定の要素のポジションが"relative"か'static"なら、そのコンテイニング・ブロックは、ブロックコンテナである最も近い先祖の内側によって形作られます。

...

4.もし作成予定の要素が"position: absolute" なら、コンテイニング・ブロックは"position: absolute, relative, fixed" をもつ最も近い祖先によって形成されます。その形成のされ方は、以下の通りです。

1.祖先がインライン要素の場合は、そのコンテイニング・ボックスが形作られる場所の、上に位置するインライン要素と下に位置するインライン要素によって形作られ、場合によって大きさが変化するバウンディングボックスになります。CSS 2.2では、インライン要素が複数の行に分離している場合、コンテイニング・ブロックは未定義となります。

2.そうでなければ、コンテイニング・ブロックは、先祖の内側によって形成されます。

5.そのような先祖がいなければ、そのコンテイニング・ブロックはイニシャルコンテイニング・ブロックです。

- 10-1. 「コンテイニング・ブロック」の定義 / -W3C - CSS2.2/ 10. 視覚的フォーマット・モデル詳細

 

自分で訳して読んでみても、いまいち分かりにくいですね??

要約すると…

今作ろうとしているboxの親要素の内側が、コンテイニング・ブロックである

ということです。

 

  • 今作ろうとしているboxに、親要素がない場合: htmlがコンテイニング・ブロックになり、それをイニシャルコンテイニング・ブロックと呼ぶ。htmlそのものではなく、"表示画面によって形作られる四角形"をコンテイニング・ブロックと呼ぶ。
  • 〃 親要素がある場合: その親要素の内側 ( padding-box ) がコンテイニング・ブロック

 

box-model - W3C --- https://www.w3.org/TR/CSS21/box.html

 

補足

 

…後でまたは図示してみます??

a list Apart さんが2009年に書かれていた記事は、まさにこのトリックを使ったものです。

 

HTML

<div class="ratio-base">
    <div class="content">
    </div>
</div>

 

CSS (アスペクト比 5:1)

div.ratio-base {
	position: relative;
	padding-bottom: 20%; 
	height: 0;
   }
div.content {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: teal;	
   }

 

5:1
 


ですが、これには問題があります。それは width: 100% の時にしか機能しないという事です。

先の a list apart さんのCSSをもう一度みてみて下さい。div.ratio-baseではwidth は書かれていませんが width: 100%になっています。理由はdiv の規定値が display: block, width: 100%で、書かなくてもOKだからです。

では仮に、先のCSSをwidth: 300px;にしてみると…

.ratio-base1-1 {
	position: relative;
	padding-bottom: 20%;
	height: 0;
	width: 300px;
   }
.content1-1 {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: teal;	
   }

 

5:1

 

見比べてみて下さい。縦幅は変わっていません。理由は、div.ratio-base のコンテイニング・ブロックがbodyだからです。

引用




という事で、これを解決するため、コンテイニング・ブロックに注意して、CSSをいじった結果がこちら↓↓

.ratio-base1-2 {
   position: relative;
   width: 300px;
   height: auto;
   }
.content1-2 {
   position: absolute;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
   background: teal;
   padding-bottom: 20%;	
   }

 

width: 300px
height: 20%( 300 × 0.2 = 60px )
width:60px
heighs:60px
width:60px
heighs:60px
 
 
 
 
 

 

ちゃんと 5:1 になりました。

ちなみに、上記のデモを見て気付きましたが、box-sizing:border-boxの場合は、border-boxがコンテイニング・ブロックになるみたいですね?

 

❷-2 : 実はこれでは親要素が自動伸縮しない

見る方が分かりやすいので以下にdemoを。。

 

demo
子: content1-2

すぐ下1番目の<p>

〃2番目の<p>

〃3番目の<p>


親要素(水色ドット) が伸縮しておらず、すぐ次の<p>が被っているのがわかっていただけるだろうか。

親要素に文字を入れるとなお分かりやすいかも知れない。

親: ratio-base1-2
子: content1-2

すぐ下1番目の<p>

〃2番目の<p>

〃3番目の<p>

 

問題 : 親要素が自動伸縮せず(子要素のoverflow)、次に来るブロック要素が被ってしまう。

と言う事で、結局これも悪くはないのだが、手直し等面倒で少し実用性に欠ける。

そこでこれを解決したのが、本記事先頭で紹介した「Make my Day.de」さんの擬似クラスを使ったコードなのだ。

 

❸擬似クラス::before | ::afterで全て解決

結局3レイヤー使っていることになりますね。先の親要素が伸縮しない問題を擬似クラスを入れることによって解決しています。もう一度先のコードを5:1用に変えて見てみましょう。

CSS
/*-------- 5:1 ------*/
.ratio5_1 {
	position: relative;
	width: 300px; /* 設定したい横幅 */
	}
.ratio5_1::before {
	content: "";
	display: block;
	padding-top: 20%; /*bottomでも可 */
	}

/*--------------*/
.content {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	/* --- デモ用 スタイリング --- */
	background: #33302e;
	color: #fff;
	font-size: 1.25rem;
	padding: 0.75rem 0 0 1.5rem;
	}
HTML
<div class="ratio5_1"> 
	<div class="content">5:1
	</div>
</div>

 

擬似クラスはpositionプロパティを使っていないので、親要素と同レイヤーになります。そして、先のpadding-bottom(top)プロパティを使って縦幅を自動伸縮するようにしています。

その結果、position: alsoluteの子要素は、親Box内に自由にレイアウトできるという訳ですね? お見事です?

5:1

 

 

 

 

 

 

 

補講 : 普通にdiv同士で親子関係作ればOK?

abc

いけますねw ただ、上下のpaddingは縦幅に使ってしまっているので使えません。唯一そこだけが問題ですね。それ以外は、コードも仕組みもシンプルで悪くはないんですけどね。

無理でしたね( ¯∀¯٥)?w paddingで縦幅を決定しているため、文字も縦幅の計算に入ってしまいますね。そりゃそうですよね、はい(*⚫︎ー⚫︎)b ?w

This Blog uses M+ Font, Logo Type Gothic, Google Fonts and FontAwesome. It"s free & Designed cool font. Greatful for Koji Morishita of M+ Fonts Designer( Creator) and "フォントな" , Google, Adobe, and Dave Gandy!
Background Photos is downloaded by Unsplash.com. Thanks!
|*´-`)チラッ
Please Click Me
本ブログ全てにおいて、アフィリエイトプログラムには参加しておりません(•ᵕᴗᵕ•) 詳しくはこちらをご覧下さい。また、 以下のバナーは、私が「質が高い・あら素敵(ˊo̶̶̷ᴗo̶̶̷`)✨」と感じたサイト様を掲載させて頂いておます_(( _๑´ω`))_⭐️