CSSスタイリングのコツ【レイアウト編】
はじめに
良いデザインにはルールがある
この本↓、絶対読んだ方がいいです。
良いデザインにはルールがあって、それに従うだけで作るアプリの見た目が劇的に変わっちゃいます。
僕はこの本を読んで感動しました。
で、そのデザインのルールを知ってると、おのずとCSSスタイリングの方法も見えてくるってことです。
なので、まずはこの本を読んでからこの記事を読んでくださいね。
...ってお忙しい皆さんが読んでくださるわけもないので、必要な部分だけ抜粋します。
意識すべきデザインのルール:整列
CSSスタイリングにおいてもっとも意識すべきデザインのルールは整列です。
Bad Example
Good Example
良いデザインでは、線が意識されて配置されています。
中央ぞろえは中央に線がありますが、テキストの左右がそろっていないので、整列が弱いです。
対して左揃えや右揃えであれば、強い透明な線が見えるようになります。
(中央ぞろえで整列を意識させる方法もありますが、それは本にお預けといたします)
CSSスタイリングのコツ
で、デザインのルールが分かれば、あとはFlexboxで簡単に作れます。
Flexboxは子要素を簡単に縦/横に並べる(整列させる)ことができます。
つまり、良いデザインは要素が整列されているはずなので、Flexboxで簡単にCSSに起こせるというわけです。
↓Flexboxのプロパティ
.parent-element {
display: flex;
flex-direction: row | column | row-reverse | column-reverse;
flex-wrap: nowrap | wrap;
align-content: normal | center | flex-start | flex-end | space-between | space-around | strech;
justify-content: normal | center | flex-start | flex-end | space-between | space-around | space-evenly;
align-items: normal | center | flex-start | flex-end | strech | baseline;
}
ちなみにReactのMaterial UI(@mui/material)ではStackを使うことで同じことができます。
<Stack direction="row" justifyContent="space-around" alignItems="center">
<Child />
<Child />
</Stack>
スタイリング例
スタイリング例にするデザイン
こちらを例に、実際にスタイリングしてみましょう。
なお、レイアウトに関係しないプロパティは書いてないものもあります。
ステップ1:線を引いて構造化する
構造化したデザイン
今回の場合はこんな感じに引きました。
ステップ2:外側からHTMLとCSSを書いていく
実際にHTMLとCSSを書いていきます。
分かりやすいようにインラインスタイルで書きます。
オレンジの部分まで
<div
style="
height: 100vh;
width: 100vw;
background-image: url(bg.png);
background-size: cover;
/* 以下Flexboxのプロパティ */
display: flex;
justify-content: center; /* 左右方向=中央揃え */
align-items: center; /* 上下方向=中央揃え */
"
>
<div style="height: 1400px; width: 788px; backdrop-filter: blur(20px)"></div>
</div>
Flexboxを使って中央に配置しています。
オレンジから黄緑まで
<div
style="
height: 1400px;
width: 788px;
backdrop-filter: blur(20px);
/* 以下Flexboxのプロパティ */
display: flex; /* 横並び */
justify-content: space-around; /* 左右方向=余白を入れる */
align-items: center; /* 上下方向=中央揃え */
"
>
<div>
Ryota Sasaki
Keio University Student Software Engineer
<img src="github.svg" alt="GitHub" />
<img src="wantedly.svg" alt="Wantedly" />
</div>
<div>
About Me
Skills
History
Portfolio Ver. 2
Portfolio Ver. 3
</div>
</div>
Flexboxを使って横並びで、外側の左右の余白が中央の半分(space-around
)になるように設定しています。
DevToolsの画像
左の黄緑の中
<div
style="
/* 以下Flexboxのプロパティ */
display: flex;
flex-direction: column; /* 縦並び、左右方向=左揃え */
/* なお子要素のFlexboxはコメントを省略 */
"
>
<div style="height: 120px; display: flex; align-items: flex-end">
<div style="font-size: 80px">Ryota Sasaki</div>
</div>
<div>Keio University Student Software Engineer</div>
<div style="height: 120px">
<div style="height: 35px; display: flex">
<img src="github.svg" alt="GitHub" style="height: 100%" />
<img src="wantedly.svg" alt="Wantedly" style="height: 100%" />
</div>
</div>
</div>
Flexboxを使って縦並び、左揃えに配置しています。
ここで、ちょっとトリッキーなんですが、真ん中のKeio University Student Software Enginner
を縦方向の真ん中に持ってくるために、その上と下の要素をheight: 120px
(flex-basis: 120px
でもよし)で固定しています。
オレンジにalign-items: center
が効いているので、上と下で均等な大きさの要素に挟まれている要素は真ん中に来ます。
さらに、Ryota Sasaki
がflex-basis: 120px
の上に張り付いて浮かないようにFlexboxのalign-items: flex-end
で下に下げています(bottom: 0
のような効果)。
下のimgを囲むFlexboxは横並び用です。
DevToolsの画像
右の黄緑の中
<div
style="
width: 300px;
height: 400px;
/* 以下Flexboxのプロパティ */
display: flex;
flex-direction: column; /* 縦並び、左右方向=左揃え */
justify-content: space-evenly; /* 上下方向=余白を入れる */
"
>
<div style="border-top: 1px solid #fff; border-bottom: 1px solid #fff">About Me</div>
<div style="border-bottom: 1px solid #fff">Skills</div>
<div style="border-bottom: 1px solid #fff">History</div>
<div style="border-bottom: 1px solid #fff">Portfolio Ver. 2</div>
<div style="border-bottom: 1px solid #fff">Portfolio Ver. 3</div>
</div>
Flexboxには子要素のflex-directionに垂直な方向の長さ(幅)をそろえる効果があります。
Flexboxにすることで、中のdivの幅、ひいてはそのボーダーの長さをそろえています。
DevToolsの画像
ステップ3:微妙なずれを直す
特にテキストは、フォントや文字によって左端がずれています。
なので、実際の画面を見ながら、marginを入れるなどして、きちんと"整列"するようにずらしましょう。
今回の例では<div>Ryota Sasaki</div>
にmargin-left: -6px
を設定しました。
全体像
<div
style="
height: 100vh;
width: 100vw;
background-image: url(bg.png);
background-size: cover;
/* 以下Flexboxのプロパティ */
display: flex;
justify-content: center; /* 左右方向=中央揃え */
align-items: center; /* 上下方向=中央揃え */
"
>
<div
style="
height: 1400px;
width: 788px;
backdrop-filter: blur(20px);
/* 以下Flexboxのプロパティ */
display: flex; /* 横並び */
justify-content: space-around; /* 左右方向=余白を入れる */
align-items: center; /* 上下方向=中央揃え */
"
>
<div
style="
/* 以下Flexboxのプロパティ */
display: flex;
flex-direction: column; /* 縦並び、左右方向=左揃え */
/* なお子要素のFlexboxはコメントを省略 */
"
>
<div style="height: 120px; display: flex; align-items: flex-end">
<div style="font-size: 80px; margin-left: -6px">Ryota Sasaki</div>
</div>
<div>Keio University Student Software Engineer</div>
<div style="height: 120px">
<img src="github.svg" alt="GitHub" />
<img src="wantedly.svg" alt="Wantedly" />
</div>
</div>
<div
style="
width: 300px;
height: 400px;
/* 以下Flexboxのプロパティ */
display: flex;
flex-direction: column; /* 縦並び、左右方向=左揃え */
justify-content: space-evenly; /* 上下方向=余白を入れる */
"
>
<div style="border-top: 1px solid #fff; border-bottom: 1px solid #fff">About Me</div>
<div style="border-bottom: 1px solid #fff">Skills</div>
<div style="border-bottom: 1px solid #fff">History</div>
<div style="border-bottom: 1px solid #fff">Portfolio Ver. 2</div>
<div style="border-bottom: 1px solid #fff">Portfolio Ver. 3</div>
</div>
</div>
</div>
Material UIのStackについて
ちなみにこの例↑はもともとReactのMaterial UI(@mui/material)で作ったものをHTML化して書いてます。
Material UIでは、Flexboxは<Stack />
で書けて、通常のdiv要素としての<Box />
と使い分けができるので、縦並び、横並び用のBoxは全部<Stack />
を使うことで可読性が上がります。
そういうわけで、レイアウト関連は基本<Stack />
で書いてたので、左の黄緑の外側のdivはFlexboxにする必要がないことに今気づきました(display: block
でも縦並びにはなる)。
が、このまま残しておきます。
Flexboxのデメリット
Flexboxを多用しててデメリット無いの?って、僕も前疑問だったのですが、今の自分が思うFlexboxのデメリットとしては以下の点があるかと思います。
高さや幅が自動で指定されていくゆえに、思い通りのレイアウトにならなかったときの修正が難しい
Flexboxで楽にレイアウトできるのはいいものの、思い通りにレイアウトされなかったときの修正にはコツがいります。
ちょっと例は示せないのですが、たまに高さや幅の指定が自動ではうまくいかないことがあります。
そういう場合は手動で高さや幅を指定してあげればいいんですが、せっかくFlexbox使ってるのに手動で指定するのはナンセンスだなと自動指定がうまくいくように色々試しだすと時間がかかります。
まあ、うまくいかないスタイリングを治すのに時間がかかるのはFlexboxに限った話ではありませんし、Flexbox以外を使っても結局手動指定が必要なので、Flexboxのデメリットというより、Flexboxの注意点って感じです。
transitionプロパティによるアニメーションに向いてない
transitionプロパティでアニメーションをつけるとき、開始値と終了値をauto
などではなく、固定値で決めないといけないですよね。
しかし、Flexboxは自動で決まっている値が多いので、一旦Flexboxで作って、あとでアニメーションをつけたくなった、ってときにspace-betweenをmarginに書き直したり、positionを決めたり、今までFlexboxで楽してたレイアウトを普通のプロパティでかけるように考え直さないといけないのは地味に面倒くさいです。
まあ、Flexboxがなかったら最初から面倒くさい普通のプロパティで書かないといけないので、これもFlexboxのデメリットというより、Flexboxの注意点って感じです。
おわりに
こんなん書きましたが、自己流なので、もっと良い方法があるよって方はコメント欄で教えていただければと思います。
Discussion