CINXE.COM
CSS Conditional Values Module Level 1
<!doctype html><html lang="en"> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"> <title>CSS Conditional Values Module Level 1</title> <meta content="UD" name="w3c-status"> <link href="https://www.w3.org/StyleSheets/TR/2021/W3C-UD" rel="stylesheet"> <meta content="Bikeshed version 742f3d674, updated Mon Nov 4 14:56:54 2024 -0800" name="generator"> <link href="https://drafts.csswg.org/css-conditional-values-1/" rel="canonical"> <meta content="dbde8fabad3b9e7fb3b25413cb4293c8e9d527d8" name="revision"> <meta content="dark light" name="color-scheme"> <link href="https://www.w3.org/StyleSheets/TR/2021/dark.css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css"> <style>/* Boilerplate: style-autolinks */ .css.css, .property.property, .descriptor.descriptor { color: var(--a-normal-text); font-size: inherit; font-family: inherit; } .css::before, .property::before, .descriptor::before { content: "‘"; } .css::after, .property::after, .descriptor::after { content: "’"; } .property, .descriptor { /* Don't wrap property and descriptor names */ white-space: nowrap; } .type { /* CSS value <type> */ font-style: italic; } pre .property::before, pre .property::after { content: ""; } [data-link-type="property"]::before, [data-link-type="propdesc"]::before, [data-link-type="descriptor"]::before, [data-link-type="value"]::before, [data-link-type="function"]::before, [data-link-type="at-rule"]::before, [data-link-type="selector"]::before, [data-link-type="maybe"]::before { content: "‘"; } [data-link-type="property"]::after, [data-link-type="propdesc"]::after, [data-link-type="descriptor"]::after, [data-link-type="value"]::after, [data-link-type="function"]::after, [data-link-type="at-rule"]::after, [data-link-type="selector"]::after, [data-link-type="maybe"]::after { content: "’"; } [data-link-type].production::before, [data-link-type].production::after, .prod [data-link-type]::before, .prod [data-link-type]::after { content: ""; } [data-link-type=element], [data-link-type=element-attr] { font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace; font-size: .9em; } [data-link-type=element]::before { content: "<" } [data-link-type=element]::after { content: ">" } [data-link-type=biblio] { white-space: pre; } @media (prefers-color-scheme: dark) { :root { --selflink-text: black; --selflink-bg: silver; --selflink-hover-text: white; } } </style> <style>/* Boilerplate: style-colors */ /* Any --*-text not paired with a --*-bg is assumed to have a transparent bg */ :root { color-scheme: light dark; --text: black; --bg: white; --unofficial-watermark: url(https://www.w3.org/StyleSheets/TR/2016/logos/UD-watermark); --logo-bg: #1a5e9a; --logo-active-bg: #c00; --logo-text: white; --tocnav-normal-text: #707070; --tocnav-normal-bg: var(--bg); --tocnav-hover-text: var(--tocnav-normal-text); --tocnav-hover-bg: #f8f8f8; --tocnav-active-text: #c00; --tocnav-active-bg: var(--tocnav-normal-bg); --tocsidebar-text: var(--text); --tocsidebar-bg: #f7f8f9; --tocsidebar-shadow: rgba(0,0,0,.1); --tocsidebar-heading-text: hsla(203,20%,40%,.7); --toclink-text: var(--text); --toclink-underline: #3980b5; --toclink-visited-text: var(--toclink-text); --toclink-visited-underline: #054572; --heading-text: #005a9c; --hr-text: var(--text); --algo-border: #def; --del-text: red; --del-bg: transparent; --ins-text: #080; --ins-bg: transparent; --a-normal-text: #034575; --a-normal-underline: #bbb; --a-visited-text: var(--a-normal-text); --a-visited-underline: #707070; --a-hover-bg: rgba(75%, 75%, 75%, .25); --a-active-text: #c00; --a-active-underline: #c00; --blockquote-border: silver; --blockquote-bg: transparent; --blockquote-text: currentcolor; --issue-border: #e05252; --issue-bg: #fbe9e9; --issue-text: var(--text); --issueheading-text: #831616; --example-border: #e0cb52; --example-bg: #fcfaee; --example-text: var(--text); --exampleheading-text: #574b0f; --note-border: #52e052; --note-bg: #e9fbe9; --note-text: var(--text); --noteheading-text: hsl(120, 70%, 30%); --notesummary-underline: silver; --assertion-border: #aaa; --assertion-bg: #eee; --assertion-text: black; --advisement-border: orange; --advisement-bg: #fec; --advisement-text: var(--text); --advisementheading-text: #b35f00; --warning-border: red; --warning-bg: hsla(40,100%,50%,0.95); --warning-text: var(--text); --amendment-border: #330099; --amendment-bg: #F5F0FF; --amendment-text: var(--text); --amendmentheading-text: #220066; --def-border: #8ccbf2; --def-bg: #def; --def-text: var(--text); --defrow-border: #bbd7e9; --datacell-border: silver; --indexinfo-text: #707070; --indextable-hover-text: black; --indextable-hover-bg: #f7f8f9; --outdatedspec-bg: rgba(0, 0, 0, .5); --outdatedspec-text: black; --outdated-bg: maroon; --outdated-text: white; --outdated-shadow: red; --editedrec-bg: darkorange; } @media (prefers-color-scheme: dark) { :root { --text: #ddd; --bg: black; --unofficial-watermark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cg fill='%23100808' transform='translate(200 200) rotate(-45) translate(-200 -200)' stroke='%23100808' stroke-width='3'%3E%3Ctext x='50%25' y='220' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EUNOFFICIAL%3C/text%3E%3Ctext x='50%25' y='305' style='font: bold 70px sans-serif; text-anchor: middle; letter-spacing: 6px;'%3EDRAFT%3C/text%3E%3C/g%3E%3C/svg%3E"); --logo-bg: #1a5e9a; --logo-active-bg: #c00; --logo-text: white; --tocnav-normal-text: #999; --tocnav-normal-bg: var(--bg); --tocnav-hover-text: var(--tocnav-normal-text); --tocnav-hover-bg: #080808; --tocnav-active-text: #f44; --tocnav-active-bg: var(--tocnav-normal-bg); --tocsidebar-text: var(--text); --tocsidebar-bg: #080808; --tocsidebar-shadow: rgba(255,255,255,.1); --tocsidebar-heading-text: hsla(203,20%,40%,.7); --toclink-text: var(--text); --toclink-underline: #6af; --toclink-visited-text: var(--toclink-text); --toclink-visited-underline: #054572; --heading-text: #8af; --hr-text: var(--text); --algo-border: #456; --del-text: #f44; --del-bg: transparent; --ins-text: #4a4; --ins-bg: transparent; --a-normal-text: #6af; --a-normal-underline: #555; --a-visited-text: var(--a-normal-text); --a-visited-underline: var(--a-normal-underline); --a-hover-bg: rgba(25%, 25%, 25%, .2); --a-active-text: #f44; --a-active-underline: var(--a-active-text); --borderedblock-bg: rgba(255, 255, 255, .05); --blockquote-border: silver; --blockquote-bg: var(--borderedblock-bg); --blockquote-text: currentcolor; --issue-border: #e05252; --issue-bg: var(--borderedblock-bg); --issue-text: var(--text); --issueheading-text: hsl(0deg, 70%, 70%); --example-border: hsl(50deg, 90%, 60%); --example-bg: var(--borderedblock-bg); --example-text: var(--text); --exampleheading-text: hsl(50deg, 70%, 70%); --note-border: hsl(120deg, 100%, 35%); --note-bg: var(--borderedblock-bg); --note-text: var(--text); --noteheading-text: hsl(120, 70%, 70%); --notesummary-underline: silver; --assertion-border: #444; --assertion-bg: var(--borderedblock-bg); --assertion-text: var(--text); --advisement-border: orange; --advisement-bg: #222218; --advisement-text: var(--text); --advisementheading-text: #f84; --warning-border: red; --warning-bg: hsla(40,100%,20%,0.95); --warning-text: var(--text); --amendment-border: #330099; --amendment-bg: #080010; --amendment-text: var(--text); --amendmentheading-text: #cc00ff; --def-border: #8ccbf2; --def-bg: #080818; --def-text: var(--text); --defrow-border: #136; --datacell-border: silver; --indexinfo-text: #aaa; --indextable-hover-text: var(--text); --indextable-hover-bg: #181818; --outdatedspec-bg: rgba(255, 255, 255, .5); --outdatedspec-text: black; --outdated-bg: maroon; --outdated-text: white; --outdated-shadow: red; --editedrec-bg: darkorange; } /* In case a transparent-bg image doesn't expect to be on a dark bg, which is quite common in practice... */ img { background: white; } } </style> <style>/* Boilerplate: style-counters */ body { counter-reset: example figure issue; } .issue { counter-increment: issue; } .issue:not(.no-marker)::before { content: "Issue " counter(issue); } .example { counter-increment: example; } .example:not(.no-marker)::before { content: "Example " counter(example); } .invalid.example:not(.no-marker)::before, .illegal.example:not(.no-marker)::before { content: "Invalid Example" counter(example); } figcaption { counter-increment: figure; } figcaption:not(.no-marker)::before { content: "Figure " counter(figure) " "; } </style> <style>/* Boilerplate: style-dfn-panel */ :root { --dfnpanel-bg: #ddd; --dfnpanel-text: var(--text); --dfnpanel-target-bg: #ffc; --dfnpanel-target-outline: orange; } @media (prefers-color-scheme: dark) { :root { --dfnpanel-bg: #222; --dfnpanel-text: var(--text); --dfnpanel-target-bg: #333; --dfnpanel-target-outline: silver; } } .dfn-panel { position: absolute; z-index: 35; width: 20em; width: 300px; height: auto; max-height: 500px; overflow: auto; padding: 0.5em 0.75em; font: small Helvetica Neue, sans-serif, Droid Sans Fallback; background: var(--dfnpanel-bg); color: var(--dfnpanel-text); border: outset 0.2em; white-space: normal; /* in case it's moved into a pre */ } .dfn-panel:not(.on) { display: none; } .dfn-panel * { margin: 0; padding: 0; text-indent: 0; } .dfn-panel > b { display: block; } .dfn-panel a { color: var(--dfnpanel-text); } .dfn-panel a:not(:hover) { text-decoration: none !important; border-bottom: none !important; } .dfn-panel a:focus { outline: 5px auto Highlight; outline: 5px auto -webkit-focus-ring-color; } .dfn-panel > b + b { margin-top: 0.25em; } .dfn-panel ul { padding: 0 0 0 1em; list-style: none; } .dfn-panel li a { max-width: calc(300px - 1.5em - 1em); overflow: hidden; text-overflow: ellipsis; } .dfn-panel.activated { display: inline-block; position: fixed; left: 8px; bottom: 2em; margin: 0 auto; max-width: calc(100vw - 1.5em - .4em - .5em); max-height: 30vh; transition: left 1s ease-out, bottom 1s ease-out; } .dfn-panel .link-item:hover { text-decoration: underline; } .dfn-panel .link-item .copy-icon { opacity: 0; } .dfn-panel .link-item:hover .copy-icon, .dfn-panel .link-item .copy-icon:focus { opacity: 1; } .dfn-panel .copy-icon { display: inline-block; margin-right: 0.5em; width: 0.85em; height: 1em; border-radius: 3px; background-color: #ccc; cursor: pointer; } .dfn-panel .copy-icon .icon { width: 100%; height: 100%; background-color: #fff; display: flex; justify-content: center; align-items: center; position: relative; } .dfn-panel .copy-icon .icon::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: 1px solid black; background-color: #ccc; opacity: 0.25; transform: translate(3px, -3px); } .dfn-panel .copy-icon:active .icon::before { opacity: 1; } .dfn-paneled[role="button"] { cursor: help; } .highlighted { animation: target-fade 3s; } @keyframes target-fade { from { background-color: var(--dfnpanel-target-bg); outline: 5px solid var(--dfnpanel-target-outline); } to { color: var(--a-normal-text); background-color: transparent; outline: transparent; } } </style> <style>/* Boilerplate: style-issues */ a[href].issue-return { float: right; float: inline-end; color: var(--issueheading-text); font-weight: bold; text-decoration: none; } </style> <style>/* Boilerplate: style-md-lists */ /* This is a weird hack for me not yet following the commonmark spec regarding paragraph and lists. */ [data-md] > :first-child { margin-top: 0; } [data-md] > :last-child { margin-bottom: 0; } </style> <style>/* Boilerplate: style-ref-hints */ :root { --ref-hint-bg: #ddd; --ref-hint-text: var(--text); } @media (prefers-color-scheme: dark) { :root { --ref-hint-bg: #222; --ref-hint-text: var(--text); } } .ref-hint { display: inline-block; position: absolute; z-index: 35; width: 20em; width: 300px; height: auto; max-height: 500px; overflow: auto; padding: 0.5em 0.5em; font: small Helvetica Neue, sans-serif, Droid Sans Fallback; background: var(--ref-hint-bg); color: var(--ref-hint-text); border: outset 0.2em; white-space: normal; /* in case it's moved into a pre */ } .ref-hint * { margin: 0; padding: 0; text-indent: 0; } .ref-hint ul { padding: 0 0 0 1em; list-style: none; } </style> <style>/* Boilerplate: style-selflinks */ :root { --selflink-text: white; --selflink-bg: gray; --selflink-hover-text: black; } .heading, .issue, .note, .example, li, dt { position: relative; } a.self-link { position: absolute; top: 0; left: calc(-1 * (3.5rem - 26px)); width: calc(3.5rem - 26px); height: 2em; text-align: center; border: none; transition: opacity .2s; opacity: .5; } a.self-link:hover { opacity: 1; } .heading > a.self-link { font-size: 83%; } .example > a.self-link, .note > a.self-link, .issue > a.self-link { /* These blocks are overflow:auto, so positioning outside doesn't work. */ left: auto; right: 0; } li > a.self-link { left: calc(-1 * (3.5rem - 26px) - 2em); } dfn > a.self-link { top: auto; left: auto; opacity: 0; width: 1.5em; height: 1.5em; background: var(--selflink-bg); color: var(--selflink-text); font-style: normal; transition: opacity .2s, background-color .2s, color .2s; } dfn:hover > a.self-link { opacity: 1; } dfn > a.self-link:hover { color: var(--selflink-hover-text); } a.self-link::before { content: "¶"; } .heading > a.self-link::before { content: "§"; } dfn > a.self-link::before { content: "#"; } </style> <style>/* Boilerplate: style-syntax-highlighting */ code.highlight { padding: .1em; border-radius: .3em; } pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; } .highlight:not(.idl) { background: rgba(0, 0, 0, .03); } c-[a] { color: #990055 } /* Keyword.Declaration */ c-[b] { color: #990055 } /* Keyword.Type */ c-[c] { color: #708090 } /* Comment */ c-[d] { color: #708090 } /* Comment.Multiline */ c-[e] { color: #0077aa } /* Name.Attribute */ c-[f] { color: #669900 } /* Name.Tag */ c-[g] { color: #222222 } /* Name.Variable */ c-[k] { color: #990055 } /* Keyword */ c-[l] { color: #000000 } /* Literal */ c-[m] { color: #000000 } /* Literal.Number */ c-[n] { color: #0077aa } /* Name */ c-[o] { color: #999999 } /* Operator */ c-[p] { color: #999999 } /* Punctuation */ c-[s] { color: #a67f59 } /* Literal.String */ c-[t] { color: #a67f59 } /* Literal.String.Single */ c-[u] { color: #a67f59 } /* Literal.String.Double */ c-[cp] { color: #708090 } /* Comment.Preproc */ c-[c1] { color: #708090 } /* Comment.Single */ c-[cs] { color: #708090 } /* Comment.Special */ c-[kc] { color: #990055 } /* Keyword.Constant */ c-[kn] { color: #990055 } /* Keyword.Namespace */ c-[kp] { color: #990055 } /* Keyword.Pseudo */ c-[kr] { color: #990055 } /* Keyword.Reserved */ c-[ld] { color: #000000 } /* Literal.Date */ c-[nc] { color: #0077aa } /* Name.Class */ c-[no] { color: #0077aa } /* Name.Constant */ c-[nd] { color: #0077aa } /* Name.Decorator */ c-[ni] { color: #0077aa } /* Name.Entity */ c-[ne] { color: #0077aa } /* Name.Exception */ c-[nf] { color: #0077aa } /* Name.Function */ c-[nl] { color: #0077aa } /* Name.Label */ c-[nn] { color: #0077aa } /* Name.Namespace */ c-[py] { color: #0077aa } /* Name.Property */ c-[ow] { color: #999999 } /* Operator.Word */ c-[mb] { color: #000000 } /* Literal.Number.Bin */ c-[mf] { color: #000000 } /* Literal.Number.Float */ c-[mh] { color: #000000 } /* Literal.Number.Hex */ c-[mi] { color: #000000 } /* Literal.Number.Integer */ c-[mo] { color: #000000 } /* Literal.Number.Oct */ c-[sb] { color: #a67f59 } /* Literal.String.Backtick */ c-[sc] { color: #a67f59 } /* Literal.String.Char */ c-[sd] { color: #a67f59 } /* Literal.String.Doc */ c-[se] { color: #a67f59 } /* Literal.String.Escape */ c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */ c-[si] { color: #a67f59 } /* Literal.String.Interpol */ c-[sx] { color: #a67f59 } /* Literal.String.Other */ c-[sr] { color: #a67f59 } /* Literal.String.Regex */ c-[ss] { color: #a67f59 } /* Literal.String.Symbol */ c-[vc] { color: #0077aa } /* Name.Variable.Class */ c-[vg] { color: #0077aa } /* Name.Variable.Global */ c-[vi] { color: #0077aa } /* Name.Variable.Instance */ c-[il] { color: #000000 } /* Literal.Number.Integer.Long */ @media (prefers-color-scheme: dark) { .highlight:not(.idl) { background: rgba(255, 255, 255, .05); } c-[a] { color: #d33682 } /* Keyword.Declaration */ c-[b] { color: #d33682 } /* Keyword.Type */ c-[c] { color: #2aa198 } /* Comment */ c-[d] { color: #2aa198 } /* Comment.Multiline */ c-[e] { color: #268bd2 } /* Name.Attribute */ c-[f] { color: #b58900 } /* Name.Tag */ c-[g] { color: #cb4b16 } /* Name.Variable */ c-[k] { color: #d33682 } /* Keyword */ c-[l] { color: #657b83 } /* Literal */ c-[m] { color: #657b83 } /* Literal.Number */ c-[n] { color: #268bd2 } /* Name */ c-[o] { color: #657b83 } /* Operator */ c-[p] { color: #657b83 } /* Punctuation */ c-[s] { color: #6c71c4 } /* Literal.String */ c-[t] { color: #6c71c4 } /* Literal.String.Single */ c-[u] { color: #6c71c4 } /* Literal.String.Double */ c-[ch] { color: #2aa198 } /* Comment.Hashbang */ c-[cp] { color: #2aa198 } /* Comment.Preproc */ c-[cpf] { color: #2aa198 } /* Comment.PreprocFile */ c-[c1] { color: #2aa198 } /* Comment.Single */ c-[cs] { color: #2aa198 } /* Comment.Special */ c-[kc] { color: #d33682 } /* Keyword.Constant */ c-[kn] { color: #d33682 } /* Keyword.Namespace */ c-[kp] { color: #d33682 } /* Keyword.Pseudo */ c-[kr] { color: #d33682 } /* Keyword.Reserved */ c-[ld] { color: #657b83 } /* Literal.Date */ c-[nc] { color: #268bd2 } /* Name.Class */ c-[no] { color: #268bd2 } /* Name.Constant */ c-[nd] { color: #268bd2 } /* Name.Decorator */ c-[ni] { color: #268bd2 } /* Name.Entity */ c-[ne] { color: #268bd2 } /* Name.Exception */ c-[nf] { color: #268bd2 } /* Name.Function */ c-[nl] { color: #268bd2 } /* Name.Label */ c-[nn] { color: #268bd2 } /* Name.Namespace */ c-[py] { color: #268bd2 } /* Name.Property */ c-[ow] { color: #657b83 } /* Operator.Word */ c-[mb] { color: #657b83 } /* Literal.Number.Bin */ c-[mf] { color: #657b83 } /* Literal.Number.Float */ c-[mh] { color: #657b83 } /* Literal.Number.Hex */ c-[mi] { color: #657b83 } /* Literal.Number.Integer */ c-[mo] { color: #657b83 } /* Literal.Number.Oct */ c-[sa] { color: #6c71c4 } /* Literal.String.Affix */ c-[sb] { color: #6c71c4 } /* Literal.String.Backtick */ c-[sc] { color: #6c71c4 } /* Literal.String.Char */ c-[dl] { color: #6c71c4 } /* Literal.String.Delimiter */ c-[sd] { color: #6c71c4 } /* Literal.String.Doc */ c-[se] { color: #6c71c4 } /* Literal.String.Escape */ c-[sh] { color: #6c71c4 } /* Literal.String.Heredoc */ c-[si] { color: #6c71c4 } /* Literal.String.Interpol */ c-[sx] { color: #6c71c4 } /* Literal.String.Other */ c-[sr] { color: #6c71c4 } /* Literal.String.Regex */ c-[ss] { color: #6c71c4 } /* Literal.String.Symbol */ c-[fm] { color: #268bd2 } /* Name.Function.Magic */ c-[vc] { color: #cb4b16 } /* Name.Variable.Class */ c-[vg] { color: #cb4b16 } /* Name.Variable.Global */ c-[vi] { color: #cb4b16 } /* Name.Variable.Instance */ c-[vm] { color: #cb4b16 } /* Name.Variable.Magic */ c-[il] { color: #657b83 } /* Literal.Number.Integer.Long */ } </style> <body class="h-entry"> <div class="head"> <p data-fill-with="logo"><a class="logo" href="https://www.w3.org/"> <img alt="W3C" height="48" src="https://www.w3.org/StyleSheets/TR/2021/logos/W3C" width="72"> </a> </p> <h1 class="p-name no-ref" id="title">CSS Conditional Values Module Level 1</h1> <p id="w3c-state"><a href="https://www.w3.org/standards/types/#UD">Unofficial Proposal Draft</a>, <time class="dt-updated" datetime="2023-02-21">21 February 2023</time></p> <details open> <summary>More details about this document</summary> <div data-fill-with="spec-metadata"> <dl> <dt>This version: <dd><a class="u-url" href="https://drafts.csswg.org/css-conditional-values-1/">https://drafts.csswg.org/css-conditional-values-1/</a> <dt>Issue Tracking: <dd><a href="https://github.com/w3c/csswg-drafts/labels/css-conditional-values-1">CSSWG Issues Repository</a> <dd><a href="#issues-index">Inline In Spec</a> <dt class="editor">Editor: <dd class="editor p-author h-card vcard" data-editor-id="52258"><a class="p-name fn u-url url" href="http://lea.verou.me/about">Lea Verou</a> (<span class="p-org org">Invited Expert</span>) <dt>Suggest an Edit for this Spec: <dd><a href="https://github.com/w3c/csswg-drafts/blob/main/css-conditional-values-1/Overview.bs">GitHub Editor</a> </dl> </div> </details> <div data-fill-with="warning"> <details class="annoying-warning" open> <summary>Not Ready For Implementation</summary> <p> This spec is not yet ready for implementation. It exists in this repository to record the ideas and promote discussion. </p> <p> Before attempting to implement this spec, please contact the CSSWG at www-style@w3.org. </p> </details> </div> <p class="copyright" data-fill-with="copyright"><a href="https://www.w3.org/policies/#copyright">Copyright</a> © 2023 <a href="https://www.w3.org/">World Wide Web Consortium</a>. <abbr title="World Wide Web Consortium">W3C</abbr><sup>®</sup> <a href="https://www.w3.org/policies/#Legal_Disclaimer">liability</a>, <a href="https://www.w3.org/policies/#W3C_Trademarks">trademark</a> and <a href="https://www.w3.org/copyright/software-license/" rel="license" title="W3C Software and Document License">permissive document license</a> rules apply. </p> <hr title="Separator for header"> </div> <div class="p-summary" data-fill-with="abstract"> <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2> <p>This module explores additions to CSS to enable conditional values.</p> <a href="https://www.w3.org/TR/CSS/">CSS</a> is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc. <script> const githubPrefix = "https://w3c.github.io/csswg-drafts/"; if(location.href.slice(0, githubPrefix.length) == githubPrefix) { const suffix = location.href.slice(githubPrefix.length); const draftUrl = "https://drafts.csswg.org/" + suffix; window.location.replace(draftUrl); } </script> </div> <h2 class="no-num no-toc no-ref heading settled" id="sotd"><span class="content">Status of this document</span></h2> <div data-fill-with="status"> <p><em>This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the <a href="https://www.w3.org/TR/">W3C technical reports index at https://www.w3.org/TR/.</a></em> </p> <p>Please send feedback by <a href="https://github.com/w3c/csswg-drafts/issues">filing issues in GitHub</a> (preferred), including the spec code “css-conditional-values” in the title, like this: “[css-conditional-values] <i>…summary of comment…</i>”. All issues and comments are <a href="https://lists.w3.org/Archives/Public/public-css-archive/">archived</a>. Alternately, feedback can be sent to the (<a href="https://lists.w3.org/Archives/Public/www-style/">archived</a>) public mailing list <a href="mailto:www-style@w3.org?Subject=%5Bcss-conditional-values%5D%20PUT%20SUBJECT%20HERE">www-style@w3.org</a>. </p> <p>This document is governed by the <a href="https://www.w3.org/policies/process/20231103/" id="w3c_process_revision">03 November 2023 W3C Process Document</a>. </p> <p>This document was produced by a group operating under the <a href="https://www.w3.org/policies/patent-policy/20200915/">W3C Patent Policy</a>. W3C maintains a <a href="https://www.w3.org/groups/wg/css/ipr" rel="disclosure">public list of any patent disclosures</a> made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains <a href="https://www.w3.org/policies/patent-policy/20200915/#def-essential">Essential Claim(s)</a> must disclose the information in accordance with <a href="https://www.w3.org/policies/patent-policy/20200915/#sec-Disclosure">section 6 of the W3C Patent Policy</a>. </p> <p></p> </div> <div data-fill-with="at-risk"></div> <nav data-fill-with="table-of-contents" id="toc"> <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2> <ol class="toc" role="directory"> <li> <a href="#intro"><span class="secno">1</span> <span class="content">Introduction</span></a> <ol class="toc"> <li><a href="#high-level-custom-properties"><span class="secno">1.1</span> <span class="content">High level custom properties</span></a> <li><a href="#relation-between-units"><span class="secno">1.2</span> <span class="content">Relation between units of the same type</span></a> <li><a href="#values"><span class="secno">1.3</span> <span class="content">Value Definitions</span></a> </ol> <li> <a href="#boolean"><span class="secno">2</span> <span class="content">Boolean data types</span></a> <ol class="toc"> <li><a href="#bool-constants"><span class="secno">2.1</span> <span class="content">Boolean constants: <span class="css">true</span> and <span class="css">false</span></span></a> <li> <a href="#condition"><span class="secno">2.2</span> <span class="content">Logical comparisons: The <span class="production"><condition></span> type</span></a> <ol class="toc"> <li><a href="#condition-computed-value"><span class="secno">2.2.1</span> <span class="content"> Computed Value</span></a> </ol> </ol> <li><a href="#if"><span class="secno">3</span> <span class="content">Inline conditionals: The <span class="css">if()</span> function</span></a> <li><a href="#priv-sec"><span class="secno">4</span> <span class="content">Privacy and Security Considerations</span></a> <li> <a href="#w3c-conformance"><span class="secno"></span> <span class="content"> Conformance</span></a> <ol class="toc"> <li><a href="#w3c-conventions"><span class="secno"></span> <span class="content"> Document conventions</span></a> <li><a href="#w3c-conformance-classes"><span class="secno"></span> <span class="content"> Conformance classes</span></a> <li> <a href="#w3c-partial"><span class="secno"></span> <span class="content"> Partial implementations</span></a> <ol class="toc"> <li><a href="#w3c-conform-future-proofing"><span class="secno"></span> <span class="content"> Implementations of Unstable and Proprietary Features</span></a> </ol> <li><a href="#w3c-testing"><span class="secno"></span> <span class="content"> Non-experimental implementations</span></a> </ol> <li> <a href="#index"><span class="secno"></span> <span class="content">Index</span></a> <ol class="toc"> <li><a href="#index-defined-here"><span class="secno"></span> <span class="content">Terms defined by this specification</span></a> <li><a href="#index-defined-elsewhere"><span class="secno"></span> <span class="content">Terms defined by reference</span></a> </ol> <li> <a href="#references"><span class="secno"></span> <span class="content">References</span></a> <ol class="toc"> <li><a href="#normative"><span class="secno"></span> <span class="content">Normative References</span></a> <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a> </ol> <li><a href="#issues-index"><span class="secno"></span> <span class="content">Issues Index</span></a> </ol> </nav> <main> <h2 class="heading settled" data-level="1" id="intro"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#intro"></a></h2> <p><em>This section is not normative.</em></p> <p class="note" role="note"><span class="marker">Note:</span> This section is a stub and needs to be expanded.</p> <p>Authors frequently need to set a property to different values based on the relation between certain values.</p> <h3 class="heading settled" data-level="1.1" id="high-level-custom-properties"><span class="secno">1.1. </span><span class="content">High level custom properties</span><a class="self-link" href="#high-level-custom-properties"></a></h3> <p>A web component may support several custom properties which do not contain a value fragment verbatim, but set several properties across multiple rules indirectly. For example, a `--size` property with values `small`, `medium`, `large`, or an `--alignment` property with values `horizontal` and `vertical`.</p> <h3 class="heading settled" data-level="1.2" id="relation-between-units"><span class="secno">1.2. </span><span class="content">Relation between units of the same type</span><a class="self-link" href="#relation-between-units"></a></h3> <p>Author code often needs to branch based on the relation between different units of the same type.</p> <p>For example:</p> <ul> <li data-md> <p>Comparing viewport and absolute units allows compact one-off viewport dimension media queries</p> <li data-md> <p>Comparing font-relative units and absolute <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#length-value" id="ref-for-length-value"><length></a> units allows authors to apply different styling for small and large font sizes, enhancing readability.</p> </ul> <h3 class="heading settled" data-level="1.3" id="values"><span class="secno">1.3. </span><span class="content">Value Definitions</span><a class="self-link" href="#values"></a></h3> <p>This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from <a data-link-type="biblio" href="#biblio-css2" title="Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification">[CSS2]</a> using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from <a data-link-type="biblio" href="#biblio-css-values-3" title="CSS Values and Units Module Level 3">[CSS-VALUES-3]</a>. Value types not defined in this specification are defined in CSS Values & Units <span title="CSS Values and Units Module Level 3">[CSS-VALUES-3]</span>. Combination with other CSS modules may expand the definitions of these value types.</p> <p>In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the <a data-link-type="dfn" href="https://drafts.csswg.org/css-values-4/#css-wide-keywords" id="ref-for-css-wide-keywords">CSS-wide keywords</a> as their property value. For readability they have not been repeated explicitly.</p> <h2 class="heading settled" data-level="2" id="boolean"><span class="secno">2. </span><span class="content">Boolean data types</span><a class="self-link" href="#boolean"></a></h2> <h3 class="heading settled" data-level="2.1" id="bool-constants"><span class="secno">2.1. </span><span class="content">Boolean constants: <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-true" id="ref-for-valdef-custom-media-true">true</a> and <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-false" id="ref-for-valdef-custom-media-false">false</a></span><a class="self-link" href="#bool-constants"></a></h3> <pre class="def prod highlight"><dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-boolean-constant"><boolean-constant></dfn> = <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="true"><c- s>'true'</c-></dfn> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one">|</a> <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="false"><c- s>'false'</c-></dfn> </pre> <h3 class="heading settled" data-level="2.2" id="condition"><span class="secno">2.2. </span><span class="content">Logical comparisons: The <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition"><condition></a> type</span><a class="self-link" href="#condition"></a></h3> <pre class="def prod"><dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-condition"><condition></dfn> = not <a class="production" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens"><condition-in-parens></a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one①">|</a> <a class="production" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens①"><condition-in-parens></a> [ and <a class="production" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens②"><condition-in-parens></a> ]<a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#mult-zero-plus" id="ref-for-mult-zero-plus">*</a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one②">|</a> <a class="production" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens③"><condition-in-parens></a> [ or <a class="production" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens④"><condition-in-parens></a> ]<a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#mult-zero-plus" id="ref-for-mult-zero-plus①">*</a> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-condition-in-parens"><condition-in-parens></dfn> = ( <a class="production" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition①"><condition></a> ) <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one③">|</a> <a class="production" data-link-type="type" href="#typedef-atomic-condition" id="ref-for-typedef-atomic-condition"><atomic-condition></a> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-atomic-condition"><atomic-condition></dfn> = <a class="production" data-link-type="type" href="#typedef-comparison-operand" id="ref-for-typedef-comparison-operand"><comparison-operand></a> <a class="production" data-link-type="type" href="#typedef-comparison-operator" id="ref-for-typedef-comparison-operator"><comparison-operator></a> <a class="production" data-link-type="type" href="#typedef-comparison-operand" id="ref-for-typedef-comparison-operand①"><comparison-operand></a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one④">|</a> <a class="production" data-link-type="type" href="#typedef-boolean-constant" id="ref-for-typedef-boolean-constant"><boolean-constant></a> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-comparison-operand"><comparison-operand></dfn> = <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#typedef-dimension" id="ref-for-typedef-dimension"><dimension></a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one⑤">|</a> <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#number-value" id="ref-for-number-value"><number></a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one⑥">|</a> <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#percentage-value" id="ref-for-percentage-value"><percentage></a> <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one⑦">|</a> <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#typedef-ident" id="ref-for-typedef-ident"><ident></a> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-comparison-operator"><comparison-operator></dfn> = [ '=' <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one⑧">|</a> '>=' <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one⑨">|</a> '>' <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one①⓪">|</a> '<' <a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-one" id="ref-for-comb-one①①">|</a> '<=' ] </pre> <p class="note" role="note"><span class="marker">Note:</span> A future version of this module may expand <a class="production css" data-link-type="type" href="#typedef-comparison-operand" id="ref-for-typedef-comparison-operand②"><comparison-operand></a> to complex types, such as colors.</p> <p><a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition②"><condition></a> values are logical expressions that resolve to a <a class="production css" data-link-type="type" href="#typedef-boolean-constant" id="ref-for-typedef-boolean-constant①"><boolean-constant></a> by performing simple comparisons and following basic boolean operators. When using `and` or `or` operators, precedence must be enforced with parentheses. The `not` operator does not require this, and has higher precedence than `and` and `or`.</p> <p>Each of these grammar terms is associated with a boolean result, as follows:</p> <dl> <dt data-md><a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition③"><condition></a> <dt data-md><a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens⑤"><condition-in-parens></a> <dd data-md> <p>The result is the result of the child subexpression.</p> <dt data-md>not <a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens⑥"><condition-in-parens></a> <dd data-md> <p>The result is the negation of the <a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens⑦"><condition-in-parens></a> term. The negation of unknown is unknown.</p> <dt data-md><a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens⑧"><condition-in-parens></a> [ and <span class="production" id="ref-for-typedef-condition-in-parens⑨"><condition-in-parens></span> ]* <dd data-md> <p>The result is true if all of the <a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens①⓪"><condition-in-parens></a> child terms are true, false if at least one of the <span class="production" id="ref-for-typedef-condition-in-parens①①"><condition-in-parens></span> is false, and unknown otherwise.</p> <dt data-md><a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens①②"><condition-in-parens></a> [ or <span class="production" id="ref-for-typedef-condition-in-parens①③"><condition-in-parens></span> ]* <dd data-md> <p>The result is false if all of the <a class="production css" data-link-type="type" href="#typedef-condition-in-parens" id="ref-for-typedef-condition-in-parens①④"><condition-in-parens></a> child terms are false, true if at least one of the <span class="production" id="ref-for-typedef-condition-in-parens①⑤"><condition-in-parens></span> is true, and unknown otherwise.</p> </dl> <p>These rules are consistent with the way conditions are resolved in <a data-link-type="biblio" href="#biblio-css-conditional-3" title="CSS Conditional Rules Module Level 3">[css-conditional-3]</a>.</p> <p class="issue" id="issue-2e2ac7ab"><a class="self-link" href="#issue-2e2ac7ab"></a> Together with this, there are currently 3 specs (<a data-link-type="biblio" href="#biblio-css-conditional-3" title="CSS Conditional Rules Module Level 3">[css-conditional-3]</a>, <a data-link-type="biblio" href="#biblio-mediaqueries-4" title="Media Queries Level 4">[mediaqueries-4]</a>) using boolean operators, and two defining how they work (<span title="CSS Conditional Rules Module Level 3">[css-conditional-3]</span> and this). Ideally, this should be defined in one place, and cited everywhere else.</p> <p>Both <a class="production css" data-link-type="type" href="#typedef-comparison-operand" id="ref-for-typedef-comparison-operand③"><comparison-operand></a> values in <a class="production css" data-link-type="type" href="#typedef-atomic-condition" id="ref-for-typedef-atomic-condition①"><atomic-condition></a> need to be of the same type. If they are not, the entire condition becomes an <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="invalid-condition">invalid condition</dfn> and evaluates to unknown.</p> <p>These operations are only defined on <a data-link-type="dfn" href="https://drafts.csswg.org/css-cascade-5/#computed-value" id="ref-for-computed-value">computed values</a>. (As a result, it is not necessary to define, for example, how to compare a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#length-value" id="ref-for-length-value①"><length></a> value of <span class="css">15pt</span> with <span class="css">5em</span> since such values will be resolved to their <a data-link-type="dfn" href="https://drafts.csswg.org/css-values-4/#canonical-unit" id="ref-for-canonical-unit">canonical unit</a> before being passed to any of the above procedures.)</p> <div class="example" id="example-e8d32dd8"><a class="self-link" href="#example-e8d32dd8"></a> For example, <span class="css">5px > 4deg</span> is an invalid condition because the first operand is a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#length-value" id="ref-for-length-value②"><length></a> and the second is an <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-values-4/#angle-value" id="ref-for-angle-value"><angle></a>. </div> <p>The host syntax defines how relative values (such as percentages or em units) are resolved in <a class="production css" data-link-type="type" href="#typedef-comparison-operand" id="ref-for-typedef-comparison-operand④"><comparison-operand></a>. When <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition④"><condition></a> is used in a declaration, these relative values resolve in the same way as regular values in the declaration property.</p> <p class="note" role="note"><span class="marker">Note:</span> Why are we using <span class="css">=</span> for equality and not ':' as is established in <a data-link-type="biblio" href="#biblio-css-conditional-4" title="CSS Conditional Rules Module Level 4">[css-conditional-4]</a> already? Because a lot of third party code (syntax highlighters etc) assumes that colons separate declarations and would break. Also, `foo: bar` establishes a key-value pair, whereas in equality comparisons the two operands are of equal weight, and do not establish a key-value pair.</p> <p class="issue" id="issue-788c09cc"><a class="self-link" href="#issue-788c09cc"></a> Do we need a "not equals" operator or is 'not(op1 = op2)' sufficient?</p> <p>The <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition⑤"><condition></a> is resolved at computed value time, though its calculation tree may be simplified earlier.</p> <div class="example" id="example-86c587ad"><a class="self-link" href="#example-86c587ad"></a> For example, <span class="css">(5px > 4px) and (1em = 2em)</span> can be simplified to <span class="css">(true) and (false)</span> and then to <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-false" id="ref-for-valdef-custom-media-false①">false</a> at parse time and serialized as such. </div> <h4 class="heading settled" data-level="2.2.1" id="condition-computed-value"><span class="secno">2.2.1. </span><span class="content"> Computed Value</span><a class="self-link" href="#condition-computed-value"></a></h4> <p>The <a data-link-type="dfn" href="https://drafts.csswg.org/css-cascade-5/#computed-value" id="ref-for-computed-value①">computed value</a> of a <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition⑥"><condition></a> value is its <a data-link-type="dfn" href="https://drafts.csswg.org/css-values-4/#calculation-tree" id="ref-for-calculation-tree">calculation tree</a> simplified, using all the information available at <span id="ref-for-computed-value②">computed value</span> time. (Such as the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-values-4/#em" id="ref-for-em">em</a> to <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-values-4/#px" id="ref-for-px">px</a> ratio, how to resolve percentages etc.)</p> <p>Where percentages are not resolved at computed-value time, they are not resolved in <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition⑦"><condition></a>.</p> <p>The <a data-link-type="dfn" href="https://drafts.csswg.org/css-values-4/#calculation-tree" id="ref-for-calculation-tree①">calculation tree</a> is again simplified at <a data-link-type="dfn" href="https://drafts.csswg.org/css-cascade-5/#used-value" id="ref-for-used-value">used value</a> time; with <span id="ref-for-used-value①">used value</span> time information, a <a class="production css" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition⑧"><condition></a> always simplifies down to a single <a class="production css" data-link-type="type" href="#typedef-boolean-constant" id="ref-for-typedef-boolean-constant②"><boolean-constant></a>.</p> <p class="issue" id="issue-ed70d1d5"><a class="self-link" href="#issue-ed70d1d5"></a> Define these concepts for comparisons (currently they point to calc())</p> <h2 class="heading settled" data-level="3" id="if"><span class="secno">3. </span><span class="content">Inline conditionals: The <a class="css" data-link-type="maybe" href="#funcdef-if" id="ref-for-funcdef-if">if()</a> function</span><a class="self-link" href="#if"></a></h2> <p>The <dfn class="dfn-paneled css" data-dfn-type="function" data-export id="funcdef-if">if()</dfn> function allows authors to set a property value (or parts thereof) to different values based on certain conditions.</p> <pre class="def prod highlight"><a class="production" data-link-type="function" href="#funcdef-if" id="ref-for-funcdef-if①"><<c- nf>if</c-><c- p>()</c->></a> = <c- nf>if</c-><c- p>(</c-> <a class="production" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition⑨"><condition></a><a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-comma" id="ref-for-comb-comma"><c- p>,</c-></a> <a class="production" data-link-type="type" href="#typedef-consequent" id="ref-for-typedef-consequent"><consequent></a><a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#comb-comma" id="ref-for-comb-comma①"><c- p>,</c-></a> <a class="production" data-link-type="type" href="#typedef-antecedent" id="ref-for-typedef-antecedent"><antecedent></a><a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#mult-opt" id="ref-for-mult-opt">?</a> <c- p>)</c-> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-consequent"><consequent></dfn> = <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value" id="ref-for-typedef-declaration-value"><declaration-value></a> <dfn class="dfn-paneled" data-dfn-type="type" data-export id="typedef-antecedent"><antecedent></dfn> = <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value" id="ref-for-typedef-declaration-value①"><declaration-value></a> </pre> <p class="issue" id="issue-bd13289d"><a class="self-link" href="#issue-bd13289d"></a> How can authors specify consequents or antecedents that include commas? Alternative syntax that addresses this, though may be hard to read when consequent/antecedent are keywords:</p> <pre class="def prod highlight"><a class="production" data-link-type="function" href="#funcdef-if" id="ref-for-funcdef-if②"><<c- nf>if</c-><c- p>()</c->></a> = <c- nf>if</c-><c- p>(</c-> <a class="production" data-link-type="type" href="#typedef-condition" id="ref-for-typedef-condition①⓪"><condition></a> then <a class="production" data-link-type="type" href="#typedef-consequent" id="ref-for-typedef-consequent①"><consequent></a> <c- p>[</c->else <a class="production" data-link-type="type" href="#typedef-antecedent" id="ref-for-typedef-antecedent①"><antecedent></a><c- p>]</c-><a data-link-type="grammar" href="https://drafts.csswg.org/css-values-4/#mult-opt" id="ref-for-mult-opt①">?</a><c- p>)</c-> <a class="production" data-link-type="type" href="#typedef-consequent" id="ref-for-typedef-consequent②"><consequent></a> = <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value" id="ref-for-typedef-declaration-value②"><declaration-value></a> <a class="production" data-link-type="type" href="#typedef-antecedent" id="ref-for-typedef-antecedent②"><antecedent></a> = <a class="production" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value" id="ref-for-typedef-declaration-value③"><declaration-value></a> </pre> <div class="example" id="example-1e69b0e1"> <a class="self-link" href="#example-1e69b0e1"></a> Authors can write inline media queries by comparing viewport and absolute units: <pre class="highlight"><c- k>flex-flow</c-><c- p>:</c-> <c- nf>if</c-><c- p>(</c-><c- m>100</c-><c- k>vw</c-> > <c- m>500</c-><c- k>px</c-><c- p>,</c-> row<c- p>,</c-> column<c- p>);</c-></pre> </div> <p>When <a class="production css" data-link-type="type" href="#typedef-antecedent" id="ref-for-typedef-antecedent③"><antecedent></a> is omitted, it defaults to ' ' (empty value).</p> <div class="example" id="example-f38b7b18"> <a class="self-link" href="#example-f38b7b18"></a> This allows authors to use conditionals to toggle certain parts of a value and even "compose" a property value from a series of conditionals: <pre class="highlight"><c- k>background</c-><c- p>:</c-> <c- nf>if</c-><c- p>(</c-><c- nf>var</c-><c- p>(</c->--raised<c- p>)</c-> = on<c- p>,</c-> <c- nf>linear-gradient</c-><c- p>(</c->white<c- p>,</c-> transparent<c- p>))</c-> <c- nf>hsl</c-><c- p>(</c-><c- m>200</c-> <c- m>100</c-><c- k>%</c-> <c- m>50</c-><c- k>%</c-><c- p>);</c-></pre> </div> <div class="example" id="example-972eb999"> <a class="self-link" href="#example-972eb999"></a> This also allows authors to write multiple branches for the same value side by side instead of deeply nesting them: <pre class="highlight"><c- k>font-size</c-><c- p>:</c-> <c- nf>if</c-><c- p>(</c-><c- nf>var</c-><c- p>(</c->--size<c- p>)</c-> = small<c- p>,</c-> <c- m>2</c-><c- k>em</c-><c- p>)</c-> <c- nf>if</c-><c- p>(</c-><c- nf>var</c-><c- p>(</c->--size<c- p>)</c-> = medium<c- p>,</c-> <c- m>3</c-><c- k>em</c-><c- p>)</c-> <c- nf>if</c-><c- p>(</c-><c- nf>var</c-><c- p>(</c->--size<c- p>)</c-> = large<c- p>,</c-> <c- m>5</c-><c- k>em</c-><c- p>)</c-> </pre> </div> <p>If after substitution of all <a class="css" data-link-type="maybe" href="#funcdef-if" id="ref-for-funcdef-if③">if()</a> values in a property value, the resulting declaration is invalid, the property containing the <span class="css" id="ref-for-funcdef-if④">if()</span> function is <a data-link-type="dfn" href="https://drafts.csswg.org/css-values-5/#invalid-at-computed-value-time" id="ref-for-invalid-at-computed-value-time">invalid at computed-value time</a>.</p> <p>When <a class="css" data-link-type="maybe" href="#funcdef-if" id="ref-for-funcdef-if⑤">if()</a> is used in shorthands, it has the same <a href="../css-variables/#variables-in-shorthands">behavior</a> as the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-variables-2/#funcdef-var" id="ref-for-funcdef-var">var()</a> function, for the same reasons.</p> <p class="issue" id="issue-4928eaeb"><a class="self-link" href="#issue-4928eaeb"></a> How to disambiguate when used in a place where arguments are disambiguated by type? Unlike <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-variables-2/#funcdef-var" id="ref-for-funcdef-var①">var()</a>, this cannot just be resolved at substitution, because we need to be able to interpret the values to compute the condition and perform the substitution accordingly. One way to address this would be to mandate that both <a class="production css" data-link-type="type" href="#typedef-consequent" id="ref-for-typedef-consequent③"><consequent></a> and <a class="production css" data-link-type="type" href="#typedef-antecedent" id="ref-for-typedef-antecedent④"><antecedent></a> need to be of the same type. How much does that limit use cases?</p> <h2 class="heading settled" data-level="4" id="priv-sec"><span class="secno">4. </span><span class="content">Privacy and Security Considerations</span><a class="self-link" href="#priv-sec"></a></h2> <p>This specification defines a purely author-level mechanism for specifying conditionals on styling information within a page they control. As such, there are no new privacy considerations.</p> </main> <h2 class="no-ref no-num heading settled" id="w3c-conformance"><span class="content"> Conformance</span><a class="self-link" href="#w3c-conformance"></a></h2> <h3 class="no-ref heading settled" id="w3c-conventions"><span class="content"> Document conventions</span><a class="self-link" href="#w3c-conventions"></a></h3> <p>Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification. </p> <p>All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. <a data-link-type="biblio" href="#biblio-rfc2119" title="Key words for use in RFCs to Indicate Requirement Levels">[RFC2119]</a></p> <p>Examples in this specification are introduced with the words “for example” or are set apart from the normative text with <code class="highlight">class=<c- s>"example"</c-></code>, like this: </p> <div class="example" id="w3c-example"> <a class="self-link" href="#w3c-example"></a> <p>This is an example of an informative example.</p> </div> <p>Informative notes begin with the word “Note” and are set apart from the normative text with <code class="highlight">class=<c- s>"note"</c-></code>, like this: </p> <p class="note" role="note">Note, this is an informative note.</p> <p>Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <code class="highlight"><strong class=<c- s>"advisement"</c->></code>, like this: <strong class="advisement"> UAs MUST provide an accessible alternative. </strong></p> <h3 class="no-ref heading settled" id="w3c-conformance-classes"><span class="content"> Conformance classes</span><a class="self-link" href="#w3c-conformance-classes"></a></h3> <p>Conformance to this specification is defined for three conformance classes: </p> <dl> <dt>style sheet <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#style-sheet">CSS style sheet</a>. <dt>renderer <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#user-agent">UA</a> that interprets the semantics of a style sheet and renders documents that use them. <dt>authoring tool <dd>A <a href="http://www.w3.org/TR/CSS21/conform.html#user-agent">UA</a> that writes a style sheet. </dl> <p>A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module. </p> <p>A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.) </p> <p>An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module. </p> <h3 class="no-ref heading settled" id="w3c-partial"><span class="content"> Partial implementations</span><a class="self-link" href="#w3c-partial"></a></h3> <p>So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers <strong>must</strong> treat as invalid (and <a href="http://www.w3.org/TR/CSS21/conform.html#ignore">ignore as appropriate</a>) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents <strong>must not</strong> selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.</p> <h4 class="heading settled" id="w3c-conform-future-proofing"><span class="content"> Implementations of Unstable and Proprietary Features</span><a class="self-link" href="#w3c-conform-future-proofing"></a></h4> <p>To avoid clashes with future stable CSS features, the CSSWG recommends <a href="http://www.w3.org/TR/CSS/#future-proofing">following best practices</a> for the implementation of <a href="http://www.w3.org/TR/CSS/#unstable">unstable</a> features and <a href="http://www.w3.org/TR/CSS/#proprietary-extension">proprietary extensions</a> to CSS. </p> <h3 class="no-ref heading settled" id="w3c-testing"><span class="content"> Non-experimental implementations</span><a class="self-link" href="#w3c-testing"></a></h3> <p>Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec. </p> <p>To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group. </p> <p>Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at <a href="http://www.w3.org/Style/CSS/Test/">http://www.w3.org/Style/CSS/Test/</a>. Questions should be directed to the <a href="http://lists.w3.org/Archives/Public/public-css-testsuite">public-css-testsuite@w3.org</a> mailing list.</p> <script src="https://www.w3.org/scripts/TR/2021/fixup.js"></script> <h2 class="no-num no-ref heading settled" id="index"><span class="content">Index</span><a class="self-link" href="#index"></a></h2> <h3 class="no-num no-ref heading settled" id="index-defined-here"><span class="content">Terms defined by this specification</span><a class="self-link" href="#index-defined-here"></a></h3> <ul class="index"> <li><a href="#typedef-antecedent"><antecedent></a><span>, in § 3</span> <li><a href="#typedef-atomic-condition"><atomic-condition></a><span>, in § 2.2</span> <li><a href="#typedef-boolean-constant"><boolean-constant></a><span>, in § 2.1</span> <li><a href="#typedef-comparison-operand"><comparison-operand></a><span>, in § 2.2</span> <li><a href="#typedef-comparison-operator"><comparison-operator></a><span>, in § 2.2</span> <li><a href="#typedef-condition"><condition></a><span>, in § 2.2</span> <li><a href="#typedef-condition-in-parens"><condition-in-parens></a><span>, in § 2.2</span> <li><a href="#typedef-consequent"><consequent></a><span>, in § 3</span> <li><a href="#false">'false'</a><span>, in § 2.1</span> <li><a href="#funcdef-if">if()</a><span>, in § 3</span> <li><a href="#invalid-condition">invalid condition</a><span>, in § 2.2</span> <li><a href="#true">'true'</a><span>, in § 2.1</span> </ul> <h3 class="no-num no-ref heading settled" id="index-defined-elsewhere"><span class="content">Terms defined by reference</span><a class="self-link" href="#index-defined-elsewhere"></a></h3> <ul class="index"> <li> <a data-link-type="biblio">[CSS-CASCADE-5]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="9cd25054">computed value</span> <li><span class="dfn-paneled" id="a4eb3c57">used value</span> </ul> <li> <a data-link-type="biblio">[CSS-SYNTAX-3]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="8144e597"><declaration-value></span> </ul> <li> <a data-link-type="biblio">[CSS-VALUES-4]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="68150e76">*</span> <li><span class="dfn-paneled" id="9f9120ff">,</span> <li><span class="dfn-paneled" id="3559c926"><angle></span> <li><span class="dfn-paneled" id="5751a02c"><dimension></span> <li><span class="dfn-paneled" id="9213678e"><ident></span> <li><span class="dfn-paneled" id="fb030e6c"><length></span> <li><span class="dfn-paneled" id="16310992"><number></span> <li><span class="dfn-paneled" id="15f5b381"><percentage></span> <li><span class="dfn-paneled" id="537cf076">?</span> <li><span class="dfn-paneled" id="80694ce7">calculation tree</span> <li><span class="dfn-paneled" id="17fc5603">canonical unit</span> <li><span class="dfn-paneled" id="358fd6ff">CSS-wide keywords</span> <li><span class="dfn-paneled" id="e8ff0bb4">em</span> <li><span class="dfn-paneled" id="9ddea951">px</span> <li><span class="dfn-paneled" id="6ec67710">|</span> </ul> <li> <a data-link-type="biblio">[CSS-VALUES-5]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="54fd6ed6">invalid at computed-value time</span> </ul> <li> <a data-link-type="biblio">[CSS-VARIABLES-2]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="dbba942a">var()</span> </ul> <li> <a data-link-type="biblio">[MEDIAQUERIES-5]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="f8b3bc81">false</span> <li><span class="dfn-paneled" id="c4484b93">true</span> </ul> </ul> <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2> <h3 class="no-num no-ref heading settled" id="normative"><span class="content">Normative References</span><a class="self-link" href="#normative"></a></h3> <dl> <dt id="biblio-css-cascade-5">[CSS-CASCADE-5] <dd>Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. <a href="https://drafts.csswg.org/css-cascade-5/"><cite>CSS Cascading and Inheritance Level 5</cite></a>. URL: <a href="https://drafts.csswg.org/css-cascade-5/">https://drafts.csswg.org/css-cascade-5/</a> <dt id="biblio-css-syntax-3">[CSS-SYNTAX-3] <dd>Tab Atkins Jr.; Simon Sapin. <a href="https://drafts.csswg.org/css-syntax/"><cite>CSS Syntax Module Level 3</cite></a>. URL: <a href="https://drafts.csswg.org/css-syntax/">https://drafts.csswg.org/css-syntax/</a> <dt id="biblio-css-values-3">[CSS-VALUES-3] <dd>Tab Atkins Jr.; Elika Etemad. <a href="https://drafts.csswg.org/css-values-3/"><cite>CSS Values and Units Module Level 3</cite></a>. URL: <a href="https://drafts.csswg.org/css-values-3/">https://drafts.csswg.org/css-values-3/</a> <dt id="biblio-css-values-4">[CSS-VALUES-4] <dd>Tab Atkins Jr.; Elika Etemad. <a href="https://drafts.csswg.org/css-values-4/"><cite>CSS Values and Units Module Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-values-4/">https://drafts.csswg.org/css-values-4/</a> <dt id="biblio-css-values-5">[CSS-VALUES-5] <dd>Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. <a href="https://drafts.csswg.org/css-values-5/"><cite>CSS Values and Units Module Level 5</cite></a>. URL: <a href="https://drafts.csswg.org/css-values-5/">https://drafts.csswg.org/css-values-5/</a> <dt id="biblio-css-variables-2">[CSS-VARIABLES-2] <dd><a href="https://drafts.csswg.org/css-variables-2/"><cite>CSS Custom Properties for Cascading Variables Module Level 2</cite></a>. Editor's Draft. URL: <a href="https://drafts.csswg.org/css-variables-2/">https://drafts.csswg.org/css-variables-2/</a> <dt id="biblio-css2">[CSS2] <dd>Bert Bos; et al. <a href="https://drafts.csswg.org/css2/"><cite>Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification</cite></a>. URL: <a href="https://drafts.csswg.org/css2/">https://drafts.csswg.org/css2/</a> <dt id="biblio-mediaqueries-5">[MEDIAQUERIES-5] <dd>Dean Jackson; et al. <a href="https://drafts.csswg.org/mediaqueries-5/"><cite>Media Queries Level 5</cite></a>. URL: <a href="https://drafts.csswg.org/mediaqueries-5/">https://drafts.csswg.org/mediaqueries-5/</a> <dt id="biblio-rfc2119">[RFC2119] <dd>S. Bradner. <a href="https://datatracker.ietf.org/doc/html/rfc2119"><cite>Key words for use in RFCs to Indicate Requirement Levels</cite></a>. March 1997. Best Current Practice. URL: <a href="https://datatracker.ietf.org/doc/html/rfc2119">https://datatracker.ietf.org/doc/html/rfc2119</a> </dl> <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3> <dl> <dt id="biblio-css-conditional-3">[CSS-CONDITIONAL-3] <dd>Chris Lilley; David Baron; Elika Etemad. <a href="https://drafts.csswg.org/css-conditional-3/"><cite>CSS Conditional Rules Module Level 3</cite></a>. URL: <a href="https://drafts.csswg.org/css-conditional-3/">https://drafts.csswg.org/css-conditional-3/</a> <dt id="biblio-css-conditional-4">[CSS-CONDITIONAL-4] <dd>David Baron; Elika Etemad; Chris Lilley. <a href="https://drafts.csswg.org/css-conditional-4/"><cite>CSS Conditional Rules Module Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-conditional-4/">https://drafts.csswg.org/css-conditional-4/</a> <dt id="biblio-mediaqueries-4">[MEDIAQUERIES-4] <dd>Florian Rivoal; Tab Atkins Jr.. <a href="https://drafts.csswg.org/mediaqueries-4/"><cite>Media Queries Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/mediaqueries-4/">https://drafts.csswg.org/mediaqueries-4/</a> </dl> <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content">Issues Index</span><a class="self-link" href="#issues-index"></a></h2> <div style="counter-reset:issue"> <div class="issue"> Together with this, there are currently 3 specs (<a data-link-type="biblio" href="#biblio-css-conditional-3" title="CSS Conditional Rules Module Level 3">[css-conditional-3]</a>, <a data-link-type="biblio" href="#biblio-mediaqueries-4" title="Media Queries Level 4">[mediaqueries-4]</a>) using boolean operators, and two defining how they work (<span title="CSS Conditional Rules Module Level 3">[css-conditional-3]</span> and this). Ideally, this should be defined in one place, and cited everywhere else. <a class="issue-return" href="#issue-2e2ac7ab" title="Jump to section">↵</a></div> <div class="issue"> Do we need a "not equals" operator or is 'not(op1 = op2)' sufficient? <a class="issue-return" href="#issue-788c09cc" title="Jump to section">↵</a></div> <div class="issue"> Define these concepts for comparisons (currently they point to calc()) <a class="issue-return" href="#issue-ed70d1d5" title="Jump to section">↵</a></div> <div class="issue"> How can authors specify consequents or antecedents that include commas? Alternative syntax that addresses this, though may be hard to read when consequent/antecedent are keywords: <a class="issue-return" href="#issue-bd13289d" title="Jump to section">↵</a></div> <div class="issue"> How to disambiguate when used in a place where arguments are disambiguated by type? Unlike <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-variables-2/#funcdef-var">var()</a>, this cannot just be resolved at substitution, because we need to be able to interpret the values to compute the condition and perform the substitution accordingly. One way to address this would be to mandate that both <a class="production css" data-link-type="type" href="#typedef-consequent"><consequent></a> and <a class="production css" data-link-type="type" href="#typedef-antecedent"><antecedent></a> need to be of the same type. How much does that limit use cases? <a class="issue-return" href="#issue-4928eaeb" title="Jump to section">↵</a></div> </div> <script>/* Boilerplate: script-dom-helper */ "use strict"; function query(sel) { return document.querySelector(sel); } function queryAll(sel) { return [...document.querySelectorAll(sel)]; } function iter(obj) { if(!obj) return []; var it = obj[Symbol.iterator]; if(it) return it; return Object.entries(obj); } function mk(tagname, attrs, ...children) { const el = document.createElement(tagname); for(const [k,v] of iter(attrs)) { if(k.slice(0,3) == "_on") { const eventName = k.slice(3); el.addEventListener(eventName, v); } else if(k[0] == "_") { // property, not attribute el[k.slice(1)] = v; } else { if(v === false || v == null) { continue; } else if(v === true) { el.setAttribute(k, ""); continue; } else { el.setAttribute(k, v); } } } append(el, children); return el; } /* Create shortcuts for every known HTML element */ [ "a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdo", "big", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame", "frameset", "head", "header", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "meta", "meter", "nav", "nobr", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "pre", "progress", "q", "s", "samp", "script", "section", "select", "small", "source", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "u", "ul", "var", "video", "wbr", "xmp", ].forEach(tagname=>{ mk[tagname] = (...args) => mk(tagname, ...args); }); function* nodesFromChildList(children) { for(const child of children.flat(Infinity)) { if(child instanceof Node) { yield child; } else { yield new Text(child); } } } function append(el, ...children) { for(const child of nodesFromChildList(children)) { if(el instanceof Node) el.appendChild(child); else el.push(child); } return el; } function insertAfter(el, ...children) { for(const child of nodesFromChildList(children)) { el.parentNode.insertBefore(child, el.nextSibling); } return el; } function clearContents(el) { el.innerHTML = ""; return el; } function parseHTML(markup) { if(markup.toLowerCase().trim().indexOf('<!doctype') === 0) { const doc = document.implementation.createHTMLDocument(""); doc.documentElement.innerHTML = markup; return doc; } else { const el = mk.template({}); el.innerHTML = markup; return el.content; } }</script> <script>/* Boilerplate: script-dfn-panel */ "use strict"; { let dfnPanelData = { "15f5b381": {"dfnID":"15f5b381","dfnText":"<percentage>","external":true,"refSections":[{"refs":[{"id":"ref-for-percentage-value"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#percentage-value"}, "16310992": {"dfnID":"16310992","dfnText":"<number>","external":true,"refSections":[{"refs":[{"id":"ref-for-number-value"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#number-value"}, "17fc5603": {"dfnID":"17fc5603","dfnText":"canonical unit","external":true,"refSections":[{"refs":[{"id":"ref-for-canonical-unit"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#canonical-unit"}, "3559c926": {"dfnID":"3559c926","dfnText":"<angle>","external":true,"refSections":[{"refs":[{"id":"ref-for-angle-value"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#angle-value"}, "358fd6ff": {"dfnID":"358fd6ff","dfnText":"CSS-wide keywords","external":true,"refSections":[{"refs":[{"id":"ref-for-css-wide-keywords"}],"title":"1.3. Value Definitions"}],"url":"https://drafts.csswg.org/css-values-4/#css-wide-keywords"}, "537cf076": {"dfnID":"537cf076","dfnText":"?","external":true,"refSections":[{"refs":[{"id":"ref-for-mult-opt"},{"id":"ref-for-mult-opt\u2460"}],"title":"3. Inline conditionals: The if() function"}],"url":"https://drafts.csswg.org/css-values-4/#mult-opt"}, "54fd6ed6": {"dfnID":"54fd6ed6","dfnText":"invalid at computed-value time","external":true,"refSections":[{"refs":[{"id":"ref-for-invalid-at-computed-value-time"}],"title":"3. Inline conditionals: The if() function"}],"url":"https://drafts.csswg.org/css-values-5/#invalid-at-computed-value-time"}, "5751a02c": {"dfnID":"5751a02c","dfnText":"<dimension>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-dimension"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#typedef-dimension"}, "68150e76": {"dfnID":"68150e76","dfnText":"*","external":true,"refSections":[{"refs":[{"id":"ref-for-mult-zero-plus"},{"id":"ref-for-mult-zero-plus\u2460"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#mult-zero-plus"}, "6ec67710": {"dfnID":"6ec67710","dfnText":"|","external":true,"refSections":[{"refs":[{"id":"ref-for-comb-one"}],"title":"2.1. Boolean constants: true and false"},{"refs":[{"id":"ref-for-comb-one\u2460"},{"id":"ref-for-comb-one\u2461"},{"id":"ref-for-comb-one\u2462"},{"id":"ref-for-comb-one\u2463"},{"id":"ref-for-comb-one\u2464"},{"id":"ref-for-comb-one\u2465"},{"id":"ref-for-comb-one\u2466"},{"id":"ref-for-comb-one\u2467"},{"id":"ref-for-comb-one\u2468"},{"id":"ref-for-comb-one\u2460\u24ea"},{"id":"ref-for-comb-one\u2460\u2460"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#comb-one"}, "80694ce7": {"dfnID":"80694ce7","dfnText":"calculation tree","external":true,"refSections":[{"refs":[{"id":"ref-for-calculation-tree"},{"id":"ref-for-calculation-tree\u2460"}],"title":"2.2.1. \nComputed Value"}],"url":"https://drafts.csswg.org/css-values-4/#calculation-tree"}, "8144e597": {"dfnID":"8144e597","dfnText":"<declaration-value>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-declaration-value"},{"id":"ref-for-typedef-declaration-value\u2460"},{"id":"ref-for-typedef-declaration-value\u2461"},{"id":"ref-for-typedef-declaration-value\u2462"}],"title":"3. Inline conditionals: The if() function"}],"url":"https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value"}, "9213678e": {"dfnID":"9213678e","dfnText":"<ident>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-ident"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#typedef-ident"}, "9cd25054": {"dfnID":"9cd25054","dfnText":"computed value","external":true,"refSections":[{"refs":[{"id":"ref-for-computed-value"}],"title":"2.2. Logical comparisons: The <condition> type"},{"refs":[{"id":"ref-for-computed-value\u2460"},{"id":"ref-for-computed-value\u2461"}],"title":"2.2.1. \nComputed Value"}],"url":"https://drafts.csswg.org/css-cascade-5/#computed-value"}, "9ddea951": {"dfnID":"9ddea951","dfnText":"px","external":true,"refSections":[{"refs":[{"id":"ref-for-px"}],"title":"2.2.1. \nComputed Value"}],"url":"https://drafts.csswg.org/css-values-4/#px"}, "9f9120ff": {"dfnID":"9f9120ff","dfnText":",","external":true,"refSections":[{"refs":[{"id":"ref-for-comb-comma"},{"id":"ref-for-comb-comma\u2460"}],"title":"3. Inline conditionals: The if() function"}],"url":"https://drafts.csswg.org/css-values-4/#comb-comma"}, "a4eb3c57": {"dfnID":"a4eb3c57","dfnText":"used value","external":true,"refSections":[{"refs":[{"id":"ref-for-used-value"},{"id":"ref-for-used-value\u2460"}],"title":"2.2.1. \nComputed Value"}],"url":"https://drafts.csswg.org/css-cascade-5/#used-value"}, "c4484b93": {"dfnID":"c4484b93","dfnText":"true","external":true,"refSections":[{"refs":[{"id":"ref-for-valdef-custom-media-true"}],"title":"2.1. Boolean constants: true and false"}],"url":"https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-true"}, "dbba942a": {"dfnID":"dbba942a","dfnText":"var()","external":true,"refSections":[{"refs":[{"id":"ref-for-funcdef-var"},{"id":"ref-for-funcdef-var\u2460"}],"title":"3. Inline conditionals: The if() function"}],"url":"https://drafts.csswg.org/css-variables-2/#funcdef-var"}, "e8ff0bb4": {"dfnID":"e8ff0bb4","dfnText":"em","external":true,"refSections":[{"refs":[{"id":"ref-for-em"}],"title":"2.2.1. \nComputed Value"}],"url":"https://drafts.csswg.org/css-values-4/#em"}, "f8b3bc81": {"dfnID":"f8b3bc81","dfnText":"false","external":true,"refSections":[{"refs":[{"id":"ref-for-valdef-custom-media-false"}],"title":"2.1. Boolean constants: true and false"},{"refs":[{"id":"ref-for-valdef-custom-media-false\u2460"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-false"}, "false": {"dfnID":"false","dfnText":"'false'","external":false,"refSections":[],"url":"#false"}, "fb030e6c": {"dfnID":"fb030e6c","dfnText":"<length>","external":true,"refSections":[{"refs":[{"id":"ref-for-length-value"}],"title":"1.2. Relation between units of the same type"},{"refs":[{"id":"ref-for-length-value\u2460"},{"id":"ref-for-length-value\u2461"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"https://drafts.csswg.org/css-values-4/#length-value"}, "funcdef-if": {"dfnID":"funcdef-if","dfnText":"if()","external":false,"refSections":[{"refs":[{"id":"ref-for-funcdef-if"},{"id":"ref-for-funcdef-if\u2460"},{"id":"ref-for-funcdef-if\u2461"},{"id":"ref-for-funcdef-if\u2462"},{"id":"ref-for-funcdef-if\u2463"},{"id":"ref-for-funcdef-if\u2464"}],"title":"3. Inline conditionals: The if() function"}],"url":"#funcdef-if"}, "invalid-condition": {"dfnID":"invalid-condition","dfnText":"invalid condition","external":false,"refSections":[],"url":"#invalid-condition"}, "true": {"dfnID":"true","dfnText":"'true'","external":false,"refSections":[],"url":"#true"}, "typedef-antecedent": {"dfnID":"typedef-antecedent","dfnText":"<antecedent>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-antecedent"},{"id":"ref-for-typedef-antecedent\u2460"},{"id":"ref-for-typedef-antecedent\u2461"},{"id":"ref-for-typedef-antecedent\u2462"},{"id":"ref-for-typedef-antecedent\u2463"}],"title":"3. Inline conditionals: The if() function"}],"url":"#typedef-antecedent"}, "typedef-atomic-condition": {"dfnID":"typedef-atomic-condition","dfnText":"<atomic-condition>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-atomic-condition"},{"id":"ref-for-typedef-atomic-condition\u2460"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"#typedef-atomic-condition"}, "typedef-boolean-constant": {"dfnID":"typedef-boolean-constant","dfnText":"<boolean-constant>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-boolean-constant"},{"id":"ref-for-typedef-boolean-constant\u2460"}],"title":"2.2. Logical comparisons: The <condition> type"},{"refs":[{"id":"ref-for-typedef-boolean-constant\u2461"}],"title":"2.2.1. \nComputed Value"}],"url":"#typedef-boolean-constant"}, "typedef-comparison-operand": {"dfnID":"typedef-comparison-operand","dfnText":"<comparison-operand>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-comparison-operand"},{"id":"ref-for-typedef-comparison-operand\u2460"},{"id":"ref-for-typedef-comparison-operand\u2461"},{"id":"ref-for-typedef-comparison-operand\u2462"},{"id":"ref-for-typedef-comparison-operand\u2463"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"#typedef-comparison-operand"}, "typedef-comparison-operator": {"dfnID":"typedef-comparison-operator","dfnText":"<comparison-operator>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-comparison-operator"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"#typedef-comparison-operator"}, "typedef-condition": {"dfnID":"typedef-condition","dfnText":"<condition>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-condition"},{"id":"ref-for-typedef-condition\u2460"},{"id":"ref-for-typedef-condition\u2461"},{"id":"ref-for-typedef-condition\u2462"},{"id":"ref-for-typedef-condition\u2463"},{"id":"ref-for-typedef-condition\u2464"}],"title":"2.2. Logical comparisons: The <condition> type"},{"refs":[{"id":"ref-for-typedef-condition\u2465"},{"id":"ref-for-typedef-condition\u2466"},{"id":"ref-for-typedef-condition\u2467"}],"title":"2.2.1. \nComputed Value"},{"refs":[{"id":"ref-for-typedef-condition\u2468"},{"id":"ref-for-typedef-condition\u2460\u24ea"}],"title":"3. Inline conditionals: The if() function"}],"url":"#typedef-condition"}, "typedef-condition-in-parens": {"dfnID":"typedef-condition-in-parens","dfnText":"<condition-in-parens>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-condition-in-parens"},{"id":"ref-for-typedef-condition-in-parens\u2460"},{"id":"ref-for-typedef-condition-in-parens\u2461"},{"id":"ref-for-typedef-condition-in-parens\u2462"},{"id":"ref-for-typedef-condition-in-parens\u2463"},{"id":"ref-for-typedef-condition-in-parens\u2464"},{"id":"ref-for-typedef-condition-in-parens\u2465"},{"id":"ref-for-typedef-condition-in-parens\u2466"},{"id":"ref-for-typedef-condition-in-parens\u2467"},{"id":"ref-for-typedef-condition-in-parens\u2468"},{"id":"ref-for-typedef-condition-in-parens\u2460\u24ea"},{"id":"ref-for-typedef-condition-in-parens\u2460\u2460"},{"id":"ref-for-typedef-condition-in-parens\u2460\u2461"},{"id":"ref-for-typedef-condition-in-parens\u2460\u2462"},{"id":"ref-for-typedef-condition-in-parens\u2460\u2463"},{"id":"ref-for-typedef-condition-in-parens\u2460\u2464"}],"title":"2.2. Logical comparisons: The <condition> type"}],"url":"#typedef-condition-in-parens"}, "typedef-consequent": {"dfnID":"typedef-consequent","dfnText":"<consequent>","external":false,"refSections":[{"refs":[{"id":"ref-for-typedef-consequent"},{"id":"ref-for-typedef-consequent\u2460"},{"id":"ref-for-typedef-consequent\u2461"},{"id":"ref-for-typedef-consequent\u2462"}],"title":"3. Inline conditionals: The if() function"}],"url":"#typedef-consequent"}, }; document.addEventListener("DOMContentLoaded", ()=>{ genAllDfnPanels(); document.body.addEventListener("click", (e) => { // If not handled already, just hide all dfn panels. hideAllDfnPanels(); }); }); window.addEventListener("resize", () => { // Pin any visible dfn panel queryAll(".dfn-panel.on, .dfn-panel.activated").forEach(el=>positionDfnPanel(el)); }); function genAllDfnPanels() { for(const panelData of Object.values(dfnPanelData)) { const dfnID = panelData.dfnID; const dfn = document.getElementById(dfnID); if(!dfn) { console.log(`Can't find dfn#${dfnID}.`, panelData); continue; } dfn.panelData = panelData; insertDfnPopupAction(dfn); } } function genDfnPanel(dfn, { dfnID, url, dfnText, refSections, external }) { const dfnPanel = mk.aside({ class: "dfn-panel on", id: `infopanel-for-${dfnID}`, "data-for": dfnID, "aria-labelled-by":`infopaneltitle-for-${dfnID}`, }, mk.span({id:`infopaneltitle-for-${dfnID}`, style:"display:none"}, `Info about the '${dfnText}' ${external?"external":""} reference.`), mk.a({href:url, class:"dfn-link"}, url), refSections.length == 0 ? [] : mk.b({}, "Referenced in:"), mk.ul({}, ...refSections.map(section=> mk.li({}, ...section.refs.map((ref, refI)=> [ mk.a({ href: `#${ref.id}` }, (refI == 0) ? section.title : `(${refI + 1})` ), " ", ] ), ), ), ), genLinkingSyntaxes(dfn), ); dfnPanel.addEventListener('click', (event) => { if (event.target.nodeName == 'A') { scrollToTargetAndHighlight(event); pinDfnPanel(dfnPanel); } event.stopPropagation(); refocusOnTarget(event); }); dfnPanel.addEventListener('keydown', (event) => { if(event.keyCode == 27) { // Escape key hideDfnPanel({dfnPanel}); event.stopPropagation(); event.preventDefault(); } }); dfnPanel.dfn = dfn; dfn.dfnPanel = dfnPanel; return dfnPanel; } function hideAllDfnPanels() { // Delete the currently-active dfn panel. queryAll(".dfn-panel").forEach(dfnPanel=>hideDfnPanel({dfnPanel})); } function showDfnPanel(dfn) { hideAllDfnPanels(); // Only display one at a time. dfn.setAttribute("aria-expanded", "true"); const dfnPanel = genDfnPanel(dfn, dfn.panelData); // Give the dfn a unique tabindex, and then // give all the tabbable panel bits successive indexes. let tabIndex = 100; dfn.tabIndex = tabIndex++; const tabbable = dfnPanel.querySelectorAll(":is(a, button)"); for (const el of tabbable) { el.tabIndex = tabIndex++; } append(document.body, dfnPanel); positionDfnPanel(dfnPanel); } function positionDfnPanel(dfnPanel) { const dfn = dfnPanel.dfn; const dfnPos = getBounds(dfn); dfnPanel.style.top = dfnPos.bottom + "px"; dfnPanel.style.left = dfnPos.left + "px"; const panelPos = dfnPanel.getBoundingClientRect(); const panelMargin = 8; const maxRight = document.body.parentNode.clientWidth - panelMargin; if (panelPos.right > maxRight) { const overflowAmount = panelPos.right - maxRight; const newLeft = Math.max(panelMargin, dfnPos.left - overflowAmount); dfnPanel.style.left = newLeft + "px"; } } function pinDfnPanel(dfnPanel) { // Switch it to "activated" state, which pins it. dfnPanel.classList.add("activated"); dfnPanel.style.position = "fixed"; dfnPanel.style.left = null; dfnPanel.style.top = null; } function hideDfnPanel({dfn, dfnPanel}) { if(!dfnPanel) dfnPanel = dfn.dfnPanel; if(!dfn) dfn = dfnPanel.dfn; dfn.dfnPanel = undefined; dfnPanel.dfn = undefined; dfn.setAttribute("aria-expanded", "false"); dfn.tabIndex = undefined; dfnPanel.remove() } function toggleDfnPanel(dfn) { if(dfn.dfnPanel) { hideDfnPanel(dfn); } else { showDfnPanel(dfn); } } function insertDfnPopupAction(dfn) { dfn.setAttribute('role', 'button'); dfn.setAttribute('aria-expanded', 'false') dfn.tabIndex = 0; dfn.classList.add('has-dfn-panel'); dfn.addEventListener('click', (event) => { toggleDfnPanel(dfn); event.stopPropagation(); }); dfn.addEventListener('keypress', (event) => { const kc = event.keyCode; // 32->Space, 13->Enter if(kc == 32 || kc == 13) { toggleDfnPanel(dfn); event.stopPropagation(); event.preventDefault(); } }); } function refocusOnTarget(event) { const target = event.target; setTimeout(() => { // Refocus on the event.target element. // This is needed after browser scrolls to the destination. target.focus(); }); } // TODO: shared util // Returns the root-level absolute position {left and top} of element. function getBounds(el, relativeTo=document.body) { const relativeRect = relativeTo.getBoundingClientRect(); const elRect = el.getBoundingClientRect(); const top = elRect.top - relativeRect.top; const left = elRect.left - relativeRect.left; return { top, left, bottom: top + elRect.height, right: left + elRect.width, } } function scrollToTargetAndHighlight(event) { let hash = event.target.hash; if (hash) { hash = decodeURIComponent(hash.substring(1)); const dest = document.getElementById(hash); if (dest) { dest.classList.add('highlighted'); setTimeout(() => dest.classList.remove('highlighted'), 1000); } } } // Functions, divided by link type, that wrap an autolink's // contents with the appropriate outer syntax. // Alternately, a string naming another type they format // the same as. function needsFor(type) { switch(type) { case "descriptor": case "value": case "element-attr": case "attr-value": case "element-state": case "method": case "constructor": case "argument": case "attribute": case "const": case "dict-member": case "event": case "enum-value": case "stringifier": case "serializer": case "iterator": case "maplike": case "setlike": case "state": case "mode": case "context": case "facet": return true; default: return false; } } function refusesFor(type) { switch(type) { case "property": case "element": case "interface": case "namespace": case "callback": case "dictionary": case "enum": case "exception": case "typedef": case "http-header": case "permission": return true; default: return false; } } function linkFormatterFromType(type) { switch(type) { case 'scheme': case 'permission': case 'dfn': return (text) => `[=${text}=]`; case 'abstract-op': return (text) => `[\$${text}\$]`; case 'function': case 'at-rule': case 'selector': case 'value': return (text) => `''${text}''`; case 'http-header': return (text) => `[:${text}:]`; case 'interface': case 'constructor': case 'method': case 'argument': case 'attribute': case 'callback': case 'dictionary': case 'dict-member': case 'enum': case 'enum-value': case 'exception': case 'const': case 'typedef': case 'stringifier': case 'serializer': case 'iterator': case 'maplike': case 'setlike': case 'extended-attribute': case 'event': case 'idl': return (text) => `{{${text}}}`; case 'element-state': case 'element-attr': case 'attr-value': case 'element': return (element) => `<{${element}}>`; case 'grammar': return (text) => `${text} (within a <pre class=prod>)`; case 'type': return (text)=> `<<${text}>>`; case 'descriptor': case 'property': return (text) => `'${text}'`; default: return; }; }; function genLinkingSyntaxes(dfn) { if(dfn.tagName != "DFN") return; const type = dfn.getAttribute('data-dfn-type'); if(!type) { console.log(`<dfn> doesn't have a data-dfn-type:`, dfn); return []; } // Return a function that wraps link text based on the type const linkFormatter = linkFormatterFromType(type); if(!linkFormatter) { console.log(`<dfn> has an unknown data-dfn-type:`, dfn); return []; } let ltAlts; if(dfn.hasAttribute('data-lt')) { ltAlts = dfn.getAttribute('data-lt') .split("|") .map(x=>x.trim()); } else { ltAlts = [dfn.textContent.trim()]; } if(type == "type") { // lt of "<foo>", but "foo" is the interior; // <<foo/bar>> is how you write it with a for, // not <foo/<bar>> or whatever. for(var i = 0; i < ltAlts.length; i++) { const lt = ltAlts[i]; const match = /<(.*)>/.exec(lt); if(match) { ltAlts[i] = match[1]; } } } let forAlts; if(dfn.hasAttribute('data-dfn-for')) { forAlts = dfn.getAttribute('data-dfn-for') .split(",") .map(x=>x.trim()); } else { forAlts = ['']; } let linkingSyntaxes = []; if(!needsFor(type)) { for(const lt of ltAlts) { linkingSyntaxes.push(linkFormatter(lt)); } } if(!refusesFor(type)) { for(const f of forAlts) { linkingSyntaxes.push(linkFormatter(`${f}/${ltAlts[0]}`)) } } return [ mk.b({}, 'Possible linking syntaxes:'), mk.ul({}, ...linkingSyntaxes.map(link => { const copyLink = async () => await navigator.clipboard.writeText(link); return mk.li({}, mk.div({ class: 'link-item' }, mk.button({ class: 'copy-icon', title: 'Copy', type: 'button', _onclick: copyLink, tabindex: 0, }, mk.span({ class: 'icon' }) ), mk.span({}, link) ) ); }) ) ]; } } </script> <script>/* Boilerplate: script-link-titles */ "use strict"; { let linkTitleData = { "https://drafts.csswg.org/css-values-4/#angle-value": "Expands to: deg | grad | rad | turn", "https://drafts.csswg.org/css-values-4/#length-value": "Expands to: advance measure | cap | ch | cm | dvb | dvh | dvi | dvmax | dvmin | dvw | em | ex | ic | in | lh | lvb | lvh | lvi | lvmax | lvmin | lvw | mm | pc | pt | px | rcap | rch | rem | rex | ric | rlh | svb | svh | svi | svmax | svmin | svw | vb | vh | vi | vmax | vmin | vw", }; function setTypeTitles() { for(let el of document.querySelectorAll("a[href]")) { if(el.href in linkTitleData && !el.hasAttribute("title")) { el.setAttribute("title", linkTitleData[el.href]); } } } document.addEventListener("DOMContentLoaded", setTypeTitles); } </script> <script>/* Boilerplate: script-ref-hints */ "use strict"; { let refsData = { "#funcdef-if": {"displayText":"if()","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"if()","type":"function","url":"#funcdef-if"}, "#typedef-antecedent": {"displayText":"<antecedent>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<antecedent>","type":"type","url":"#typedef-antecedent"}, "#typedef-atomic-condition": {"displayText":"<atomic-condition>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<atomic-condition>","type":"type","url":"#typedef-atomic-condition"}, "#typedef-boolean-constant": {"displayText":"<boolean-constant>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<boolean-constant>","type":"type","url":"#typedef-boolean-constant"}, "#typedef-comparison-operand": {"displayText":"<comparison-operand>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<comparison-operand>","type":"type","url":"#typedef-comparison-operand"}, "#typedef-comparison-operator": {"displayText":"<comparison-operator>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<comparison-operator>","type":"type","url":"#typedef-comparison-operator"}, "#typedef-condition": {"displayText":"<condition>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<condition>","type":"type","url":"#typedef-condition"}, "#typedef-condition-in-parens": {"displayText":"<condition-in-parens>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<condition-in-parens>","type":"type","url":"#typedef-condition-in-parens"}, "#typedef-consequent": {"displayText":"<consequent>","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-conditional-values","spec":"css-conditional-values-1","status":"local","text":"<consequent>","type":"type","url":"#typedef-consequent"}, "https://drafts.csswg.org/css-cascade-5/#computed-value": {"displayText":"computed value","export":true,"for_":[],"level":"5","normative":true,"shortname":"css-cascade","spec":"css-cascade-5","status":"current","text":"computed value","type":"dfn","url":"https://drafts.csswg.org/css-cascade-5/#computed-value"}, "https://drafts.csswg.org/css-cascade-5/#used-value": {"displayText":"used value","export":true,"for_":[],"level":"5","normative":true,"shortname":"css-cascade","spec":"css-cascade-5","status":"current","text":"used value","type":"dfn","url":"https://drafts.csswg.org/css-cascade-5/#used-value"}, "https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value": {"displayText":"<declaration-value>","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"<declaration-value>","type":"type","url":"https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value"}, "https://drafts.csswg.org/css-values-4/#angle-value": {"displayText":"<angle>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<angle>","type":"type","url":"https://drafts.csswg.org/css-values-4/#angle-value"}, "https://drafts.csswg.org/css-values-4/#calculation-tree": {"displayText":"calculation tree","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"calculation tree","type":"dfn","url":"https://drafts.csswg.org/css-values-4/#calculation-tree"}, "https://drafts.csswg.org/css-values-4/#canonical-unit": {"displayText":"canonical unit","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"canonical unit","type":"dfn","url":"https://drafts.csswg.org/css-values-4/#canonical-unit"}, "https://drafts.csswg.org/css-values-4/#comb-comma": {"displayText":",","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":",","type":"grammar","url":"https://drafts.csswg.org/css-values-4/#comb-comma"}, "https://drafts.csswg.org/css-values-4/#comb-one": {"displayText":"|","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"|","type":"grammar","url":"https://drafts.csswg.org/css-values-4/#comb-one"}, "https://drafts.csswg.org/css-values-4/#css-wide-keywords": {"displayText":"CSS-wide keywords","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"css-wide keywords","type":"dfn","url":"https://drafts.csswg.org/css-values-4/#css-wide-keywords"}, "https://drafts.csswg.org/css-values-4/#em": {"displayText":"em","export":true,"for_":["<length>"],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"em","type":"value","url":"https://drafts.csswg.org/css-values-4/#em"}, "https://drafts.csswg.org/css-values-4/#length-value": {"displayText":"<length>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<length>","type":"type","url":"https://drafts.csswg.org/css-values-4/#length-value"}, "https://drafts.csswg.org/css-values-4/#mult-opt": {"displayText":"?","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"?","type":"grammar","url":"https://drafts.csswg.org/css-values-4/#mult-opt"}, "https://drafts.csswg.org/css-values-4/#mult-zero-plus": {"displayText":"*","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"*","type":"grammar","url":"https://drafts.csswg.org/css-values-4/#mult-zero-plus"}, "https://drafts.csswg.org/css-values-4/#number-value": {"displayText":"<number>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<number>","type":"type","url":"https://drafts.csswg.org/css-values-4/#number-value"}, "https://drafts.csswg.org/css-values-4/#percentage-value": {"displayText":"<percentage>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<percentage>","type":"type","url":"https://drafts.csswg.org/css-values-4/#percentage-value"}, "https://drafts.csswg.org/css-values-4/#px": {"displayText":"px","export":true,"for_":["<length>"],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"px","type":"value","url":"https://drafts.csswg.org/css-values-4/#px"}, "https://drafts.csswg.org/css-values-4/#typedef-dimension": {"displayText":"<dimension>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<dimension>","type":"type","url":"https://drafts.csswg.org/css-values-4/#typedef-dimension"}, "https://drafts.csswg.org/css-values-4/#typedef-ident": {"displayText":"<ident>","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-values","spec":"css-values-4","status":"current","text":"<ident>","type":"type","url":"https://drafts.csswg.org/css-values-4/#typedef-ident"}, "https://drafts.csswg.org/css-values-5/#invalid-at-computed-value-time": {"displayText":"invalid at computed-value time","export":true,"for_":[],"level":"5","normative":true,"shortname":"css-values","spec":"css-values-5","status":"current","text":"invalid at computed-value time","type":"dfn","url":"https://drafts.csswg.org/css-values-5/#invalid-at-computed-value-time"}, "https://drafts.csswg.org/css-variables-2/#funcdef-var": {"displayText":"var()","export":true,"for_":[],"level":"2","normative":true,"shortname":"css-variables","spec":"css-variables-2","status":"current","text":"var()","type":"function","url":"https://drafts.csswg.org/css-variables-2/#funcdef-var"}, "https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-false": {"displayText":"false","export":true,"for_":["@custom-media"],"level":"5","normative":true,"shortname":"mediaqueries","spec":"mediaqueries-5","status":"current","text":"false","type":"value","url":"https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-false"}, "https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-true": {"displayText":"true","export":true,"for_":["@custom-media"],"level":"5","normative":true,"shortname":"mediaqueries","spec":"mediaqueries-5","status":"current","text":"true","type":"value","url":"https://drafts.csswg.org/mediaqueries-5/#valdef-custom-media-true"}, }; function mkRefHint(link, ref) { const linkText = link.textContent; let dfnTextElements = ''; if (ref.displayText.toLowerCase() != linkText.toLowerCase()) { // Give the original term if it's being displayed in a different way. // But allow casing differences, they're insignificant. dfnTextElements = mk.li({}, mk.b({}, "Term: "), mk.span({}, ref.displayText) ); } const forList = ref.for_; let forListElements; if(forList.length == 0) { forListElements = []; } else if(forList.length == 1) { forListElements = mk.li({}, mk.b({}, "For: "), mk.span({}, forList[0]), ); } else { forListElements = mk.li({}, mk.b({}, "For: "), mk.ul({}, ...forList.map(forItem => mk.li({}, mk.span({}, forItem) ), ), ), ); } const url = ref.url; const safeUrl = encodeURIComponent(url); const hintPanel = mk.aside({ class: "ref-hint", id: `ref-hint-for-${safeUrl}`, "data-for": url, "aria-labelled-by": `ref-hint-for-${safeUrl}`, }, mk.ul({}, dfnTextElements, mk.li({}, mk.b({}, "URL: "), mk.a({ href: url, class: "ref" }, url), ), mk.li({}, mk.b({}, "Type: "), mk.span({}, `${ref.type}`), ), mk.li({}, mk.b({}, "Spec: "), mk.span({}, `${ref.spec ? ref.spec : ''}`), ), forListElements ), ); hintPanel.forLink = link; setupRefHintEventListeners(link, hintPanel); return hintPanel; } function hideAllRefHints() { queryAll(".ref-hint").forEach(el=>hideRefHint(el)); } function hideRefHint(refHint) { const link = refHint.forLink; link.setAttribute("aria-expanded", "false"); if(refHint.teardownEventListeners) { refHint.teardownEventListeners(); } refHint.remove(); } function showRefHint(link) { if(link.classList.contains("dfn-link")) return; const url = link.getAttribute("href"); const ref = refsData[url]; if(!ref) return; hideAllRefHints(); // Only display one at this time. const refHint = mkRefHint(link, ref); append(document.body, refHint); link.setAttribute("aria-expanded", "true"); positionRefHint(refHint); } function setupRefHintEventListeners(link, refHint) { if (refHint.teardownEventListeners) return; // Add event handlers to hide the refHint after the user moves away // from both the link and refHint, if not hovering either within one second. let timeout = null; const startHidingRefHint = (event) => { if (timeout) { clearTimeout(timeout); } timeout = setTimeout(() => { hideRefHint(refHint); }, 1000); } const resetHidingRefHint = (event) => { if (timeout) clearTimeout(timeout); timeout = null; }; link.addEventListener("mouseleave", startHidingRefHint); link.addEventListener("mouseenter", resetHidingRefHint); link.addEventListener("blur", startHidingRefHint); link.addEventListener("focus", resetHidingRefHint); refHint.addEventListener("mouseleave", startHidingRefHint); refHint.addEventListener("mouseenter", resetHidingRefHint); refHint.addEventListener("blur", startHidingRefHint); refHint.addEventListener("focus", resetHidingRefHint); refHint.teardownEventListeners = () => { // remove event listeners resetHidingRefHint(); link.removeEventListener("mouseleave", startHidingRefHint); link.removeEventListener("mouseenter", resetHidingRefHint); link.removeEventListener("blur", startHidingRefHint); link.removeEventListener("focus", resetHidingRefHint); refHint.removeEventListener("mouseleave", startHidingRefHint); refHint.removeEventListener("mouseenter", resetHidingRefHint); refHint.removeEventListener("blur", startHidingRefHint); refHint.removeEventListener("focus", resetHidingRefHint); }; } function positionRefHint(refHint) { const link = refHint.forLink; const linkPos = getBounds(link); refHint.style.top = linkPos.bottom + "px"; refHint.style.left = linkPos.left + "px"; const panelPos = refHint.getBoundingClientRect(); const panelMargin = 8; const maxRight = document.body.parentNode.clientWidth - panelMargin; if (panelPos.right > maxRight) { const overflowAmount = panelPos.right - maxRight; const newLeft = Math.max(panelMargin, linkPos.left - overflowAmount); refHint.style.left = newLeft + "px"; } } // TODO: shared util // Returns the root-level absolute position {left and top} of element. function getBounds(el, relativeTo=document.body) { const relativeRect = relativeTo.getBoundingClientRect(); const elRect = el.getBoundingClientRect(); const top = elRect.top - relativeRect.top; const left = elRect.left - relativeRect.left; return { top, left, bottom: top + elRect.height, right: left + elRect.width, } } function showRefHintListener(e) { // If the target isn't in a link (or is a link), // just ignore it. let link = e.target.closest("a"); if(!link) return; // If the target is in a ref-hint panel // (aka a link in the already-open one), // also just ignore it. if(link.closest(".ref-hint")) return; // Otherwise, show the panel for the link. showRefHint(link); } function hideAllHintsListener(e) { // If the click is inside a ref-hint panel, ignore it. if(e.target.closest(".ref-hint")) return; // Otherwise, close all the current panels. hideAllRefHints(); } document.addEventListener("DOMContentLoaded", () => { document.body.addEventListener("mousedown", showRefHintListener); document.body.addEventListener("focus", showRefHintListener); document.body.addEventListener("click", hideAllHintsListener); }); window.addEventListener("resize", () => { // Hide any open ref hint. hideAllRefHints(); }); } </script>