Flexboxの最新テクニック! メディアクエリはなし、同じCSSで4つの異なるレイアウトに対応したフォームを実装
Post on:2022年1月26日
sponsorsr
メディアクエリはなし、同じHTMLとCSSで、親コンテナの幅に応じて4つの異なるレイアウトに対応したフォームを実装するFlexboxの最新テクニックを紹介します。
もちろんコンテナクエリもなしです。
同じコードでフォームをどこにでも配置でき、コンテンツでもサイドバーでもフォームは最適にレイアウトされます。Flexboxの最新のテクニックを使用すると、CSSで明示的に定義しなくても、レイアウトの柔軟性を得られます。

まずは、実際の動作をデモページでご覧ください。
サイズを変更して見るには、右上「Edit on CodePen」をクリックして別タブでご覧ください。
See the Pen
Flexbox Responsive Form by Adam Argyle (@argyleink)
on CodePen.
ラベルが付いているデモページはこちら。
See the Pen
Flexbox Responsive Form (now with labels for a11y) by Angelique (@angeliquejw)
on CodePen.
フォームのHTMLは、非常にシンプルです。
|
1 2 3 4 5 |
<form> <input type="text" placeholder="Name"> <input type="email" placeholder="Email Address"> <input type="submit" value="Subscribe"> </form> |
4つの異なるレイアウトを実装するCSSです。他のスタイルは省略しました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
form { display: flex; flex-wrap: wrap; & > input { flex: 1 1 10ch; margin: .5rem; &[type="email"] { flex: 3 1 30ch; } } } |
CSSにすると、こんな感じです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
form { display: flex; flex-wrap: wrap; } form > input { flex: 1 1 10ch; margin: .5rem; } form > input[type="email"] { flex: 3 1 30ch; } |
CSSの仕組みを簡単に説明します。
ラッパーのformには、display: flex;が定義されており、すべてのflexアイテムが水平の1行に収まるように設定されています。flex-wrap: wrap;を加えることで、1行に収まらない場合に行を折り返すように設定されています。
これにより、3つのinput要素が、1行・2行・3行に配置されます。
次に、3つのinput要素のCSSを見てましょう。
3つのinputにflex: 1 1 10ch;、e-mailにflex: 3 1 30ch;が定義されており、これがこの実装の最大のポイントです。
flexは、flex-growとflex-shrinkとflex-basisのショートハンドです。
flex-grow: 1;は、全てのflexアイテムは同じサイズになります。flex-shrink: 1;は、flexアイテムが残りのアイテムと比較してどのくらい縮まるかです。flex-basis: 10ch;は、flexアイテムを10chに指定し、残りは最初の大きさに従います。1ch単位はフォントの「0」文字の幅に相当します。
参考: flexプロパティ(伸長係数・縮小係数・初期サイズを定義)
3つのinput要素の初期サイズはflex-basisの値、10ch, 30ch, 10ch になり、合計値は 50ch になります。配置するスペースが50ch以上の場合(アイテムがスペースに収まる場合)は、1行に配置されます。

1番目のレイアウト
各input要素の幅はflex-growの比率になります。submitの幅がtextより小さいのは、textとsubmitのflex値は同じですが、ボタンタイプの要素はコンテンツのサイズがわずかに異なるため、通常の入力フィールドよりも小さくなります。
この3つのinput要素を1行に配置するスペースが十分ではない場合は、行に折り返されます。3つすべてにflex-grow: 1;が定義されており、他の要素と行を共有しないため、3つすべてが行の幅全体に拡大します。margin: .5rem;があるため、全幅より少し小さいです。

4番目のレイアウト
幅を少し広くします。
textとe-mailの2つを1行に配置するスペースが十分でない場合、e-mailが行に折り返されます。textとsubmitのflex値は同じですが、ボタンタイプの要素はコンテンツのサイズがわずかに異なるため、通常の入力フィールドよりもわずかに小さくなります。そのため、e-mailとsubmitは1行に収まります。これで、2行になりました。textの幅はflex-grow: 1;で行の幅全体に拡大され、e-mailの幅はflex-grow: 3;の比率で拡大されます。

3番目のレイアウト
幅をさらに少し広くします。
textとe-mailの2つを1行に配置するスペースが十分な場合、submitが行に折り返されます。textとe-mailの幅はflex-growとflex-basisの比率になり、submitの幅はflex-grow: 1;で行の幅全体に拡大されます。

2番目のレイアウト
元ネタは、下記ツイートからです。
4 layouts for the price of 1, thanks flex 👍
css
form {
display: flex;
flex-wrap: wrap;& > input {
flex: 1 1 10ch;
margin: .5rem;&[type="email"] {
flex: 3 1 30ch;
}
}
}view source on Codepen 👇https://t.co/Q8H5ly2ZIe pic.twitter.com/y6HqxClILZ
— Adam Argyle (@argyleink) January 14, 2020
sponsors











