LPのFVのバナーに指定していたwidthが、ブラウザに無効な値として扱われ、適用されていませんでした。原因は、max()の中に書いた0に、単位が付いていなかったことでした。
max()内の0に単位がなくwidthが無効になった
LPのFVに、画面の幅が1440pxを超えたら、広がった分の半分だけ、バナーの幅を足す指定を書いていました。次の1行です。
width: calc(68.51rem + max(0, (100vw - 144rem) / 2));
calc()は、CSSの中で計算をするための書き方です。max()は、並べた値のうち、大きいほうを選びます。remは、文字の基準の大きさ(このサイトでは10px)を1とする単位で、vwは、画面の幅の1%を表す単位です。この指定は、画面が1440px以下のときは68.51remのままで、1440pxより広いときだけ、幅を広げる意図でした。
このwidthは、ブラウザの開発者ツールで、無効な値として扱われていました。
max()内の0に単位がなくてもコンパイルは通る
この確認は、Claude Codeに相談しながら行いました。
SCSSをコンパイルしても、エラーは出ませんでした。手元のDart Sass(Ver:1.105.1)で確認すると、書いたとおりの値が、そのままCSSに出力されました。
.a {
width: calc(68.51rem + max(0, (100vw - 144rem) / 2));
}
コンパイルで気づけないため、ブラウザに読み込ませた後で、値が有効かどうかを確かめる必要がありました。
メディアクエリの単位の書き間違いも、コンパイルは通りました。詳しくは、CSSのメディアクエリが効かない原因は、pxのpが抜けていたに書いています。
CSS.supports()で値が有効かを確かめる
キャッシュが古いのではないかと疑う前に、値そのものが有効かを確かめました。ブラウザのコンソールで使えるCSS.supports()は、ブラウザが、その値を有効なものとして扱うかどうかを、trueかfalseで返します。Chrome で、次のように確認しました。
CSS.supports('width', 'calc(68.51rem + max(0, (100vw - 144rem) / 2))')
// false
CSS.supports('width', 'calc(68.51rem + max(0rem, (100vw - 144rem) / 2))')
// true
単位の有無だけが違う2つの指定で、結果が分かれました。max()の中の0に単位を付けないと、値ごと無効になるということがわかりました。
| 指定 | 結果 |
|---|---|
max(0, 10px) |
false(無効) |
max(0px, 10px) |
true(有効) |
値が無効なwidthはブラウザに読み飛ばされる
無効な値の宣言は、ブラウザが読み飛ばし、エラーは出ません。そのため、widthに何も指定されていないのと同じ状態になり、画面の幅を広げたときの動きが、意図どおりになりませんでした。
直した指定で、画面の幅が1920pxのときのwidthを測ると、925.09pxでした。68.51rem(685.1px)に、広がった分の半分((1920px − 1440px)÷ 2 = 240px)を足した値と、一致しました。
width: calc(68.51rem + max(0rem, (100vw - 144rem) / 2));
CSS.supports()で書き間違いを防ぐ確認
この書き間違いは、コンパイルでも、Stylelintでも、見つかりませんでした。Stylelintは、CSSの書き間違いを見つけるツールです。その中のdeclaration-property-value-no-unknownは、「そのプロパティに、その値を書いてよいか」を調べる検査です。Stylelint(16.26.1)で試すと、width: max(0, 10px)は検出されませんでした。SassとStylelintが見つける書き間違いの違いは、SCSSがコンパイルされない原因は閉じ括弧の漏れと未定義の名前だったに書いています。
そこで、コンパイル後のCSSの中から、ブラウザが「使えない」と判断する書き方を、まとめて探すコードを、Claude Codeに相談して書きました。
コンパイルでもStylelintでも気づけなかった書き間違いが、これで見つかります。仕組みは、CSSに書かれた「プロパティ: 値」を1つずつ、ブラウザのCSS.supports()に渡して、使えるかどうかを確かめるものです。
const css = await (await fetch('/wp-content/themes/hirosenozomi/css/style.css')).text();
const bad = [];
for (const m of css.matchAll(/([a-z-]+)\s*:\s*([^;{}]+);/g)) {
const prop = m[1], value = m[2].trim();
if (prop.startsWith('-') || /-(moz|ms|webkit|o)-/.test(value)) continue;
if (!CSS.supports(prop, value)) bad.push(prop + ': ' + value);
}
console.log(bad);
このコードを実行すると、使えないと判断された「プロパティ: 値」が、コンソールに一覧で表示されます。一覧に出たものが、書き間違いの候補です。何も表示されなければ、使えない書き方は残っていないことになります。
確認結果は、次のとおりです。
- 直す前のCSSで、書き間違えたmax(0, …)の指定が間違いの候補として出てきた。
- 直した後のCSSでは、何も出てこなかった。
ほかに、スライダー(Slick)に初めから入っていた古い値cursor: handも、間違いの候補として偶然見つかりました。直前の行のcursor: pointerで同じ指定ができているため、不要な行だとわかりました。
結論
今回の原因は、max()の中の0に、単位が付いていなかったことでした。コンパイルもStylelintも通り、ブラウザにエラーも出ないため、見た目だけでは気づけません。そこで、今後は、納品前のチェックとして、コンパイル後のCSSをCSS.supports()に通して、無効な指定を一覧にする確認を加えました。また、max()やcalc()、clamp()の中に0を書くときは、0remのように、単位を付けて書くことにしています。