#概要
今までCSSを書いていて、メディアクエリで思惑通りスタイルが反映されないことが多々あり、まあ仕様なのだろうと軽く流して!important
を付け足していましたが、根本的にメディアクエリを誤解していました。
CSSをそこそこ書いている人は理解されていると思います。
以下の内容は自分で色々テストして推測したメディアクエリの挙動なので、厳密には間違っているかもしれません。仕様というより、コーティングするときの考え方程度に捉えてください。
#今までの間違った考え方
例えば以下のように書いた場合↓
p {
size: 16px;
color: red; /* 赤色にする */
}
@media(min-width: 500px){ /* 画面サイズが500px以上の時は... */
p {
color: yellow; /* 黄色にする */
}
}
500px未満のとき↓
p {
size: 16px;
color: red; /* 赤色にする */
}
p {
color: yellow; /* 黄色にする */
}
500px以上のとき↓
p {
size: 16px;
color: red; /* 赤色にする */
}
こんな風に考えていました。
しかし、そんなに単純ではなかった。。。
#本当の考え方
メディアクエリは、二つのステップを踏むと考えてください。
- メディアクエリで指定されたセレクタと**"セレクタが同一"**のプロパティの書き換え
- 書き換えたプロパティの優先度を下げる
セレクタとプロパティとは、こいつらです。↓
(サルワカより引用)
###ステップ1 - プロパティの書き換え
例として以下のようなCSSがあるとします。
今までの私は、これをみて「文字は黄色になる」と考えていたわけです。
body p {
color: blue; /* 青色にする */
}
p {
size: 16px;
color: red; /* 赤色にする */
}
@media(min-width: 500px){ /* 画面サイズが500px以上の時は... */
p {
color: yellow; /* 黄色にする */
}
}
まず、メディアクエリは、セレクタ名が同一のセレクタのプロパティを書き換えます。
あくまで対象の要素が一致するセレクタではありません。
ここでp
とbody p
は同じ要素を示していますが、別のセレクタとして扱われます。
(今回はbody p
としているのでp
と対象が必ず一致し違和感がありますが、.header p
とp
が別のセレクタとして扱われることを考えると、当たり前のことですね。)
書き換えると以下の通りです。
body p {
color: blue; /* 青色にする */
}
p {
size: 16px;
color: yellow; /* 黄色にする */
}
(body p
とbody > p
は同じものとして扱われるようです。)
###ステップ2 - 優先度を下げる
上述した例文を実行してみれば分かりますが、文字は青色になります。
つまり、メディアクエリを除いたスタイルの中でも、body p
の方が優先度が低いにも関わらず、適用されてしまっているわけです。
書き換えると、以下のように処理されます。
p {
size: 16px;
color: yellow; /* 黄色にする */
}
body p {
color: blue; /* 青色にする */
}
#解決方法
###1. !important
をつける
あまり推奨される方法ではないですが、メディアクエリ内に限定して使用すれば、それほどソースコードが荒れることは無いと思います。それに、とても簡単です。
/* 黄色になる */
body p {
color: blue; /* 青色にする */
}
p {
size: 16px;
color: red; /* 赤色にする */
}
@media(min-width: 500px){ /* 画面サイズが500px以上の時は... */
p {
color: yellow !important; /* 黄色にする */
}
}
###2. 最初から気をつける
セレクタに無駄なものをつけないようにしましょう。この記事で言いたいことはこれに尽きます。
.header p{}
で指定可能なものを、.header .menu p{}
のように無駄なものをつけないようにすることで、可読性も上がります。