React Native
でライブラリを使っていて style
の上書きがうまくできないことがあります。配列によるスタイル指定が機能しなかったり。
今回は margin
の上書きが出来なかったことから色々試してみたという内容です。
バニラで書いてると気づきやすいですが、フレームワーク+ライブラリの状態だとハマりやすいので気を付けましょう。
効かないスタイル変更の原因
今回の対象は react-native-elements の ButtonGroup です。
こんな感じで margin:0
の普通のボタングループを作成します。
1 2 3 4 5 6 7 8 9 10 |
<ButtonGroup onPress={onPress} selectedIndex={idx} buttons={buttons} containerStyle={{ margin:0, }} textStyle={{ fontSize: 16, textAlign: "center" }} selectedButtonStyle={styles.selected} /> |
親View
にくっつく形のボタングループにしたかったのですが、マージンが残ります、
padding, border, width
などいじりまわすも、やはりmargin
の問題でした。
ソースを見ると、該当箇所はこう。
1 2 3 4 5 6 7 8 |
<View {...attributes} style={StyleSheet.flatten([ styles.container, vertical && styles.verticalContainer, containerStyle && containerStyle, ])} > |
styles.container
はこうなってます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
const styles = { ... , container: { marginHorizontal: 10, marginVertical: 5, borderColor: '#e3e3e3', borderWidth: 1, flexDirection: 'row', borderRadius: 3, overflow: 'hidden', backgroundColor: '#fff', height: 40, }, ... } |
通常のCSS
だと margin-top
の後ろに margin
を指定すると上書きできますが、このmarginHorizontal
やmarginVertical
は上書きできませんでした。
とりあえず対処方法は簡単です。問題のスタイルを0にします。
1 2 3 4 5 6 7 8 9 10 11 |
<ButtonGroup onPress={onPress} selectedIndex={idx} buttons={buttons} containerStyle={{ marginHorizontal: 0, marginVertical: 0, }} textStyle={{ fontSize: 16, textAlign: "center" }} selectedButtonStyle={styles.selected} /> |
borderTop
だけ残して色々いじるとこういう感じになります。
下の4つがボタングループでタブ化したメニューになります。
marginの上書きについて
なんで上書きできないのかもう少し掘り下げてみましょう。
単純な正方形のView
を2つ作ってスタイルがどう上書きされるか見ます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
import React from "react"; import { StyleSheet, View } from "react-native"; export default function App() { return ( <View style={styles.container}> <View style={styles.s1}> <View style={[styles.s2, styles.margin3]} /> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, s1: { width: 100, height: 100, backgroundColor: "red" }, s2: { width: 20, height: 20, backgroundColor: "green" }, margin1: { margin: 10, marginHorizontal: 50, }, //marginHorizontal > margin margin1b: { marginHorizontal: 50, margin: 10, }, // = 1 margin2: { marginLeft: 5, marginHorizontal: 50, margin: 10, }, //marginLeft > marginHorizontal > margin margin2b: { marginHorizontal: 50, marginLeft: 5, margin: 10, }, // = 2 margin2c: { marginHorizontal: 50, margin: 10, marginLeft: 5, }, // = 2 margin3: { marginStart: 10, marginEnd: 10, marginLeft: 20, marginRight: 20, marginTop: 20, marginBottom: 20, marginHorizontal: 50, marginVertical: 50, margin: 100, }, }); |
こんな感じの優先順位があって後ろに書くだけでは上書きできないです。
左:marginStart > marginLeft > marginHorizontal > margin
下:marginBottom > marginHorizontal > margin
より細かい指定方法が上位(かつStart, End > Left, Right
)のようです。
これは padding
も同様でした。
ちゃんと上書きするために
面倒ですがライブラリの実装を見て同じプロパティを上書きするのが一番良いと思いますが普通に面倒くさいです。
margin
や padding
は string
指定ができるので、複数指定や !important
など出来ないかと試行錯誤してみたけど良い方法は見つからなかった。
とりあえずの処置なら最も強い要素で上書きするのが簡単です。
1 2 3 4 5 6 7 8 9 10 11 12 |
const styles = StyleSheet.create({ reset: { marginStart: 0, marginEnd: 0, marginTop: 0, marginBottom: 0, paddingStart: 0, paddingEnd: 0, paddingTop: 0, paddingBottom: 0, }, }); |