CSS tips - Flexbox でネイティブっぽいリストアイテムを作る方法
最近, 仕事で CSS を使ってスマホの UI を再現してくれーという要望が多いので, その中でも中心となる リストアイテムのスタイリングについて備忘録がてらまとめました.
Flexbox を上手く使うことでシンプルなものからアイコン付きや, 2カラム, 3カラムになってもキレイに配置されるようにスタイリングすることができます.
デモはすべて Runstant で作ってあるので, fork して色を変えたり要素を増やしたりして遊んでみてください.
※ CSS には Less を使っています. 変換後の状態が見たい場合は下記のツールをお使いください.
『リアルタイムで LESS から CSS に変換する Web ツール作りました! | phiary』
シンプルなリストアイテム
border-top は全ての要素に, border-bottom は最後の要素のみ表示するようにすることで区切り線を表現しています. flex 系の指定は以降への布石です.
HTML
<div class='list'>
<a class='item', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
<a class='item', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
<a class='item pad', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
<a class='item pad', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
</div>
CSS(LESS)
.item {
text-decoration: none;
color: #444;
padding: 0.5rem;
background-color: white;
display: flex;
align-items: flex-start;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
&:hover {
background-color: #fafafa;
}
&.pad {
padding: 1rem;
}
}
複数行に対応したリストアイテム
やっていることは, タイトルを強調しているぐらいですね.
HTML
<div class='list'>
<a class='item', href=''>
<div class='content'>
<div class='header'>
<div class='title'>Daniel</div>
</div>
<div>Hi, how are you? Glad to hear you are interested in our project.</div>
</div>
</a>
<a class='item', href=''>
<div class='content'>
<div class='header'>
<div class='title'>John</div>
</div>
<div>I am a teacher at a elementary school.</div>
</div>
</a>
</div>
CSS(LESS)
.item {
text-decoration: none;
color: #444;
padding: 0.5rem;
background-color: white;
display: flex;
align-items: flex-start;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
&:hover {
background-color: #fafafa;
}
&.pad {
padding: 1rem;
}
.content {
flex: 1;
.header {
display: flex;
align-items: center;
margin-bottom: 0.1rem;
.title {
flex: auto;
color: hsl(220, 80%, 50%);
font-weight: bold;
}
}
}
}
時間表示にも対応したリストアイテム
align-items: center
を指定することでタイトルと時間の縦軸がキレイにならぶよう調整しています.
また, title のみ flex: auto
を指定することで画面サイズに応じて幅が広がるようになっています.
HTML
<div class='list'>
<a class='item', href=''>
<div class='content'>
<div class='header'>
<div class='title'>Daniel</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>Hi, how are you? Glad to hear you are interested in our project.</div>
</div>
</a>
<a class='item', href=''>
<div class='content'>
<div class='header'>
<div class='title'>John</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>I am a teacher at a elementary school.</div>
</div>
</a>
</div>
CSS(LESS)
.item {
text-decoration: none;
color: #444;
padding: 0.5rem;
background-color: white;
display: flex;
align-items: flex-start;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
&:hover {
background-color: #fafafa;
}
&.pad {
padding: 1rem;
}
.content {
flex: 1;
.header {
display: flex;
align-items: center;
margin-bottom: 0.1rem;
.title {
flex: auto;
color: hsl(220, 80%, 50%);
font-weight: bold;
}
.time {
text-align: right;
color: #888;
font-size: 0.6rem;
}
}
}
}
アイコン画像付きリストアイテム
最初に指定した display:felx
が活きてきます.
この指定による横並びになり, .content
のほうには flex: 1
, .icon
のほうは width を固定サイズにそれぞれ指定することで, 画面サイズが変わっても .content
の方のみ伸縮するようにしています.
またアイコンを円形にするスタイリングを .circle
クラスとして外出しすることで HTML 側で
使い分けることができるようになっています.
HTML
<div class='list'>
<a class='item', href=''>
<div class='icon'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>Daniel</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>Hi, how are you? Glad to hear you are interested in our project.</div>
</div>
</a>
<a class='item', href=''>
<div class='icon circle'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>John</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>I am a teacher at a elementary school.</div>
</div>
</a>
</div>
CSS(LESS)
.item {
text-decoration: none;
color: #444;
padding: 0.5rem;
background-color: white;
display: flex;
align-items: flex-start;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
&:hover {
background-color: #fafafa;
}
&.pad {
padding: 1rem;
}
.content {
flex: 1;
.header {
display: flex;
align-items: center;
margin-bottom: 0.1rem;
.title {
flex: auto;
color: hsl(220, 80%, 50%);
font-weight: bold;
}
.time {
text-align: right;
color: #888;
font-size: 0.6rem;
}
}
}
.icon {
width: 30px;
height: 30px;
margin-right: 0.5rem;
border: 1px solid rgba(0, 0, 0, 0.1);
&.circle {
border-radius: 50%;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
}
}
}
カードタイプのリストアイテム
margin を指定して, border
や box-sizing
を調整してあげるだけで
Material Design の Cards のような表現ができます.
これも .card
というクラスとして外出ししておくことで HTML 側で切り替えることができるようにしています.
HTML
<div class='list'>
<a class='item card', href=''>
<div class='icon'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>Daniel</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>Hi, how are you? Glad to hear you are interested in our project.</div>
</div>
</a>
<a class='item card', href=''>
<div class='icon circle'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>John</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div>I am a teacher at a elementary school.</div>
</div>
</a>
</div>
CSS(LESS)
.item {
text-decoration: none;
color: #444;
padding: 0.5rem;
background-color: white;
display: flex;
align-items: flex-start;
justify-content: space-between;
border-top: 1px solid rgba(0, 0, 0, 0.1);
&:last-child {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
&:hover {
background-color: #fafafa;
}
&.pad {
padding: 1rem;
}
&.card {
margin: 0.5rem;
border: none;
border-radius: 4px;
box-shadow: 1px 1px 2px 0px #aaa;
}
.content {
flex: 1;
.header {
display: flex;
align-items: center;
margin-bottom: 0.1rem;
.title {
flex: auto;
color: hsl(220, 80%, 50%);
font-weight: bold;
}
.time {
text-align: right;
color: #888;
font-size: 0.6rem;
}
}
}
.icon {
width: 30px;
height: 30px;
margin-right: 0.5rem;
border: 1px solid rgba(0, 0, 0, 0.1);
&.circle {
border-radius: 50%;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
}
}
}
様々なタイプのリストアイテム
全部のせです. CSS は, カードタイプのリストアイテム と同じものを使っています.
一部をクラス指定にすることによってオプション化してあるので, 今まで紹介してきたリストアイテムを HTML 側で使い分けることができます.
HTML
<div class='list'>
<a class='item', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
<a class='item pad', href=''>
<div class='content'>
<div>Item</div>
</div>
</a>
<a class='item', href=''>
<div class='content'>
<div class='header'>
<div class='title'>Daniel</div>
</div>
<div class='desc'>Hi, how are you? Glad to hear you are interested in our project.</div>
</div>
</a>
<a class='item', href=''>
<div class='icon circle'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>John</div>
</div>
<div class='desc'>I am a teacher at a elementary school.</div>
</div>
</a>
<a class='item', href=''>
<div class='icon circle'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>Lucy</div>
<div class='time'><time>2016/05/18</time></div>
</div>
<div class='desc'>Hello, nice meeting you.</div>
</div>
</a>
</div>
<div class='list'>
<a class='item card', href=''>
<div class='icon circle'>
<img src='http://phi-jp.github.io/phiary-workspace/assets/images/kenkyo.jpg' />
</div>
<div class='content'>
<div class='header'>
<div class='title'>Elizabeth</div>
</div>
<div class='desc'>Please call me when you're ready.</div>
</div>
</a>
</div>