HTML・CSSテックラボ

FlexBoxで固定幅+可変幅のレイアウト

CSSのFlexBoxを使って1カラムを固定幅、もう1カラムをリキッド(可変幅)にし、ウインドウサイズが一定のサイズ以下になると、固定幅のカラムを下に落とし、両カラムとも横幅100%にする方法を紹介します。

デモ

HTMLは以下の通りです。
※レイアウトに必要な部分のみの抜粋です。

<main>
	<div class="entry">
		entry
	</div>
	<div class="sub">
		sub
	</div>
</main>

SCSSは以下の通りです。

@import "bourbon";	// Bourbonの読み込み

// レスポンシブ用横幅指定
$w-entry: 600px;
$w-sub: 300px;
$w-margin: 10px;

// 簡易なCSSリセット
*, *:before, *:after {
	box-sizing: border-box;
	margin: 0; padding: 0;
}

/* ========================================================
レイアウト
=========================================================*/
main{
	// FlexBox指定
	@include display(flex);
	@include flex-flow(row wrap);

	// リキッドカラム
	.entry{
		// flex-growを1に指定
		// 余白をflexアイテムで分け合い、自動的に横幅が調整されます。
		@include flex(1);

		// ▼ min-widthと余白の設定
		min-width: $w-entry;
		margin-right: $w-margin;

		// ▼下記2行は見栄えを整えるためで必須ではない
		background: #efefef;
		padding: 20px;
	}
	// 固定幅カラム
	.sub{
		// 横幅の設定
		width: $w-sub;

		// ▼下記2行は見栄えを整えるためで必須ではない
		background: #efefef;
		padding: 20px;
	}
}

/* ========================================================
レスポンシブ用(カラム落ちした際の処理)
=========================================================*/
// ウインドウサイズが .entry の min-width + 余白 + .sub の横幅以下になった場合の処理です
@media only screen and (max-width: $w-entry + $w-sub + $w-margin) {
	main{
		.entry{
			// 横幅を100%
			width: 100%;
			// ▼min-width、余白をリセット
			min-width: inherit;
			margin-right: 0;
		}
		.sub{
			// 横幅を100%
			width: 100%;

			// 見栄えを整えるためで必須ではない
			margin-top: 10px;
		}
	}
}

ポイントとしてはリキッドさせたいカラムに flex-grow:1 を指定します。この指定で余白をflexアイテムで分け合い、自動的に横幅が調整されるようになります。
SCSSでは下記のように指定します。

@include flex(1);

このままだとウインドウサイズに合わせてどこまでも小さくなるので、min-width で最小の横幅を設定しておくと良いでしょう。

.entry{
	@include flex(1);
	min-width: $w-entry;
}

メディアクエリを使って、固定幅カラムが落ちたとき、固定幅のカラムとリキッドのカラムの横幅が100%になるような処理を加えます。
まず、固定幅カラムの横幅と、リキッドカラムの最小の横幅、余白を変数にしておきます。

$w-entry: 600px;
$w-sub: 300px;
$w-margin: 10px;

設定した変数を足した値がカラム落ちするウインドウサイズの横幅になるので、下記のようにメディアクエリに値を指定します。
※ここでは2つのカラムとその間の余白の3つの値だけですが、さらに両カラムの左右に余白がある場合はその値も足します。

@media only screen and (max-width: $w-entry + $w-sub + $w-margin) {

ポイントになるのは以上です。

SCSSを使わない人ように出力結果のCSSも記載します。
※ベンダープレフィックスは省略しています。

*, *:before, *:after {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

main {
	display: flex;
	flex-flow: row wrap;
}
main .entry {
	flex: 1;
	margin-right: 10px;
	min-width: 600px;
	background: #efefef;
	padding: 20px;
}
main .sub {
	width: 300px;
	background: #efefef;
	padding: 20px;
}

/* ========================================================
レスポンシブ用(カラム落ちした際の処理)
=========================================================*/
@media only screen and (max-width: 910px) {
	main .entry {
		width: 100%;
		min-width: inherit;
		margin-right: 0;
	}
	main .sub {
		margin-top: 10px;
		width: 100%; 
	} 
}

関連記事