menu
書いてる野郎
orebike@gmail.com
flex と Grid は同じような並びを制御するためのモノなのでどっちを使えばいいのかと。
flex は主に幅や高さによって流動的にレイアウトを調整したい場合に使い、grid はコンテンツの並びやレイアウトはもう決まっていて変化しないのだがコンテンツ自体の増減に柔軟に対応したい場合に使うといいと思われる。
grid のほうがより計画的に設計して緻密に記述する必要があるので flex のほうが勢いで作るのは楽。
簡単な例だと2カラムの並びを flex で作りたいが左は固定、右は親ブロックいっぱいまで伸ばしたい、 みたいな状況
このようにする
#oya{ display: flex; width: 600px; } #hidari{ width: 200px; flex-shrink: 0; } #migi{ flex-grow: 1; }
flex-shrink
を 0 に指定した場合その対象は flex の幅計算から開放されて width で指定した物になる。
この状態で #migi
の内容物が非常に少ない場合 #hidari
に続いて内容物の幅だけ確保されて並ぶだけになる。ここで flex-grow
に 1 を指定すると親の幅まで拡大されて、200px 400px のブロックが並ぶという結果になる。
これは CSS Grid を頑張れば回避できる問題ではあるのだが。
レスポンシブデザインでこのようなコードをよく書くのではないだろうか
display: flex; flex-wrap: wrap; justify-content: space-around;
これで flex は要素の伸縮はせず余白の伸縮をやってくれるようになり、 余白がなくなると行を折ってくれるという挙動になる。
これにより幅に応じて段組み数を調整できるというレスポンシブになり 広い場合は一覧性がよく狭くなっても細部は潰れないという動きになる。
では space-around 無しの状態で ul に対して li が 8個あった場合。ul が li 4個幅の場合は4個で折れて4と4に分かれる。
li | li | li | li |
li | li | li | li |
では4個幅未満になった場合は、3, 3, 2 に分かれる
li | li | li | |
li | li | li | |
li | li | | |
しかもこの時点で 3個行の右端に約1個分の空間が空いてしまう。2個行には約2個分の空間が空き、 全体としては左寄りにスタイルされいるかのようなアンバランス感がでてしまう。
それを回避したいがために space-around で全体を真ん中にもってきたいのだが今度は2個の行が2個でセンタリングされてしまって3個の行と縦位置が揃わなくなる。これはこれで不格好になる。
そこでこれを解決するには、8個のliのケツにもう1個内容無しのliを足して9個にしてやる。 そうなると 4個幅の時は折れて3行目に行く、
li | li | li | li |
li | li | li | li |
無 | | | |
しかし内容が無いので見えないからOK
3個幅になると、前は2個の行だったのが3個になり333で縦位置が揃う。space-around 指定されているので左右の余白も均等になり左寄り感が解消される。
li | li | li |
li | li | li |
li | li | 無 |
2個幅になっても最終行に存在はするのだが見えないのでOK
li | li |
li | li |
li | li |
li | li |
無 | |
この手法は同様に justify-content: space-between
に対しても機能する。
状況によってはこのダミーを複数入れておく。高さを最小にしておくとよい。
万能な解決策に見えるが、この技は必要な要素が必ず1行分あることが前提になっていて、要素数が1行未満になると空間が空いてしまう。なので幅を絞って1行分の幅を狭めておこう。
対象の要素に
hoge{ width: 100px; flex-shrink: 0; }
とつけると、それが flex の幅調整対象から外れて、その要素が持つ幅で固定される。
flex では余白に余裕が無い場合(且つ折れない場合)要素を縮小してレイアウトを調整しようとする。 その縮小の対象から外せる。
こうすることで、対象は幅固定でその他が伸縮するという動きができる。
天地中央に設置するテクニックは色々あったが、これが決定版という感じなのでこれを使えばいい。
対象のブロック内部に要素が1個しかない状態で↓
#hoge{ display: flex; align-items: center; justify-content: center; }
display: flex
指定した場合その内容物が考慮されて幅が適当に設定されてしまう。
文章満載のブロックと画像1個の要素が並んだ場合縮小できる余地が大きいほうの要素(内容が少ない、余白が多い)が小さくなってしまう可能性がある。
これを避けて幅を同列に扱いたい場合、対象の flex-item 全部に対して flex: 1
を付与すると内容物の考慮がなくなり単純に数だけで幅が調整されるようになる。
横スライドする複数の写真群を提示するモノを作る想定。
flex 指定して子要素のブロック(写真)を横に並べる。 しかし flex の管理下に入るので幅の制御を取られてしまい、単純に親の幅に複数の写真が詰め込まれるという挙動になる。 やりたいのは親に overflow scroll 指定で擬似的なフレームを作り横スライドすることだ。
フレームとなる親は縦横が明示的に指定されている。 そのフレームのデカさに対してぴったり縦横100%の写真を複数持つ
こんな感じ
<ul class="frame"> <li class="photo"><img /></li> <li class="photo"><img /></li> <li class="photo"><img /></li> </ul>
こうなる
ul.frame{ width: 80vw; height: 80vh; display: flex; overflow: scroll; } ul.frame li.photo{ min-width: 100%; } ul.frame li.photo img{ display: block; width: 100%; }
できるはず。