SC(非公式)Advent Calendar 2017 の12日目です。
普段サーバーサイドでC#を書いたり、SQLを書いたり、AzureのPOCとかをしています。
#はじめに
サーバーサイドエンジニアってデザイナさんが作ったHTML/CSSにロジックを足していくパターンが多いと思います。
.Netとかだと.Net MVCの場合はRazorなんかを使ってViewの表示を切り替えたりすると思います。
が、CSS3(CSS)を使用していると初見殺しのシンタックスが結構あるので、知っとくと便利なCSSを紹介したいと思います。
##レイアウト
下手にいじっちゃうと大惨事になるレイアウト周り。
サーバーサイドの人からすると、レイアウト関連のdivタグの使い方って神ですよね。
けど、ひと昔前までは職人(神)技だったけど、今はそれに近いことが、割と簡単にできるようになってきた(かも。。。)
###レイアウトサンプル
業務アプリでよく見るこんな感じのレイアウト
###Flex Box display: flex
Can I Use
主要ブラウザだと、IE11だけベンダープレフィックスを付ける必要があります。それ以外の主要ブラウザではサポートされています。
きっと普段みなさんが日常的にみているサイトのほとんどはFlexBoxを使用していると思います。
Flex BoxはFlexコンテナーという親要素とFlexアイテムで構成されます。
Flexコンテナーで囲った領域内のアイテムを縦に並べるのか、横に並べるのか、右からか、左からか、といったことを決めていきます。
.container {
display: flex;
flex-direction: column;
}
.item {
flex: 0 1 auto;
}
flex-direction: column;
はアイテムを縦に
flex-direction: row;
はアイテムを横(デフォルト左から右)に並べます。
flex: 0 1 auto;
はflex-grow:0
、flex-shrink:1
、flex-basis:auto
のショートハンド
さらに、Flexアイテム自体をFlexコンテナとして指定ができる。
.container {
display: flex;
flex-direction: column;
}
.item {
display: flex;
flex-direction: row;
flex: 0 1 auto;
}
.side-menu {
width: 30%;
flex: 0 1 auto;
}
.main {
width: 70%;
flex: 0 1 auto;
}
.container {
display: flex;
flex-direction: column;
}
.item {
display: flex;
flex-direction: row;
flex: 0 1 auto;
}
.side-menu {
width: 30%;
flex: 0 1 auto;
}
.main {
display: flex;
width: 70%;
flex: 0 1 auto;
}
.search-area {
height: 150px;
flex: 0 1 auto;
}
.grid {
height: 350px;
flex: 0 1 auto;
}
こんな感じで**Flexコンテナ(display:flex)とFlexアイテム(flex:~)**をネストしてレイアウトを作っていきます。float: left
みたいに、下に滑ることもないし、今は中身のコンテンツがないので、便宜上width
やheight
を指定していますが、コンテンツがあれば、width
やheight
指定なしでレイアウトを組むことができます。カッコいい
###Grid Layout
個人的にイチ押しのCSS Grid Layoutです。
Can I Use
Edgeもベンダープレフィックスなしで使えるようになりました。IE11は相変わらずです。
float: left
でレイアウトを作っていく場合もdisplay: flex
で作っていく場合も、並べたいdiv
要素に対して、親要素でくくる必要がありましたが、GridLayoutは必要ありません。直観的(というかTableレイアウト的?)です。
とは言えContainerは必要です。
display:grid
でContainerを定義して、grid-template-columns
とgrid-template-rows
で列と行の境界を指定していきます。
まずはdisplay:grid
を指定してContainerを作ります。
<body>
<div class="container">
<div class="header"></div>
<div class="side-menu"></div>
<div class="search"></div>
<div class="grid"></div>
</div>
</body>
grid-template-columns:~
で列の数・幅を
grid-template-rows:~
で行の数・幅を決めていきます。
.container {
display: grid;
grid-template-columns: 180px 1fr;
grid-template-rows: 70px 70px 400px;
background-color: #ddd
}
.header {
grid-column: 1/3;
grid-row: 1;
border: 1px solid blue;
}
.side-menu {
grid-column: 1;
grid-row: 2/4;
border: 1px solid orange;
}
.search {
grid-column: 2;
grid-row: 2/3;
border: 1px solid red;
}
.grid {
grid-column: 2;
grid-row: 3/4;
border: 1px solid red;
}
はい、これだけ。
HTMLを見ていただけるとわかりますが、余計なネストがないのがわかると思います。
なれるまでは、Gridテンプレートの指定の方法がいろいろあるので、苦戦するかもしれませんが、IE10以下の要件がなければ、かなり楽ができそうです。
React.jsやVue.jsのようなコンポーネントを配置する考え方と非常に相性がいいです。
ただ、Gridテンプレートの境界を超えるようなアニメーションとかは難しいです。
##Tips編
よくあるレイアウト修正のTipsの紹介
###line-height
よく見るけど、正確に仕様を把握している人が少なそうなline-height
です。
line-height
は行の高さを決めるプロパティですね。
基本的にはfont-size
プロパティの大きさに対する比率で行の高さが決まります。
line-height: 1
line-height: 16em
line-height: 100%
のように色々な単位で指定できますが、子、孫のフォントサイズに対して、親要素のline-height
が継承されてしまうため、単位をつけない方がいいとされています。
個人的には、超重要な属性だと思っていて、例えばよくある検索条件レイアウトで、ラベル、テキストボックス、ドロップダウンが並んでいる場合。
#####chrome
#####IE11
#####FireFox
<div class="container">
<div class="item">
<label for="name">名前:</label>
</div>
<div class="item">
<input type="text"></input>
</div>
<div class="item">
<select name="aaa" id="">
<option value="1">月曜</option>
<option value="2">火曜</option>
・・・
</select>
</div>
</div>
.container {
display: flex;
}
.item {
flex: 0 1 auto;
}
すごく細かいですが、テキストボックスとドロップダウンの高さとか、Topの位置が違うのがわかると思います。
FlexBoxにはFlexアイテムを縦方向で中央寄せにするalign-items: center
プロパティがあるので、指定してみます。
#####chrome
#####IE11
#####FireFox
.container {
display: flex;
align-items: center;
}
.item {
flex: 0 1 auto;
}
FireFoxはいい感じになりました。
が、ブラウザ間で差異が出るので、marrgin-top:○px
とかやりたくないですよね。
ここで、line-height
の登場です。
.container {
display: flex;
align-items: center;
line-height: 1;
}
.item {
flex: 0 1 auto;
}
親要素である、.container
クラスにline-height: 1
を追加してみます。
#####chrome
#####IE11
#####FireFox
『ダイブいい感じー』になりました。
これは、ブラウザのuser-agent間の差異が原因で、reset.cssとか使ってればいいんですが、reset.cssでもほとんどのタグはvertical-align:baseline;
に設定されていることが多いので、縦方向がうまくそろわないことがあります。
vertical-align
、margin
、padding
あたりをいじりたくなる気持ちもわかりますが、line-height
を試してみてください。
###text-overflow
text-overflow
は指定した幅を超えてテキストが表示されるときに「・・・(3点リーダー)」に変換してくれるプロパティです。
設計段階ではわからなかったけど、データをバインドしたら、予想以上にデータが長い。そういう時にgridの列幅を可変にする仕様追加や、ロジックで何文字以下とするのは愚かな選択です。その分テストの工数が増えるし、CSSで解決できることはCSSに任せちゃいましょう。(まぁデータの種類にもよりますが・・・)
.text-overflow {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
#最後に
SPA(シングルページアプリケーション)の時代ですね。
サーバーサイドの役割も変わってきています。
MVCやMVVMが古いわけじゃないけど、ユーザーがもとめているものをより早くデリバリできる柔軟さが求められてきていると思います。
CSSやjavascriptで解決できるものはそちらに任せた方がいいものもあります。
ブラウザからDBまで、処理の重さや頻度、通信の速度、保守性、拡張性を加味して、最適なソリューションを実践していきたいです。
個人的には、プロジェクトでケースバイケースでClient/Server間の役割分担を決めていけばいいと思っていますが、最近は選択肢が多いのが逆に悩みのタネです。