if()
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Experimental: これは実験的な機能です。
本番で使用する前にブラウザー互換性一覧表をチェックしてください。
if()
は CSS の関数で、条件付き検査の結果に応じて、プロパティに異なる値を設定することができます。この検査は、スタイルクエリー、メディアクエリー、機能クエリーに基づいて行うことができます。
構文
/* 単独の <if-test> */
if(style(--scheme: dark): #eeeeee;)
if(media(print): black;)
if(media(width > 700px): 0 auto;)
if(supports(color: lch(7.1% 60.23 300.16)): lch(7.1% 60.23 300.16);)
/* <if-test> に else をつけたもの */
if(style(--size: "2xl"): 1em; else: 0.25em;)
if(media(print): white; else: black;)
if(media(width < 700px): 0 auto; else: 20px auto)
if(
supports(color: lch(7.1% 60.23 300.16)): lch(7.1% 60.23 300.16);
else: #03045e;
)
if(
supports(color: lch(75% 0 0)): 3px solid lch(75% 0 0);
else: 3px solid silver;
)
/* 複数の <if-test> */
if(
style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8);
style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971);
else: none;
)
/* 一括指定内の <if-test> */
3px yellow if(
style(--color: green): dashed;
style(--color: yellow): inset;
else: solid;
)
引数
この引数は、セミコロンで区切られた <if-branch>
のリストです。それぞれの <if-branch>
は、 <if-condition>
にコロンと <value>
が続く形式です。
<if-branch> = <if-condition> : <value>;
返値
値または guaranteed-invalid。
解説
CSS の if()
関数は、CSS プロパティの値に条件付き論理を提供し、JavaScript の if...else
文と同様に動作します。
if(!)
関数は、任意のプロパティの値内で使用することができ、セミコロンで区切られた <if-condition>
を 0 個以上含めることができます。それぞれの <if-condition>
は、<if-test> : <value>
のペア、または else : <value>
のペアのいずれかです。最後の <if-condition>
の後のセミコロンはオプションです。
返値は次のように計算されます。
<if-condition>
式は、関数に現れる順に評価されます。- 最初の
true
と評価される<if-condition>
は、関連付けられた<value>
を返します。 <if-condition>
がtrue
と評価されない場合、関数は <guaranteed-invalid>: を返します。これは、カスタムプロパティ やanchor()
関数など、代替値を持つ値文でif()
関数が使用されている場合、不正またはfalse
として動作します。
例を示します。
div {
background-image: if(
style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8);
style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971);
else: none;
);
}
この場合、--scheme
カスタムプロパティ が ice
とfire
のどちらに設定されているかによって、<div>
要素の background-image
として異なる linear-gradient()
を設定しています。 --scheme
が存在しない場合、または存在しても他の値に設定されている場合は、 else
の値が適用され、 background-image
プロパティは none
に設定されます。
メモ:
それぞれの条件は、関連付けられた値とコロンで区切り、それぞれの <if-condition> : <value>
ペアはセミコロンで区切る必要が あります。最後の <if-condition> : <value>
ペアでは、セミコロンはオプションです。
警告:
if
と開き括弧 ((
) の間に空白があってはなりません。空白がある場合、宣言全体が不正になります。
単一の <if-condition>
または <value>
が不正な場合、if()
関数全体が不正になるわけではありません。代わりに、パーサーは次の <if-condition> : <value>
ペアに移動します。 <if-condition>
および <value>
のいずれも有効でない場合、関数は guaranteed-invalid を返します。
else : <value>
ペアの頻度と位置
if()
関数内には、任意の位置に複数の else : <value>
ペアを含めることができます。ただし、ほとんどの場合、セミコロンで区切られたリストの最後に 1 つの else : <value>
ペアを指定して、<if-test>
のいずれも真と評価されなかった場合に常に返される既定値を指定します。
<if-test> : <value>
ペアの前に else : <value>
ペアを含めると、else
は常に true
と評価されるため、それに続く条件は評価されません。したがって、次の if()
は常に none
を返し、2 つの <if-test> : <value>
ペアは決して評価されません。
div {
background-image: if(
else: none;
style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8);
style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971)
);
}
期待どおりに動作していない値をデバッグする場合、値リストの末尾以外の位置に else : <value>
を配置したい場合があります。次の例では、最初の <if-test> : <value>
ペアが正しく動作しているかどうかを調べます。正常に動作していない場合、else : <value>
ペアは url("debug.png")
の値を返し、最初の <if-test> : <value>
ペアを修正する必要があることを示す画像を表示します。最後の 2 つの <if-test> : <value>
ペアは、ここでも評価されません。
div {
background-image: if(
style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8);
else: url("debug.png");
style(--scheme: fire): linear-gradient(#ffc971, white, #ffc971);
else: none;
);
}
if()
関数は、else : <value>
のペアのみ、またはまったく何も含まれていない場合でも、有効であることに注意してください。次のプロパティ値はどちらも有効です。
background-color: if(else: yellow);
background-image: if();
これらの関数はあまり有用ではありません。妥当性を示すために記載してあります。この場合、background-color
の値は常に yellow
に設定され、 background-image
は初期値に設定されます。 background-color
を直接 yellow
に、 background-image
を initial
または none
に設定したほうがいいでしょう。
if-test の型
<if-test>
は 3 つのクエリー型のいずれかを受け入れます。この節では、それぞれの型について詳しく見ていきます。
スタイルクエリー
スタイルクエリー の <if-test>
を使用すると、要素に特定のプロパティ値が設定されているかどうかを検査し、その結果に応じて別のプロパティに値を適用することができます。先ほど、いくつかのスタイルクエリーの例を追ってみましたが、もう 1 つ例を見てみましょう。
background-image: if(
style(--scheme: ice): linear-gradient(#caf0f8, white, #caf0f8);
else: none;
);
同じ要素で --scheme
独自のプロパティが ice
の値に設定されている場合、指定された linear-gradient()
の値が返されます。そうでない場合、none
が返されます。
if(()
文内でスタイルクエリーを使用すると、 @container
クエリーよりも利点があります。コンテナーの親要素に設定されているスタイルをチェックする代わりに、独自のプロパティが設定されているかどうかによって、スタイルが設定されている要素を直接指定できるからです。
スタイルクエリー内では、and
、or
、not
の論理も使用することができます。例を示します。
background-color: if(
style((--scheme: dark) or (--scheme: very-dark)): black;
);
background-color: if(
style((--scheme: dark) and (--contrast: hi)): black;
);
background-color: if(
not style(--scheme: light): black;
);
@container
クエリーにはいくつかの利点があります。if()
スタイルのクエリーでは、一度に 1 つのプロパティ値しか設定できませんが、@container
クエリーを使用すると、一連のルール全体を条件付きで適用することができます。この 2 つの手法は相互に補完的であり、用途も異なります。
コンテナースタイルクエリーは、現在、通常の CSS プロパティは対応していません。CSS のカスタムプロパティのみ対応しています。例えば、以下は機能しません。
if(
background-color: if(style(color: white): black;);
)
メディアクエリー
メディアクエリー の <if-test>
を使用すると、メディアクエリー検査の返値が true であるかどうかに応じて、プロパティの値を設定することができます。
メディア種別を使用することができます。例えば、次の <if-test> : <value>
ペアは、印刷メディアでは white
の値を返しますが、else
節は、印刷以外のメディアでは #eeeeee
を返します。
background-color: if(
media(print): white;
else: #eeeeee;
)
メディア特性も使用できます。次のコードは、現在のビューポートの幅が 700px
未満の場合は 0 auto
、それ以外の場合は 20px auto
という値を返します。
margin: if(
media(width < 700px): 0 auto;
else: 20px auto;
)
これは、メディアクエリー結果に基づいて 1 つのプロパティの値を変更する必要がある場合に、実に有益です。
メディアクエリー内では、and
、or
、not
の論理も使用することができます。例を示します。
border-color: if(
media((width > 700px) and (width < 1000px)): blue;
);
border-color: if(
media((width < 500px) or (orientation: landscape)): blue;
);
background-color: if(
not media(width < 500px): blue;
else: red
);
1 つのメディアクエリーに基づいて複数の宣言やルールを設定したい場合は、通常の @media
構文を使用する必要があります。この 2 つの手法は相互に補完的であり、それぞれ異なる用途があります。
機能クエリー
機能クエリー の <if-test>
を使用すると、ブラウザーが特定のプロパティ値に対応しているかどうかによって、プロパティの値を設定することができます。
例えば、lch()
色に対応している場合は lch()
色を、対応していない場合は rgb()
色を返します。
color: if(
supports(color: lch(75% 0 0)): lch(75% 0 0);
else: rgb(185 185 185);
)
セレクター対応クエリーも動作します。ブラウザーが :buffering
擬似クラスに対応している場合、次のクエリーは 1em
を返します。対応していない場合は initial
を返します。
margin-top: if(
supports(selector(:buffering)): 1em;
else: initial;
)
機能クエリー内では、and
、or
、not
論理も使用できます。例を示します。
margin-top: if(
supports((selector(:buffering)) and (color: blue)): 1em;
);
margin-top: if(
supports((selector(:buffering)) or (color: not-a-color)): 1em;
);
margin-top: if(
supports(not selector(:buffering)): 1em;
);
機能クエリーは、特定の値または別個のプロパティの対応状況に 基づいて単一のプロパティの値を変更する必要がある場合、 if()
文内で実に便利です。1 つの機能クエリーに基づいて複数の宣言またはルールを設定する場合は、通常の @supports
構文を使用することをお勧めします。この 2 つの手法は相互に補完的であり、用途も異なります。
代替値の指定
if()
文は、うまく機能しなくなることはありません。対応していないブラウザー用に、明示的な代替手段を指定しておく必要があります。
例えば、この例では、if()
に対応していないブラウザー用に、静的な padding
値を指定しています。if()
に対応しているブラウザーでは、最初の宣言は 2 つ目の宣言で上書きされ、 --size: "2xl"
という独自のプロパティが設定されているかどうかによって、異なるパディング値が設定されます。
padding: 1em;
padding: if(style(--size: "2xl"): 1em; else: 0.25em);
メモ:
else
条件を忘れずに記載してください。if()
に対応しているブラウザーでは、else
値が記載されておらず、--size
が "2xl"
以外の場合、パディングは initial
に設定されます。
全体および部分的な値
if()
関数は、任意の CSS プロパティの値として設定することができますが、プロパティ値の一部を決定するためにも使用できます。例えば、次の例では、lch()
の色指定に対応しているかどうかによって、border
一括指定プロパティ内の border-color
に異なる値を設定しています。
border: if(
supports(color: lch(75% 0 0)): 3px solid lch(75% 0 0);
else: 3px solid silver;
);
しかし、if()
関数を使用すると、border-color
要素のみを指定することができます。
border: 3px solid
if(
supports(color: lch(75% 0 0)): lch(75% 0 0); else: silver;
);
if() 関数の入れ子
if()
関数は、プロパティ値全体または個々の要素の場所として取ることができるため、if()
関数を他の if()
関数内、および calc()
などの他の関数内に入れ子にして使用することができます。
例えば、この宣言では、if()
を使用して、さまざまな条件に応じて color
プロパティの値を設定しています。外側の if()
関数は、カスタムプロパティ --scheme
が ice
と fire
のどちらに設定されているかによって、具体的な値を返します(どちらの条件も真を返さない場合は、 else
値 black
が返されます)。
ただし、2 つの <value>
も if()
関数です。これらの内部 if()
関数は、ユーザーが暗い色スキームを推奨している場合(prefers-color-scheme
メディアクエリーを使用して決定)、明るい色の値を返し、そうでない場合は暗い色の値を返します。
color: if(
style(--scheme: ice):
if(
media(prefers-color-scheme: dark): #caf0f8;
else: #03045e;
);
style(--scheme: fire):
if(
media(prefers-color-scheme: dark): #ffc971;
else: #621708;
);
else: black
);
次の例では、width
プロパティを、親要素の幅のパーセント値から 50px
を差し引く calc()
関数に設定します。パーセント値は、--scheme: wide
というカスタムプロパティが設定されているかどうかを検査する if()
関数で表します。設定されている場合、パーセント値は 70%
なので、外側の関数は calc(70% - 50px)
と評価されます。設定されていない場合、パーセント値は 50%
なので、外側の関数は calc(50% - 50px)
と評価されます。
width: calc(if(
style(--scheme: wide): 70%;
else: 50%;
) - 50px);
形式文法
Parse error: Unexpected input例
>基本的な if()
の使い方
この例では、3 つの種類の <if-test>
のそれぞれの基本的な使用法を示します。
HTML
この HTML には、2 つの <article>
要素を含む <section>
要素があり、その中に <h2>
見出しが含まれています。 <section>
には、style
属性内にカスタムプロパティ --show-apple:true
が設定されています。このプロパティは、後でプロパティの値を条件付きで設定するために使用します。
<section style="--show-apple:true">
<article><h2>最初の記事</h2></article>
<article><h2>次の記事</h2></article>
</section>
CSS
CSS では、最初に <section>
要素を対象とし、フレックスボックス でレイアウトし、2 つの子要素 <article>
要素の間に gap
を設定します。次に、 orientation
メディアクエリー <if-test>
を含む if()
関数を使用して、文書が横向きの場合に flex-direction
プロパティの値を row
に、縦向きの場合に column
に設定します。これにより、広い画面では article
要素が横に並んだレイアウトになり、狭い画面では上下に並んだレイアウトになります。
section {
display: flex;
gap: 16px;
flex-direction: if(
media(orientation: landscape): row;
else: column;
)
}
次に、<h2>
要素の ::before
擬似要素をターゲットとし、その content
プロパティをリンゴの絵文字に設定します。ただし、--show-apple: true
が設定されている場合のみです(これは、HTML でインライン <style>
を使用して、先ほど設定しました)。これは、スタイルクエリー の <if-test>
に対応する if()
関数を使用して実現しています。
h2::before {
content: if(
style(--show-apple: true): "🍎 ";
);
}
最後に、<h2>
要素自体をターゲットにします。機能クエリー <if-test>
を使用して、ブラウザーが lch()
色に対応しているかどうかを検査し、対応している場合は color
プロパティを lch()
色に設定し、対応していない場合は 16 進数で表現した色に設定します。
h2 {
color: if(
supports(color: lch(29.57% 43.25 344.44)): lch(29.57% 43.25 344.44);
else: #792359;
)
}
結果
スタイル設定がどのように適用されているかに注目してください。ブラウザーの開発者ツールを使用して、レンダリングされたデモを変更し、最初の 2 つの if()
クエリーに対する条件付きスタイル設定を検査してください。
<section>
要素のstyle
属性を除去し、リンゴの絵文字が表示されなくなったことを確認してください。- 埋め込み
<iframe>
のheight
属性を1200px
に変更します。これにより、方向が横向きから縦向きに変更されます。その結果、レイアウトがどのように変化するかを確認してください。
if()
による配色の制御
このデモでは、CSS の if()
関数を使って、CSS をより楽しく使う方法をご紹介します。それ以外にも、if()
関数を使って、カスタムプロパティの値を条件に応じて設定し、配色全体を制御することができます。
HTML
HTML には、いくつかのコンテンツを含む <article>
要素が含まれています。最上位の見出し、2 つの <p>
要素、および <aside>
です。また、配色を選択できる <select>
ドロップダウンを含む <form>
も含んでいます。
<article>
<h1>Main heading</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipiscing elit.
Quisque faucibus ex sapien vitae pellentesque sem placerat.
In id cursus mi pretium tellus duis convallis.
</p>
<aside>
<h2>An aside</h2>
<p>
Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus
fringilla lacus nec metus bibendum egestas.
</p>
</aside>
<p>
Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut
hendrerit semper vel class aptent taciti sociosqu. Ad litora
torquent per conubia nostra inceptos himenaeos.
</p>
</article>
<form>
<label for="scheme">配色を選択:</label>
<select id="scheme">
<option value="">既定</option>
<option value="ice">Ice</option>
<option value="fire">Fire</option>
</select>
</form>
JavaScript
JavaScript は、<select>
要素に change
イベントリスナーを追加します。新しい値が選択されると、スクリプトは <article>
要素の class
属性をその値に設定します。
const articleElem = document.querySelector("article");
const selectElem = document.querySelector("select");
selectElem.addEventListener("change", () => {
articleElem.className = selectElem.value;
});
CSS
CSS では、<body>
要素に 700px
の max-width
を指定し、auto
margin
の値を使用して中央に配置しています。しかし、メディアクエリー <if-test>
を含む if()
関数を使用して、ビューポートの幅が 700px
未満の場合は margin
一括指定内の margin-top
要素を 0
に、それより広い場合は 20px
に設定します。これは、広い画面ではコンテンツの上部に少しマージンが取得されるが、狭い画面ではそれが除去され、少し奇妙に見えることを意味している。
body {
max-width: 700px;
margin: if(
media(width < 700px): 0;
else: 20px;
) auto 0;
}
次に、<article>
要素の class
名と一致するように、--scheme
というカスタムプロパティを設定します。このクラスは、<select>
要素で新しい値が選択されると、JavaScript によって設定されます。カスタム要素の値の重要性は、次の CSS ブロックでわかります。
.ice {
--scheme: ice;
}
.fire {
--scheme: fire;
}
CSS の if()
関数の真の実力は、カスタムプロパティと組み合わせたときに発揮されます。ここでは、if()
関数を使用して、カスタムプロパティ --scheme
の値に応じて、カスタムプロパティ --color1
と --color2
に異なる色値を設定しています。次に、<article>
要素の color
、border
、background-image
プロパティ、および <aside>
要素の color
および background-color
プロパティで、--color1
および --color2
の値を使用しています。
ここでは、独自のプロパティを使用して、 if()
関数で設定したさまざまな値によって、配色全体を制御しています。
article {
padding: 20px;
--color1: if(
style(--scheme: ice): #03045e;
style(--scheme: fire): #621708;
else: black;
);
--color2: if(
style(--scheme: ice): #caf0f8;
style(--scheme: fire): #ffc971;
else: white;
);
color: var(--color1);
border: 3px solid var(--color1);
background-image: linear-gradient(
to left,
var(--color2),
white,
var(--color2)
);
}
aside {
color: var(--color2);
background-color: var(--color1);
padding: 20px;
}
最後に、if()
関数をさらに 2 か所で使用します。
- ビューポートの幅が
700px
より広い場合は、<h1>
要素のfont-size
をcalc(3rem + 2vw)
に設定し、それ以外の場合は3rem
に設定します。これは、広い画面ではフォントサイズがビューポートの幅の変化に応じて動的に更新され、狭い画面ではフォントサイズが変更されないことを意味しています。 --scheme
カスタムプロパティの値に応じて、<h1>
要素の::before
擬似クラスのcontent
に適切な絵文字を設定します。
h1 {
margin: 0;
font-size: if(
media(width > 700px): calc(3rem + 2vw);
else: 3rem;
);
}
h1::before {
content: if(
style(--scheme: ice): "❄️ ";
style(--scheme: fire): "🔥 ";
else: "";
);
}
結果
このデモは次のように表示されます。
さまざまな配色値を選択して、外観や操作感に与える効果を確認してみてください。
仕様書
Specification |
---|
CSS Values and Units Module Level 5> # if-notation> |
ブラウザーの互換性
Loading…