webのreactと同じノリで書こうとしたら、ネイティブアプリの洗礼を受けた話。
基本、前提
普通にcssで実装するなら、、、
- 横並び→flex-directionのraw
- 折り返し→wrapを設定
- 等間隔→space-around、space-between、もしくはgap
この辺を使えばよさそうです。
space-around、space-betweenの問題
wrapした時に行ごとに等間隔にしてしまって不恰好になる。
例えば5個の要素があって、1行に3つごとおきたい場合、
.list-wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.list-item {
width: 30%;
}
などとすると3個の行と2個の行に分かれる。
その時3個は等間隔になるが、2個はその2個で等間隔になるので、5個の間隔がバラバラになってしまう。
(この場合1行目は間隔5%だけど、2列目は30%空いてしまう)
結論:wrapと組み合わせるならspace-around、space-betweenは使わない方がいい。
解決1(失敗)
gapを使おう
https://developer.mozilla.org/ja/docs/Web/CSS/gap
.list-wrapper {
gap: 1em;
gap: 10px 20px; // 縦 横
}
のようにすると自動的に間隔を付けてくれる。
(もちろん端にはつけず、要素の間だけつけてくれる)
react nativeでgap使えない問題
やってみたらエラーでてどうやら使えないものだということを悟った、、、
解決2(失敗)
widthとmarginだけで解決しよう
例えば3分割したいなら、
30% 5% 30% 5% 30%で分ければ良いので
.list-item {
width: 30%;
&:not(:nth-child(3n)) {
margin-right: 5%;
}
}
という実装ができる。
react nativeでnth-child使えない問題
何とこっちも使えない。
エラーが出るのではなく、単純にnth-child部分が無視された表示になった。
どうやらnth-childのみならず、last-childとかも含めて使えないらしい。
ということでそれにあたるロジックを自分で書く必要があった。
解決3(成功)
今回はstyled-componentsでの実装。
ロジックはcss内に書くこともできるのかもしれないが、なんか上手くいかなかったのでjsx/tsx内で解決した。
方針としては解決2と似ていて、nth-childの代わりにmap時のkeyに使われるidxを使って分岐させる処理を書く。
まずはnth-childしたかったcomponentにmarginRightというpropsを追加。
{datas.map((data, idx) => {
return (
<YourStyledComponent marginRight={idx % 3 === 2 ? '0%' : '5%'}>
</YourStyledComponent>
)
})}
と三項演算子で分岐処理を実装。
idxは0スタートなので、こうすることで3n番目の要素のみmarginRightを0にできる。
これをstyled componentで受け取る。
const YourStyledComponent = styled.View<{marginRight: string}>`
width: 30%
margin-right: ${({marginRight}): string => marginRight}
`
これでいけました。