CINXE.COM
CSS Nesting Module
<!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 Nesting Module</title> <meta content="ED" name="w3c-status"> <link href="https://www.w3.org/StyleSheets/TR/2021/W3C-ED" rel="stylesheet"> <meta content="Bikeshed version 742f3d674, updated Mon Nov 4 14:56:54 2024 -0800" name="generator"> <link href="https://www.w3.org/TR/css-nesting-1/" rel="canonical"> <link href="https://drafts.csswg.org/csslogo.ico" rel="icon"> <meta content="1f4e5de6538eeaed2378d127300a62f95146562f" 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-idl-highlighting */ pre.idl.highlight { background: var(--borderedblock-bg, var(--def-bg)); } </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> <style>/* Boilerplate: style-wpt */ :root { --wpt-border: hsl(0, 0%, 60%); --wpt-bg: hsl(0, 0%, 95%); --wpt-text: var(--text); --wptheading-text: hsl(0, 0%, 30%); } @media (prefers-color-scheme: dark) { :root { --wpt-border: hsl(0, 0%, 30%); --wpt-bg: var(--borderedblock-bg); --wpt-text: var(--text); --wptheading-text: hsl(0, 0%, 60%); } } .wpt-tests-block { list-style: none; border-left: .5em solid var(--wpt-border); background: var(--wpt-bg); color: var(--wpt-text); margin: 1em auto; padding: .5em; } .wpt-tests-block summary { color: var(--wptheading-text); font-weight: normal; text-transform: uppercase; } .wpt-tests-block summary::marker{ color: var(--wpt-border); } .wpt-tests-block summary:hover::marker{ color: var(--wpt-text); } /* The only content of a wpt test block in its closed state is the <summary>, which contains the word TESTS, and that is absolutely positioned. In that closed state, wpt test blocks are styled to have a top margin whose height is exactly equal to the height of the absolutely positioned <summary>, and no other background/padding/margin/border. The wpt test block elements will therefore allow the maring of the previous/next block elements to collapse through them; if this combined margin would be larger than its own top margin, it stays as is, and therefore the pre-existing vertical rhythm of the document is undisturbed. If that combined margin would be smaller, it is grown to that size. This means that the wpt test block ensures that there's always enough vertical space to insert the summary, without adding more than is needed. */ .wpt-tests-block:not([open]){ padding: 0; border: none; background: none; font-size: 0.75em; line-height: 1; position: relative; margin: 1em 0 0; } .wpt-tests-block:not([open]) summary { position: absolute; right: 0; bottom: 0; } /* It is possible that both the last child of a block element and the block element itself would be annotated with a <wpt> block each. If the block element has a padding or a border, that's fine, but otherwise the bottom margin of the block and of its last child would collapse and both <wpt> elements would overlap, being both placed there. To avoid that, add 1px of padding to the <wpt> element annotating the last child to prevent the bottom margin of the block and of its last child from collapsing (and as much negative margin, as wel only want to prevent margin collapsing, but are not trying to actually take more space). */ .wpt-tests-block:not([open]):last-child { padding-bottom: 1px; margin-bottom: -1px; } /* Exception to the previous rule: don't do that in non-last list items, because it's not necessary, and would therefore consume more space than strictly needed. Lists must have list items as children, not <wpt> elements, so a <wpt> element cannot be a sibling of a list item, and the collision that the previous rule avoids cannot happen. */ li:not(:last-child) > .wpt-tests-block:not([open]):last-child, dd:not(:last-child) > .wpt-tests-block:not([open]):last-child { padding-bottom: 0; margin-bottom: 0; } .wpt-tests-block:not([open]):not(:hover){ opacity: 0.5; } .wpt-tests-list { list-style: none; display: grid; margin: 0; padding: 0; grid-template-columns: 1fr max-content auto auto; grid-column-gap: .5em; } .wpt-tests-block hr:last-child { display: none; } .wpt-test { display: contents; } .wpt-test > a { text-decoration: underline; border: none; } .wpt-test > .wpt-name { grid-column: 1; } .wpt-test > .wpt-results { grid-column: 2; } .wpt-test > .wpt-live { grid-column: 3; } .wpt-test > .wpt-source { grid-column: 4; } .wpt-test > .wpt-results { display: flex; gap: .1em; } .wpt-test .wpt-result { display: inline-block; height: 1em; width: 1em; border-radius: 50%; position: relative; } </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 Nesting Module</h1> <p id="w3c-state"><a href="https://www.w3.org/standards/types/#ED">Editor’s Draft</a>, <time class="dt-updated" datetime="2024-11-06">6 November 2024</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-nesting/">https://drafts.csswg.org/css-nesting/</a> <dt>Latest published version: <dd><a href="https://www.w3.org/TR/css-nesting-1/">https://www.w3.org/TR/css-nesting-1/</a> <dt>Feedback: <dd><a href="https://github.com/w3c/csswg-drafts/labels/css-nesting-1">CSSWG Issues Repository</a> <dd><a href="#issues-index">Inline In Spec</a> <dt class="editor">Editors: <dd class="editor p-author h-card vcard" data-editor-id="42199"><a class="p-name fn u-url url" href="http://xanthir.com/contact/">Tab Atkins-Bittner</a> (<span class="p-org org">Google</span>) <dd class="editor p-author h-card vcard" data-editor-id="112669"><a class="p-name fn u-url url" href="https://nerdy.dev">Adam Argyle</a> (<span class="p-org org">Google</span>) <dt>Suggest an Edit for this Spec: <dd><a href="https://github.com/w3c/csswg-drafts/blob/main/css-nesting-1/Overview.bs">GitHub Editor</a> </dl> </div> </details> <div data-fill-with="warning"></div> <p class="copyright" data-fill-with="copyright"><a href="https://www.w3.org/policies/#copyright">Copyright</a> © 2024 <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 introduces the ability to nest one style rule inside another, with the selector of the child rule relative to the selector of the parent rule. This increases the modularity and maintainability of CSS stylesheets.</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> This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress. </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-nesting” in the title, like this: “[css-nesting] <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-nesting%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></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="#placement"><span class="secno">1.1</span> <span class="content"> Module Interactions</span></a> <li><a href="#values"><span class="secno">1.2</span> <span class="content"> Values</span></a> </ol> <li><a href="#explainer"><span class="secno">2</span> <span class="content"> Explainer</span></a> <li> <a href="#nesting"><span class="secno">3</span> <span class="content">Nesting Style Rules</span></a> <ol class="toc"> <li><a href="#syntax"><span class="secno">3.1</span> <span class="content">Syntax</span></a> <li><a href="#syntax-examples"><span class="secno">3.2</span> <span class="content"> Examples</span></a> <li> <a href="#conditionals"><span class="secno">3.3</span> <span class="content">Nesting Other At-Rules</span></a> <ol class="toc"> <li><a href="#nesting-at-scope"><span class="secno">3.3.1</span> <span class="content"> Nested <span class="css">@scope</span> Rules</span></a> </ol> <li><a href="#mixing"><span class="secno">3.4</span> <span class="content">Mixing Nesting Rules and Declarations</span></a> </ol> <li><a href="#nest-selector"><span class="secno">4</span> <span class="content">Nesting Selector: the <span class="css">&</span> selector</span></a> <li><a href="#nested-declarations-rule"><span class="secno">5</span> <span class="content"> The Nested Declarations Rule</span></a> <li> <a href="#cssom"><span class="secno">6</span> <span class="content">CSSOM</span></a> <ol class="toc"> <li><a href="#the-cssnestrule"><span class="secno">6.1</span> <span class="content">The <code class="idl"><span>CSSNestedDeclarations</span></code> Interface</span></a> <li><a href="#changes"><span class="secno">6.2</span> <span class="content">Changes</span></a> </ol> <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="#idl-index"><span class="secno"></span> <span class="content">IDL Index</span></a> <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>This module describes support for nesting a style rule within another style rule, allowing the inner rule’s selector to reference the elements matched by the outer rule. This feature allows related styles to be aggregated into a single structure within the CSS document, improving readability and maintainability.</p> <h3 class="heading settled" data-level="1.1" id="placement"><span class="secno">1.1. </span><span class="content"> Module Interactions</span><a class="self-link" href="#placement"></a></h3> <p>This module introduces new parser rules that extend the <a data-link-type="biblio" href="#biblio-css21" title="Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification">[CSS21]</a> parser model. It introduces selectors that extend the <a data-link-type="biblio" href="#biblio-selectors-4" title="Selectors Level 4">[SELECTORS-4]</a> module. It extends and modifies some IDL and algorithms defined in the <a data-link-type="biblio" href="#biblio-cssom-1" title="CSS Object Model (CSSOM)">[CSSOM-1]</a> module.</p> <h3 class="heading settled" data-level="1.2" id="values"><span class="secno">1.2. </span><span class="content"> Values</span><a class="self-link" href="#values"></a></h3> <p>This specification does not define any new properties or values.</p> <h2 class="heading settled" data-level="2" id="explainer"><span class="secno">2. </span><span class="content"> Explainer</span><a class="self-link" href="#explainer"></a></h2> <p><em>This section is non-normative.</em></p> <p>Imagine you have some CSS that you’d like to write in a more compact way.</p> <pre class="highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> <c- p>}</c-> .foo .bar <c- p>{</c-> <c- k>font-size</c-><c- p>:</c-> <c- m>1.4</c-><c- k>rem</c-><c- p>;</c-> <c- p>}</c-> </pre> <p>With Nesting, you can write such code as:</p> <pre class="highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> .bar <c- p>{</c-> <c- k>font-size</c-><c- p>:</c-> <c- m>1.4</c-><c- k>rem</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>If you’ve been nesting styles in Sass or other CSS preprocessors, you will find this very familiar.</p> <p>You can nest any rules inside of a parent style rule:</p> <pre class="highlight">main <c- p>{</c-> div <c- p>{</c-> ... <c- p>}</c-> .bar <c- p>{</c-> ... <c- p>}</c-> #baz <c- p>{</c-> ...<c- p>}</c-> <c- nf>:has</c-><c- p>(</c->p<c- p>)</c-> <c- p>{</c-> ... <c- p>}</c-> ::backdrop <c- p>{</c-> ... <c- p>}</c-> <c- p>[</c->lang|=<c- s>"zh"</c-><c- p>]</c-> <c- p>{</c-> ... <c- p>}</c-> * <c- p>{</c-> ... <c- p>}</c-> <c- p>}</c-> </pre> <p>By default, the child rule’s selector is assumed to connect to the parent rule by a <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#descendant-combinator" id="ref-for-descendant-combinator">descendant combinator</a>, but you can start the nested selector with any combinator to change that:</p> <pre class="highlight">main <c- p>{</c-> + article <c- p>{</c-> ... <c- p>}</c-> > p <c- p>{</c-> ... <c- p>}</c-> ~ main <c- p>{</c-> ... <c- p>}</c-> <c- p>}</c-> </pre> <p>The new <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-">&</a> selector lets you refer to the elements matched by the parent selector explictly, so the previous examples could have been written as:</p> <pre class="highlight">main <c- p>{</c-> & + article <c- p>{</c-> ... <c- p>}</c-> & > p <c- p>{</c-> ... <c- p>}</c-> & ~ main <c- p>{</c-> ... <c- p>}</c-> <c- p>}</c-> </pre> <p>But you can place the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①">&</a> in other locations within the nested selector, to indicate other types of relationships between the parent and child rule. For example, this CSS:</p> <pre class="highlight">ul <c- p>{</c-> <c- k>padding-left</c-><c- p>:</c-> <c- m>1</c-><c- k>em</c-><c- p>;</c-> <c- p>}</c-> .component ul <c- p>{</c-> <c- k>padding-left</c-><c- p>:</c-> <c- m>0</c-><c- p>;</c-> <c- p>}</c-> </pre> <p>Can be rewritten using Nesting as:</p> <pre class="highlight">ul <c- p>{</c-> <c- k>padding-left</c-><c- p>:</c-> <c- m>1</c-><c- k>em</c-><c- p>;</c-> .component & <c- p>{</c-> <c- k>padding-left</c-><c- p>:</c-> <c- m>0</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>Again, the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-②">&</a> gives you a way to say “this is where I want the nested selector to go”.</p> <p>It’s also handy when you don’t want a space between your selectors. For example:</p> <pre class="highlight">a <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> &:hover <c- p>{</c-> <c- k>color</c-><c- p>:</c-> lightblue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>Such code yields the same result as <code class="highlight"><c- k>a</c-><c- p>:</c->hover <c- p>{</c-></code>. Without the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-③">&</a>, you’d get <code class="highlight"><c- k>a</c-> <c- p>:</c->hover <c- p>{</c-></code>—notice the space between <code class="highlight">a</code> and <code class="highlight">:hover</code>—which would fail to style your hover link.</p> <p>You can nest more than one layer deep—nesting CSS inside already-nested CSS—in as many levels as you desire. You can mix Nesting with Container Queries, Supports Queries, Media Queries, and/or Cascade Layers however you want. (Nearly) anything can go inside of anything.</p> <h2 class="heading settled" data-level="3" id="nesting"><span class="secno">3. </span><span class="content">Nesting Style Rules</span><a class="self-link" href="#nesting"></a></h2> <p>Style rules can be nested inside of other styles rules. These <dfn class="dfn-paneled" data-dfn-type="dfn" data-export data-lt="nested style rule|nesting style rule" id="nested-style-rule">nested style rules</dfn> act exactly like ordinary style rules—associating properties with elements via selectors—but they "inherit" their parent rule’s selector context, allowing them to further build on the parent’s selector without having to repeat it, possibly multiple times.</p> <p>A <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule">nested style rule</a> is exactly like a normal style rule, except that it can use <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector">relative selectors</a>, which are implicitly relative to the elements matched by the parent rule.</p> <div class="example" id="example-82c7d228"> <a class="self-link" href="#example-82c7d228"></a> That is, a nested style rule like: <pre class="lang-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> a <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>is valid, and equivalent to:</p> <pre class="lang-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> .foo a <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> <p>The nested rule can also use the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector">nesting selector</a> to directly refer to the parent rule’s matched elements, or use <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector①">relative selector</a> syntax to specify relationships other than "descendant".</p> <pre class="lang-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> &:hover <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to: */</c-> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> .foo:hover <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> <pre class="lang-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> + .bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to: */</c-> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> .foo + .bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> </div> <h3 class="heading settled" data-level="3.1" id="syntax"><span class="secno">3.1. </span><span class="content">Syntax</span><a class="self-link" href="#syntax"></a></h3> <p>The contents of <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#style-rule" id="ref-for-style-rule">style rules</a> now accepts <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule①">nested style rules</a> and <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#at-rule" id="ref-for-at-rule">at-rules</a>, in addition to the existing <a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-declarations" id="ref-for-cssstyledeclaration-declarations">declarations</a>.</p> <p><a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule②">Nested style rules</a> differ from non-nested rules in the following ways:</p> <ul> <li data-md> <p>A <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule③">nested style rule</a> accepts a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/selectors-4/#typedef-relative-selector-list" id="ref-for-typedef-relative-selector-list"><relative-selector-list></a> as its prelude (rather than just a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/selectors-4/#typedef-selector-list" id="ref-for-typedef-selector-list"><selector-list></a>). Any <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector②">relative selectors</a> are relative to the elements represented by the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector①">nesting selector</a>.</p> <li data-md> <p>If a selector in the <a class="production css" data-link-type="type" href="https://drafts.csswg.org/selectors-4/#typedef-relative-selector-list" id="ref-for-typedef-relative-selector-list①"><relative-selector-list></a> does not start with a <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#selector-combinator" id="ref-for-selector-combinator">combinator</a> but does <a data-link-type="dfn" href="#contain-the-nesting-selector" id="ref-for-contain-the-nesting-selector">contain the nesting selector</a>, it is interpreted as a non-<a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector③">relative selector</a>.</p> </ul> <p>The precise details of how nested style rules are parsed are defined in <a data-link-type="biblio" href="#biblio-css-syntax-3" title="CSS Syntax Module Level 3">[CSS-SYNTAX-3]</a>.</p> <p>An invalid <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule④">nested style rule</a> is ignored, along with its contents, but does not invalidate its parent rule.</p> <p>Nested rules with <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector④">relative selectors</a> include the specificity of their implied <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector②">nesting selector</a>. For example, <span class="css">.foo { > .bar {...}}</span> and <span class="css">.foo { & > .bar {...}}</span> have the same specificity for their inner rule.</p> <div class="note" role="note"> Some CSS-generating tools that preprocess nesting will concatenate selectors as strings, allowing authors to build up a <em>single</em> <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#simple" id="ref-for-simple">simple selector</a> across nesting levels. This is sometimes used with hierarchical name patterns like <a href="https://en.wikipedia.org/wiki/CSS#:~:text=bem%20(block%2C%20element%2C%20modifier)">BEM</a> to reduce repetition across a file, when the selectors themselves have significant repetition internally. <p>For example, if one component uses the class <span class="css">.foo</span>, and a nested component uses <span class="css">.fooBar</span>, you could write this in <a href="https://sass-lang.com/">Sass</a> as:</p> <pre class="lang-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> &Bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* In Sass, this is equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .fooBar { color: red; }</c-> <c- c>*/</c-> </pre> <p>This is not allowed in CSS, as nesting is not a syntax transformation, but rather matches on the actual elements the parent selector matches.</p> <p>It is also true that the selector <span class="css">&Bar</span> is invalid in CSS in the first place, as the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-ui-4/#valdef-caret-shape-bar" id="ref-for-valdef-caret-shape-bar">Bar</a> part is a type selector, which must come first in the compound selector. (That is, it must be written as <span class="css">Bar&</span>.) So, luckily, there is no overlap between CSS Nesting and the preprocessor syntax.</p> </div> <div class="algorithm" data-algorithm="contain the nesting selector"> A selector is said to <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="contain-the-nesting-selector">contain the nesting selector</dfn> if, when it was <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#css-parse-something-according-to-a-css-grammar" id="ref-for-css-parse-something-according-to-a-css-grammar">parsed</a> as any type of selector, a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-delim-token" id="ref-for-typedef-delim-token"><delim-token></a> with the value "&" (U+0026 AMPERSAND) was encountered. <p class="note" role="note"><span class="marker">Note:</span> This is phrased in this explicit manner so as to catch cases like <span class="css">:is(:unknown(&), .bar)</span>, where an unknown selector (which, being unknown, we have no way of knowing whether the argument is <em>meant</em> to be parsed as a selector or not) is the only part of the selector that contains an <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-④">&</a>. As that <em>might</em> be a perfectly valid selector that’s only supported by newer browsers, and we don’t want parsing to be dependent on unrelated versioning issues, we treat it as still <a data-link-type="dfn" href="#contain-the-nesting-selector" id="ref-for-contain-the-nesting-selector①">containing the nesting selector</a>.</p> </div> <p>If a <a class="production css" data-link-type="type" href="https://drafts.csswg.org/selectors-4/#typedef-forgiving-selector-list" id="ref-for-typedef-forgiving-selector-list"><forgiving-selector-list></a> has an item that <a data-link-type="dfn" href="#contain-the-nesting-selector" id="ref-for-contain-the-nesting-selector②">contains the nesting selector</a> but is invalid, that item is preserved exactly as-is rather than being discarded. (This does not change the matching behavior of the selector—an invalid selector still fails to match anything—just the serialization of the selector.)</p> <p class="issue" id="issue-03f974e2"><a class="self-link" href="#issue-03f974e2"></a> The preceding paragraph needs to move to Selectors when we move <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-⑤">&</a> itself to Selectors; I’m monkey-patching for convenience here.</p> <h3 class="heading settled" data-level="3.2" id="syntax-examples"><span class="secno">3.2. </span><span class="content"> Examples</span><a class="self-link" href="#syntax-examples"></a></h3> <pre class="lang-css highlight"><b><c- c>/* & can be used on its own */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> & > .bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> > .baz <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .foo > .bar { color: red; }</c-> <c- c> .foo > .baz { color: green; }</c-> <c- c>*/</c-> <b><c- c>/* or in a compound selector,</c-> <c- c> refining the parent’s selector */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> &.bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .foo.bar { color: red; }</c-> <c- c>*/</c-> <b><c- c>/* multiple selectors in the list are all</c-> <c- c> relative to the parent */</c-></b> .foo<c- p>,</c-> .bar <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> + .baz<c- p>,</c-> &.qux <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo, .bar { color: blue; }</c-> <c- c> :is(.foo, .bar) + .baz,</c-> <c- c> :is(.foo, .bar).qux { color: red; }</c-> <c- c>*/</c-> <b><c- c>/* & can be used multiple times in a single selector */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> & .bar & .baz & .qux <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .foo .bar .foo .baz .foo .qux { color: red; }</c-> <c- c>*/</c-> <b><c- c>/* & doesn’t have to be at the beginning of the selector */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> .parent & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: red; }</c-> <c- c> .parent .foo { color: blue; }</c-> <c- c>*/</c-> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- nf>:not</c-><c- p>(</c->&<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: red; }</c-> <c- c> :not(.foo) { color: blue; }</c-> <c- c>*/</c-> <b><c- c>/* But if you use a </c-><a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector⑤"><c- c>relative selector</c-></a><c- c>,</c-> <c- c> an initial & is implied automatically */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> + .bar + & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: red; }</c-> <c- c> .foo + .bar + .foo { color: blue; }</c-> <c- c>*/</c-> <b><c- c>/* Somewhat silly, but & can be used all on its own, as well. */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> & <c- p>{</c-> <c- k>padding</c-><c- p>:</c-> <c- m>2</c-><c- k>ch</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .foo { padding: 2ch; }</c-> <c- c> // or</c-> <c- c> .foo {</c-> <c- c> color: blue;</c-> <c- c> padding: 2ch;</c-> <c- c> }</c-> <c- c>*/</c-> <b><c- c>/* Again, silly, but can even be doubled up. */</c-></b> .foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> && <c- p>{</c-> <c- k>padding</c-><c- p>:</c-> <c- m>2</c-><c- k>ch</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo { color: blue; }</c-> <c- c> .foo.foo { padding: 2ch; }</c-> <c- c>*/</c-> <b><c- c>/* The parent selector can be arbitrarily complicated */</c-></b> .error<c- p>,</c-> #404 <c- p>{</c-> &:hover > .baz <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> :is(.error, #404):hover > .baz { color: red; }</c-> <c- c>*/</c-> .ancestor .el <c- p>{</c-> .other-ancestor & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .other-ancestor :is(.ancestor .el) { color: red; }</c-> <b><c- c>/* As can the nested selector */</c-></b> .foo <c- p>{</c-> & <c- nf>:is</c-><c- p>(</c->.bar<c- p>,</c-> &.baz<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .foo :is(.bar, .foo.baz) { color: red; }</c-> <c- c>*/</c-> <b><c- c>/* Multiple levels of nesting "stack up" the selectors */</c-></b> figure <c- p>{</c-> <c- k>margin</c-><c- p>:</c-> <c- m>0</c-><c- p>;</c-> > figcaption <c- p>{</c-> <c- k>background</c-><c- p>:</c-> <c- nf>hsl</c-><c- p>(</c-><c- m>0</c-> <c- m>0</c-><c- k>%</c-> <c- m>0</c-><c- k>%</c-> / <c- m>50</c-><c- k>%</c-><c- p>);</c-> > p <c- p>{</c-> <c- k>font-size</c-><c- p>:</c-> <c- m>.9</c-><c- k>rem</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> figure { margin: 0; }</c-> <c- c> figure > figcaption { background: hsl(0 0% 0% / 50%); }</c-> <c- c> figure > figcaption > p { font-size: .9rem; }</c-> <c- c>*/</c-> <b><c- c>/* Example usage with Cascade Layers */</c-></b> <c- n>@layer</c-> base <c- p>{</c-> html <c- p>{</c-> <c- k>block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> body <c- p>{</c-> <c- k>min-block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> @layer base {</c-> <c- c> html { block-size: 100%; }</c-> <c- c> html body { min-block-size: 100%; }</c-> <c- c> }</c-> <c- c>*/</c-> <b><c- c>/* Example nesting Cascade Layers */</c-></b> <c- n>@layer</c-> base <c- p>{</c-> html <c- p>{</c-> <c- k>block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- n>@layer</c-> support <c- p>{</c-> body <c- p>{</c-> <c- k>min-block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> @layer base {</c-> <c- c> html { block-size: 100%; }</c-> <c- c> }</c-> <c- c> @layer base.support {</c-> <c- c> html body { min-block-size: 100%; }</c-> <c- c> }</c-> <c- c>*/</c-> <b><c- c>/* Example usage with Scoping */</c-></b> <c- n>@scope</c-> <c- p>(</c->.card<c- p>)</c-> to <c- p>(</c->> header<c- p>)</c-> <c- p>{</c-> :scope <c- p>{</c-> <c- k>inline-size</c-><c- p>:</c-> <c- m>40</c-><c- k>ch</c-><c- p>;</c-> <c- k>aspect-ratio</c-><c- p>:</c-> <c- m>3</c->/<c- m>4</c-><c- p>;</c-> > header <c- p>{</c-> <c- k>border-block-end</c-><c- p>:</c-> <c- m>1</c-><c- k>px</c-> solid white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> @scope (.card) to (> header) {</c-> <c- c> :scope { inline-size: 40ch; aspect-ratio: 3/4; }</c-> <c- c> :scope > header { border-block-end: 1px solid white; }</c-> <c- c> }</c-> <c- c>*/</c-> <b><c- c>/* Example nesting Scoping */</c-></b> .card <c- p>{</c-> <c- k>inline-size</c-><c- p>:</c-> <c- m>40</c-><c- k>ch</c-><c- p>;</c-> <c- k>aspect-ratio</c-><c- p>:</c-> <c- m>3</c->/<c- m>4</c-><c- p>;</c-> <c- n>@scope</c-> <c- p>(</c->&<c- p>)</c-> to <c- p>(</c->> header > *<c- p>)</c-> <c- p>{</c-> :scope > header <c- p>{</c-> <c- k>border-block-end</c-><c- p>:</c-> <c- m>1</c-><c- k>px</c-> solid white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to</c-> <c- c> .card { inline-size: 40ch; aspect-ratio: 3/4; }</c-> <c- c> @scope (.card) to (> header > *) {</c-> <c- c> :scope > header { border-block-end: 1px solid white; }</c-> <c- c> }</c-> <c- c>*/</c-> </pre> <h3 class="heading settled" data-level="3.3" id="conditionals"><span class="secno">3.3. </span><span class="content">Nesting Other At-Rules</span><a class="self-link" href="#conditionals"></a></h3> <p>In addition to <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule⑤">nested style rules</a>, this specification allows <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="nested-group-rules">nested group rules</dfn> inside of <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#style-rule" id="ref-for-style-rule①">style rules</a>: any at-rule whose body contains <span id="ref-for-style-rule②">style rules</span> can be nested inside of a <span id="ref-for-style-rule③">style rule</span> as well.</p> <p>When nested in this way, the contents of a <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules">nested group rule</a>'s block are parsed as <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-block-contents" id="ref-for-typedef-block-contents"><block-contents></a> rather than <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-syntax-3/#typedef-rule-list" id="ref-for-typedef-rule-list"><rule-list></a>:</p> <ul> <li data-md> <p><a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#style-rule" id="ref-for-style-rule④">Style rules</a> are <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule⑥">nested style rules</a>, with their <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector③">nesting selector</a> taking its definition from the nearest ancestor <span id="ref-for-style-rule⑤">style rule</span>.</p> <li data-md> <p>Properties can be directly used, acting as if they were nested in a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①">nested declarations rule</a>.</p> </ul> <div class="note" role="note"> Specifically, these rules are capable of being <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules①">nested group rules</a>: <ul> <li data-md> <p>all the <a data-link-type="dfn" href="https://drafts.csswg.org/css-conditional-3/#conditional-group-rule" id="ref-for-conditional-group-rule">conditional group rules</a> (<a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-5/#at-ruledef-container" id="ref-for-at-ruledef-container">@container</a>, <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-media" id="ref-for-at-ruledef-media">@media</a>, <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports" id="ref-for-at-ruledef-supports">@supports</a>)</p> <li data-md> <p><a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-cascade-5/#at-ruledef-layer" id="ref-for-at-ruledef-layer">@layer</a></p> <li data-md> <p><a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope" id="ref-for-at-ruledef-scope">@scope</a></p> </ul> </div> <p>The meanings and behavior of such <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules②">nested group rules</a> is otherwise unchanged, unless otherwise specified.</p> <div class="example" id="example-81212ace"> <a class="self-link" href="#example-81212ace"></a> For example, the following conditional nestings are valid: <pre class="lang-css highlight"><b><c- c>/* Properties can be directly used */</c-></b> .foo <c- p>{</c-> <c- k>display</c-><c- p>:</c-> grid<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> <c- p>{</c-> <c- k>grid-auto-flow</c-><c- p>:</c-> column<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to: */</c-> .foo <c- p>{</c-> <c- k>display</c-><c- p>:</c-> grid<c- p>;</c-> <c- p>}</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> <c- p>{</c-> .foo <c- p>{</c-> <c- k>grid-auto-flow</c-><c- p>:</c-> column <c- p>}</c-> <c- p>}</c-> <c- c>/* and also equivalent to the unnested: */</c-> .foo <c- p>{</c-> <c- k>display</c-><c- p>:</c-> grid<c- p>;</c-> <c- p>}</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> <c- p>{</c-> .foo <c- p>{</c-> <c- k>grid-auto-flow</c-><c- p>:</c-> column<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <b><c- c>/* Conditionals can be further nested */</c-></b> .foo <c- p>{</c-> <c- k>display</c-><c- p>:</c-> grid<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> <c- p>{</c-> <c- k>grid-auto-flow</c-><c- p>:</c-> column<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->min-width > <c- m>1024</c-><c- k>px</c-><c- p>)</c-> <c- p>{</c-> <c- k>max-inline-size</c-><c- p>:</c-> <c- m>1024</c-><c- k>px</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to */</c-> .foo <c- p>{</c-> <c- k>display</c-><c- p>:</c-> grid<c- p>;</c-> <c- p>}</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> <c- p>{</c-> .foo <c- p>{</c-> <c- k>grid-auto-flow</c-><c- p>:</c-> column<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- n>@media</c-> <c- p>(</c->orientation: landscape<c- p>)</c-> and <c- p>(</c->min-width > <c- m>1024</c-><c- k>px</c-><c- p>)</c-> <c- p>{</c-> .foo <c- p>{</c-> <c- k>max-inline-size</c-><c- p>:</c-> <c- m>1024</c-><c- k>px</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <b><c- c>/* Example nesting Cascade Layers */</c-></b> html <c- p>{</c-> <c- n>@layer</c-> base <c- p>{</c-> <c- k>block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- n>@layer</c-> support <c- p>{</c-> & body <c- p>{</c-> <c- k>min-block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to */</c-> <c- n>@layer</c-> base <c- p>{</c-> html <c- p>{</c-> <c- k>block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- n>@layer</c-> base.support <c- p>{</c-> html body <c- p>{</c-> <c- k>min-block-size</c-><c- p>:</c-> <c- m>100</c-><c- k>%</c-><c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <b><c- c>/* Example nesting Scoping */</c-></b> .card <c- p>{</c-> <c- k>inline-size</c-><c- p>:</c-> <c- m>40</c-><c- k>ch</c-><c- p>;</c-> <c- k>aspect-ratio</c-><c- p>:</c-> <c- m>3</c->/<c- m>4</c-><c- p>;</c-> <c- n>@scope</c-> <c- p>(</c->&<c- p>)</c-> <c- p>{</c-> :scope <c- p>{</c-> <c- k>border</c-><c- p>:</c-> <c- m>1</c-><c- k>px</c-> solid white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* equivalent to */</c-> .card <c- p>{</c-> <c- k>inline-size</c-><c- p>:</c-> <c- m>40</c-><c- k>ch</c-><c- p>;</c-> <c- k>aspect-ratio</c-><c- p>:</c-> <c- m>3</c->/<c- m>4</c-><c- p>;</c-> <c- p>}</c-> <c- n>@scope</c-> <c- p>(</c->.card<c- p>)</c-> <c- p>{</c-> :scope <c- p>{</c-> <c- k>border-block-end</c-><c- p>:</c-> <c- m>1</c-><c- k>px</c-> solid white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> </div> <p>Runs of consecutive directly-nested properties are automatically wrapped in <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①">nested declarations rules</a>. (This is observable in the CSSOM.)</p> <h4 class="heading settled" data-level="3.3.1" id="nesting-at-scope"><span class="secno">3.3.1. </span><span class="content"> Nested <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope" id="ref-for-at-ruledef-scope①">@scope</a> Rules</span><a class="self-link" href="#nesting-at-scope"></a></h4> <p>When the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope" id="ref-for-at-ruledef-scope②">@scope</a> rule is a <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules③">nested group rule</a>, an <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-⑥">&</a> in the <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-cascade-6/#typedef-scope-start" id="ref-for-typedef-scope-start"><scope-start></a> selector refers to the elements matched by the nearest ancestor style rule.</p> <p>For the purposes of the style rules in its body and its own <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-cascade-6/#typedef-scope-end" id="ref-for-typedef-scope-end"><scope-end></a> selector, the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope" id="ref-for-at-ruledef-scope③">@scope</a> rule is treated as an ancestor style rule, matching the elements matched by its <a class="production css" data-link-type="type" href="https://drafts.csswg.org/css-cascade-6/#typedef-scope-start" id="ref-for-typedef-scope-start①"><scope-start></a> selector.</p> <div class="example" id="example-792b81d1"> <a class="self-link" href="#example-792b81d1"></a> That is, the following code: <pre class="highlight">.parent <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- n>@scope</c-> <c- p>(</c->& > .scope<c- p>)</c-> to <c- p>(</c->& .limit<c- p>)</c-> <c- p>{</c-> & .content <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>is equivalent to:</p> <pre class="highlight">.parent <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- n>@scope</c-> <c- p>(</c->.parent > .scope<c- p>)</c-> to <c- p>(</c->.parent > .scope .limit<c- p>)</c-> <c- p>{</c-> .parent > .scope .content <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> </div> <h3 class="heading settled" data-level="3.4" id="mixing"><span class="secno">3.4. </span><span class="content">Mixing Nesting Rules and Declarations</span><a class="self-link" href="#mixing"></a></h3> <p>When a style rule contains both declarations and <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule⑦">nested style rules</a> or <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules④">nested group rules</a>, all three can be arbitrarily mixed. Declarations coming after or between rules are implicitly wrapped in <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①②">nested declarations rules</a>, to preserve their order relative to the other rules.</p> <div class="example" id="example-de3f70c3"> <a class="self-link" href="#example-de3f70c3"></a> For example, in the following code: <pre class="lang-css highlight">article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> color: red<c- p>;</c-> <c- p>}</c-> <c- c>/* equivalent to */</c-> article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> <c- p>}</c-> <c- nf>:is</c-><c- p>(</c->article<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- c>/* NOT equivalent to */</c-> article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> green<c- p>;</c-> <c- p>}</c-> article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- nf>:is</c-><c- p>(</c->article<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> </div> <p>For the purpose of determining the <a href="https://drafts.csswg.org/css-cascade-4/#cascade-sort">Order Of Appearance</a>, <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule⑧">nested style rules</a> and <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules⑤">nested group rules</a> are considered to come <em>after</em> their parent rule.</p> <div> For example: <pre class="lang-css highlight">article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>Both declarations have the same specificity (0,0,1), but the nested rule is considered to come <em>after</em> its parent rule, so the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color">color: red</a> declarations wins the cascade.</p> <p>On the other hand, in this example:</p> <pre class="lang-css highlight">article <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- nf>:where</c-><c- p>(</c->&<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>The <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#where-pseudo" id="ref-for-where-pseudo">:where()</a> pseudoclass reduces the specificity of the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector④">nesting selector</a> to 0, so the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color①">color: red</a> declaration now has a specificity of (0,0,0), and loses to the <span class="css" id="ref-for-propdef-color②">color: blue</span> declaration before "Order Of Appearance" comes into consideration.</p> </div> <p class="note" role="note"><span class="marker">Note:</span> While one <em>can</em> freely intermix declarations and nested rules, it’s harder to read and somewhat confusing to do so, since the later properties are automatically wrapped in a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①③">nested declarations rule</a> that doesn’t appear in the source text. For readability’s sake, it’s recommended that authors put all their properties first in a style rule, before any nested rules. (This also happens to act slightly better in older user agents: due to specifics of how parsing and error-recovery work, properties appearing after nested rules can get skipped.)</p> <h2 class="heading settled" data-level="4" id="nest-selector"><span class="secno">4. </span><span class="content">Nesting Selector: the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-⑦">&</a> selector</span><a class="self-link" href="#nest-selector"></a></h2> <p>When using a <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule⑨">nested style rule</a>, one must be able to refer to the elements matched by the parent rule; that is, after all, <em>the entire point of nesting</em>. To accomplish that, this specification defines a new selector, the <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="nesting-selector">nesting selector</dfn>, written as <dfn class="dfn-paneled css" data-dfn-type="selector" data-export id="selectordef-">&</dfn> (U+0026 AMPERSAND).</p> <p>When used in the selector of a <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule①⓪">nested style rule</a>, the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector⑤">nesting selector</a> represents the elements matched by the parent rule. When used in any other context, it represents the same elements as <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#scope-pseudo" id="ref-for-scope-pseudo">:scope</a> in that context (unless otherwise defined).</p> <div class="note" role="note"> The <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector⑥">nesting selector</a> can be desugared by replacing it with the parent style rule’s selector, wrapped in an <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo">:is()</a> selector. For example, <pre class="lang-css highlight">a<c- p>,</c-> b <c- p>{</c-> & c <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>is equivalent to</p> <pre class="lang-css highlight"><c- nf>:is</c-><c- p>(</c->a<c- p>,</c-> b<c- p>)</c-> c <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> </div> <p>The <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector⑦">nesting selector</a> cannot represent pseudo-elements (identical to the behavior of the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo①">:is()</a> pseudo-class).</p> <div class="example" id="example-7145ff1e"> <a class="self-link" href="#example-7145ff1e"></a> For example, in the following style rule: <pre class="lang-css highlight">.foo<c- p>,</c-> .foo::before<c- p>,</c-> .foo::after <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> &:hover <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-⑧">&</a> only represents the elements matched by <span class="css">.foo</span>; in other words, it’s equivalent to:</p> <pre class="lang-css highlight">.foo<c- p>,</c-> .foo::before<c- p>,</c-> .foo::after <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> .foo:hover <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> </pre> </div> <p class="issue" id="issue-62c479a8"><a class="self-link" href="#issue-62c479a8"></a> We’d like to relax this restriction, but need to do so simultaneously for both <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo②">:is()</a> and <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-⑨">&</a>, since they’re intentionally built on the same underlying mechanisms. (<a href="https://github.com/w3c/csswg-drafts/issues/7433">Issue 7433</a>)</p> <p>The <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#specificity" id="ref-for-specificity">specificity</a> of the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector⑧">nesting selector</a> is equal to the largest specificity among the complex selectors in the parent style rule’s selector list (identical to the behavior of <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo③">:is()</a>), or zero if no such selector list exists.</p> <div class="example" id="example-a71fa710"> <a class="self-link" href="#example-a71fa710"></a> For example, given the following style rules: <pre class="lang-css highlight">#a<c- p>,</c-> b <c- p>{</c-> & c <c- p>{</c-> <c- k>color</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> .foo c <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- p>}</c-> </pre> <p>Then in a DOM structure like</p> <pre class="lang-html highlight"><c- p><</c-><c- f>b</c-> <c- e>class</c-><c- o>=</c-><c- s>foo</c-><c- p>></c-> <c- p><</c-><c- f>c</c-><c- p>></c->Blue text<c- p></</c-><c- f>c</c-><c- p>></c-> <c- p></</c-><c- f>b</c-><c- p>></c-> </pre> <p>The text will be blue, rather than red. The specificity of the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①⓪">&</a> is the larger of the specificities of <span class="css">#a</span> ([1,0,0]) and <span class="css">b</span> ([0,0,1]), so it’s [1,0,0], and the entire <span class="css">& c</span> selector thus has specificity [1,0,1], which is larger than the specificity of <span class="css">.foo c</span> ([0,1,1]).</p> <p>Notably, this is <em>different</em> than the result you’d get if the nesting were manually expanded out into non-nested rules, since the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color③">color: blue</a> declaration would then be matching due to the <span class="css">b c</span> selector ([0,0,2]) rather than <span class="css">#a c</span> ([1,0,1]).</p> </div> <details class="note"> <summary>Why is the specificity different than non-nested rules?</summary> <p>The <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector⑨">nesting selector</a> intentionally uses the same specificity rules as the <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo④">:is()</a> pseudoclass, which just uses the largest specificity among its arguments, rather than tracking <em>which</em> selector actually matched.</p> <p>This is required for performance reasons; if a selector has multiple possible specificities, depending on how precisely it was matched, it makes selector matching much more complicated and slower.</p> <p>That skirts the question, tho: why <em>do</em> we define <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①①">&</a> in terms of <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo⑤">:is()</a>? Some non-browser implementations of Nesting-like functionality do <em>not</em> desugar to <span class="css" id="ref-for-matches-pseudo⑥">:is()</span>, largely because they predate the introduction of <span class="css" id="ref-for-matches-pseudo⑦">:is()</span> as well. Instead, they desugar directly; however, this comes with its own <em>significant</em> problems, as some (reasonably common) cases can accidentally produce <em>massive</em> selectors, due to the exponential explosion of possibilities.</p> <pre class="lang-css highlight">.a1<c- p>,</c-> .a2<c- p>,</c-> .a3 <c- p>{</c-> .b1<c- p>,</c-> .b2<c- p>,</c-> .b3 <c- p>{</c-> .c1<c- p>,</c-> .c2<c- p>,</c-> .c3 <c- p>{</c-> ...<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> <c- c>/* naively desugars to */</c-> .a1 .b1 .c1<c- p>,</c-> .a1 .b1 .c2<c- p>,</c-> .a1 .b1 .c3<c- p>,</c-> .a1 .b2 .c1<c- p>,</c-> .a1 .b2 .c2<c- p>,</c-> .a1 .b2 .c3<c- p>,</c-> .a1 .b3 .c1<c- p>,</c-> .a1 .b3 .c2<c- p>,</c-> .a1 .b3 .c3<c- p>,</c-> .a2 .b1 .c1<c- p>,</c-> .a2 .b1 .c2<c- p>,</c-> .a2 .b1 .c3<c- p>,</c-> .a2 .b2 .c1<c- p>,</c-> .a2 .b2 .c2<c- p>,</c-> .a2 .b2 .c3<c- p>,</c-> .a2 .b3 .c1<c- p>,</c-> .a2 .b3 .c2<c- p>,</c-> .a2 .b3 .c3<c- p>,</c-> .a3 .b1 .c1<c- p>,</c-> .a3 .b1 .c2<c- p>,</c-> .a3 .b1 .c3<c- p>,</c-> .a3 .b2 .c1<c- p>,</c-> .a3 .b2 .c2<c- p>,</c-> .a3 .b2 .c3<c- p>,</c-> .a3 .b3 .c1<c- p>,</c-> .a3 .b3 .c2<c- p>,</c-> .a3 .b3 .c3 <c- p>{</c->...<c- p>}</c-> </pre> <p>Here, three levels of nesting, each with three selectors in their lists, produced 27 desugared selectors. Adding more selectors to the lists, adding more levels of nesting, or making the nested rules more complex can make a relatively small rule expand into multiple megabytes of selectors (or much, much more!).</p> <p>Some CSS tools avoid the worst of this by heuristically discarding some variations, so they don’t have to output as much but are still <em>probably</em> correct, but that’s not an option available to UAs.</p> <p>Desugaring with <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo" id="ref-for-matches-pseudo⑧">:is()</a> instead eliminates this problem entirely, at the cost of making specificity slightly less useful, which was judged a reasonable trade-off.</p> </details> <p>The <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector①⓪">nesting selector</a> is capable of matching <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#featureless" id="ref-for-featureless">featureless</a> elements, if they were matched by the parent rule.</p> <p>While the position of a <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector①①">nesting selector</a> in a <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#compound" id="ref-for-compound">compound selector</a> does not make a difference in its behavior (that is, <span class="css">&.foo</span> and <span class="css">.foo&</span> match the same elements), the existing rule that a <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#type-selector" id="ref-for-type-selector">type selector</a>, if present, must be first in the <span id="ref-for-compound①">compound selector</span> continues to apply (that is, <span class="css">&div</span> is illegal, and must be written <span class="css">div&</span> instead).</p> <h2 class="heading settled" data-level="5" id="nested-declarations-rule"><span class="secno">5. </span><span class="content"> The Nested Declarations Rule</span><a class="self-link" href="#nested-declarations-rule"></a></h2> <p>For somewhat-technical reasons, it’s important to be able to distinguish properties that appear at the start of a style rule’s contents from those that appear interspersed with other rules.</p> <div class="example" id="example-b6fcbb18"> <a class="self-link" href="#example-b6fcbb18"></a> For example, in the following two rules: <pre class="language-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->...<c- p>)</c-> <c- p>{</c->...<c- p>}</c-> background: blue<c- p>;</c-> <c- p>}</c-> </pre> <p>We need to treat the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color④">color: red</a> and <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background" id="ref-for-propdef-background">background: blue</a> slightly differently. In particular, in the CSSOM, the <span class="css" id="ref-for-propdef-color⑤">color: red</span> is exposed in the style rule’s <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style" id="ref-for-dom-cssstylerule-style">style</a></code> attribute, while the <span class="css" id="ref-for-propdef-background①">background: blue</span> needs to instead show up in its <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-cssrules" id="ref-for-dom-cssgroupingrule-cssrules">cssRules</a></code> list.</p> </div> <p>To accomplish this, CSS parsing <em>automatically</em> wraps such properties in a special child rule to contain them. However, if we were to wrap them in a <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#style-rule" id="ref-for-style-rule⑥">style rule</a> with an <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①②">&</a> selector, it would have somewhat unfortunate behavior:</p> <div class="example" id="example-a4638964"> <a class="self-link" href="#example-a4638964"></a> For example, in <pre class="language-css highlight">.foo<c- p>,</c-> .foo::before <c- p>{</c-> <c- k>color</c-><c- p>:</c-> red<c- p>;</c-> & <c- p>{</c-> <c- k>background</c-><c- p>:</c-> blue<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>the nested rule <em>does not</em> apply the <a class="property css" data-link-type="property" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background" id="ref-for-propdef-background②">background</a> property to the <span class="css">.foo::before</span> elements, because the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①③">&</a> can’t represent pseudo-elements.</p> </div> <p>Similarly, child declarations in nested non-style rules need to be exposed as <a data-link-type="dfn" href="https://drafts.csswg.org/css-syntax-3/#css-rule" id="ref-for-css-rule">rules</a> in some way, because these sorts of rules (like <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-media" id="ref-for-at-ruledef-media①">@media</a>) have never had <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style" id="ref-for-dom-cssstylerule-style①">style</a></code> properties. These run into the same problems as above.</p> <p>To address all of these issue, we instead wrap runs of consecutive directly-nested properties in a <dfn class="dfn-paneled" data-dfn-type="dfn" data-export id="nested-declarations-rule①">nested declarations rule</dfn>.</p> <p>Unless otherwise specified, a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①④">nested declarations rule</a> is a <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule①①">nested style rule</a>, and acts identically to any other style rule. It matches the exact same elements and pseudo-elements as its parent style rule, with the same specificity behavior. <span class="note">(This is <em>similar to</em> being a style rule with an <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①④">&</a> selector, but slightly more powerful, as explained above.)</span></p> <details class="note"> <summary>Why does the <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①⑤">nested declarations rule</a> exist?</summary> <p>Originally, this specification grouped all declarations in style rules together, "moving" them from their original location to act as if they were placed at the front of the rule. It also automatically wrapped raw declarations inside of <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules⑥">nested group rules</a> in plain style rules, using the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①⑤">&</a> selector.</p> <p>There are two major reasons we switched to instead use the <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①⑥">nested declarations rule</a>.</p> <p>First, using an <span class="css">& {...}</span> rule to implicitly wrap declarations in a <a data-link-type="dfn" href="#nested-group-rules" id="ref-for-nested-group-rules⑦">nested group rule</a> also changed the behavior. As shown in the example following this note, it breaks cases where the parent style rule contains pseudo-elements, and even when that’s not the case, it potentially changes the specificity behavior of the nested declarations. Switching to the <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①⑦">nested declarations rule</a> avoids these problems, making the behavior of nested <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-conditional-3/#at-ruledef-media" id="ref-for-at-ruledef-media②">@media</a>/etc identical to the behavior of *non*-nested <span class="css" id="ref-for-at-ruledef-media③">@media</span>/etc.</p> <p>Second, there are some details of future CSS features (notably, "mixins") that simply won’t work correctly if interleaved declarations are automatically moved to the front of the style rule. We need to keep their relative order with other rules, and in order to actually make that representable in the CSSOM, that means they have to be wrapped in some kind of rule. The same issues as the previous paragraph apply if we just use a normal <span class="css">& {...}</span> rule, so the <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①⑧">nested declarations rule</a> lets us do so without side effects.</p> </details> <div class="example" id="example-cef45fb3"> <a class="self-link" href="#example-cef45fb3"></a> For example, in the following stylesheet snippet: <pre class="language-css highlight">.foo<c- p>,</c-> .foo::before<c- p>,</c-> .foo::after <c- p>{</c-> <c- k>color</c-><c- p>:</c-> black<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->prefers-color-scheme: dark<c- p>)</c-> <c- p>{</c-> & <c- p>{</c-> <c- k>color</c-><c- p>:</c-> white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>In a darkmode page, the <span class="css">.foo</span> element would have its text color changed to white, but its <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-pseudo-4/#selectordef-before" id="ref-for-selectordef-before">::before</a> and <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/css-pseudo-4/#selectordef-after" id="ref-for-selectordef-after">::after</a> pseudos would remain black, because the <a class="css" data-link-type="maybe" href="#selectordef-" id="ref-for-selectordef-①⑥">&</a> selector can’t represent pseudo-elements.</p> <p>However, it was instead written as:</p> <pre class="language-css highlight">.foo<c- p>,</c-> .foo::before<c- p>,</c-> .foo::after <c- p>{</c-> <c- k>color</c-><c- p>:</c-> black<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->prefers-color-scheme: dark<c- p>)</c-> <c- p>{</c-> <c- k>color</c-><c- p>:</c-> white<c- p>;</c-> <c- p>}</c-> <c- p>}</c-> </pre> <p>Then the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color⑥">color: white</a> is implicitly wrapped in a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①⑨">nested declarations rule</a>, which is guaranteed to match <em>exactly</em> the same as its parent style rule, so the element <em>and</em> its pseudo-elements would all have white text in a darkmode page.</p> </div> <div class="example" id="example-c3bca626"> <a class="self-link" href="#example-c3bca626"></a> Declarations interleaved with rules get implicitly wrapped in a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①⓪">nested declarations rule</a>, which makes them part of a separate style rule. For example, given this CSS: <pre class="language-css highlight">.foo <c- p>{</c-> <c- k>color</c-><c- p>:</c-> black<c- p>;</c-> <c- n>@media</c-> <c- p>(</c->...<c- p>)</c-> <c- p>{</c->...<c- p>}</c-> background: silver<c- p>;</c-> <c- p>}</c-> </pre> <p>If the <span class="css">.foo</span> rule’s CSSOM object is examined, its <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style" id="ref-for-dom-cssstylerule-style②">style</a></code> attribute will contain only one declaration: the <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-color-4/#propdef-color" id="ref-for-propdef-color⑦">color: black</a> one.</p> <p>The <a class="css" data-link-type="propdesc" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background" id="ref-for-propdef-background③">background: silver</a> declaration will instead be found in the implicitly-created <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①①">nested declarations child rule</a>, at <code class="highlight">fooRule<c- p>.</c->cssRules<c- p>[</c-><c- mf>1</c-><c- p>].</c->style</code>.</p> </div> <h2 class="heading settled" data-level="6" id="cssom"><span class="secno">6. </span><span class="content">CSSOM</span><a class="self-link" href="#cssom"></a></h2> <p class="note" role="note"><span class="marker">Note:</span> <a data-link-type="biblio" href="#biblio-cssom-1" title="CSS Object Model (CSSOM)">[CSSOM-1]</a> now defines that <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#cssstylerule" id="ref-for-cssstylerule">CSSStyleRule</a></code> can have child rules.</p> <p>When serializing a <a data-link-type="dfn" href="https://drafts.csswg.org/selectors-4/#relative-selector" id="ref-for-relative-selector⑥">relative selector</a> in a <a data-link-type="dfn" href="#nested-style-rule" id="ref-for-nested-style-rule①②">nested style rule</a>, the selector must be absolutized, with the implied <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector①②">nesting selector</a> inserted.</p> <div class="example" id="example-724b564c"><a class="self-link" href="#example-724b564c"></a> For example, the selector <span class="css">> .foo</span> will serialize as <span class="css">& > .foo</span>. </div> <h3 class="heading settled" data-level="6.1" id="the-cssnestrule"><span class="secno">6.1. </span><span class="content">The <code class="idl"><a data-link-type="idl" href="#cssnesteddeclarations" id="ref-for-cssnesteddeclarations">CSSNestedDeclarations</a></code> Interface</span><a class="self-link" href="#the-cssnestrule"></a></h3> <p>The <code class="idl"><a data-link-type="idl" href="#cssnesteddeclarations" id="ref-for-cssnesteddeclarations①">CSSNestedDeclarations</a></code> interface represents a <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①②">nested declarations rule</a>.</p> <pre class="idl highlight def">[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#Exposed" id="ref-for-Exposed"><c- g>Exposed</c-></a>=<c- n>Window</c->] <c- b>interface</c-> <dfn class="dfn-paneled idl-code" data-dfn-type="interface" data-export id="cssnesteddeclarations"><code class="highlight"><c- g>CSSNestedDeclarations</c-></code></dfn> : <a data-link-type="idl-name" href="https://drafts.csswg.org/cssom-1/#cssrule" id="ref-for-cssrule"><c- n>CSSRule</c-></a> { [<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#SameObject" id="ref-for-SameObject"><c- g>SameObject</c-></a>, <a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#PutForwards" id="ref-for-PutForwards"><c- g>PutForwards</c-></a>=<a class="idl-code" data-link-type="attribute"><c- n>cssText</c-></a>] <c- b>readonly</c-> <c- b>attribute</c-> <a data-link-type="idl-name" href="https://drafts.csswg.org/cssom-1/#cssstyleproperties" id="ref-for-cssstyleproperties"><c- n>CSSStyleProperties</c-></a> <a class="idl-code" data-link-type="attribute" data-readonly data-type="CSSStyleProperties" href="#dom-cssnesteddeclarations-style" id="ref-for-dom-cssnesteddeclarations-style"><c- g>style</c-></a>; }; </pre> <div class="algorithm" data-algorithm="style" data-algorithm-for="CSSNestedDeclarations"> The <dfn class="dfn-paneled idl-code" data-dfn-for="CSSNestedDeclarations" data-dfn-type="attribute" data-export id="dom-cssnesteddeclarations-style"><code class="highlight">style</code></dfn> attribute must return a <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#cssstyleproperties" id="ref-for-cssstyleproperties①">CSSStyleProperties</a></code> object for the rule, with the following properties: <dl> <dt data-md><a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-computed-flag" id="ref-for-cssstyledeclaration-computed-flag">computed flag</a> <dd data-md> <p>Unset</p> <dt data-md><a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-readonly-flag" id="ref-for-cssstyledeclaration-readonly-flag">readonly flag</a> <dd data-md> <p>Unset</p> <dt data-md><a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-declarations" id="ref-for-cssstyledeclaration-declarations①">declarations</a> <dd data-md> <p>The declared declarations in the rule, in <a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#concept-declarations-specified-order" id="ref-for-concept-declarations-specified-order">specified order</a>.</p> <dt data-md><a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-parent-css-rule" id="ref-for-cssstyledeclaration-parent-css-rule">parent CSS rule</a> <dd data-md> <p><a data-link-type="dfn" href="https://webidl.spec.whatwg.org/#this" id="ref-for-this">this</a></p> <dt data-md><a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#cssstyledeclaration-owner-node" id="ref-for-cssstyledeclaration-owner-node">owner node</a> <dd data-md> <p>Null</p> </dl> </div> <p>The <code class="idl"><a data-link-type="idl" href="#cssnesteddeclarations" id="ref-for-cssnesteddeclarations②">CSSNestedDeclarations</a></code> rule <a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#serialize-a-css-rule" id="ref-for-serialize-a-css-rule">serializes</a> as if its <a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#css-declaration-block" id="ref-for-css-declaration-block">declaration block</a> had been <a data-link-type="dfn" href="https://drafts.csswg.org/cssom-1/#serialize-a-css-declaration-block" id="ref-for-serialize-a-css-declaration-block">serialized</a> directly.</p> <p class="note" role="note"><span class="marker">Note:</span> This means that multiple adjacent <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①③">nested declarations rules</a> (which is possible to create with e.g. <code class="idl"><a data-link-type="idl" href="https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-insertrule" id="ref-for-dom-cssgroupingrule-insertrule">insertRule</a></code>) will collapse into a single rule when serialized and parsed again.</p> <h3 class="heading settled" data-level="6.2" id="changes"><span class="secno">6.2. </span><span class="content">Changes</span><a class="self-link" href="#changes"></a></h3> <p>Significant changes since the <a href="https://www.w3.org/TR/2023/WD-css-nesting-1-20230214/">Feb 14, 2023 Working Draft</a>:</p> <ul> <li data-md> <p>Clarified that the <a data-link-type="dfn" href="#nesting-selector" id="ref-for-nesting-selector①③">nesting selector</a> is allowed to match featureless elements.</p> <li data-md> <p>Switched <span class="css">&div</span> back to being invalid; now that Syntax does "infinite lookahead", we no longer need to allow it. Plus, doing so avoids a clash with preprocessors. (<a href="https://github.com/w3c/csswg-drafts/issues/8662">Issue 8662</a>)</p> <li data-md> <p>CSSOM now defines that CSSStyleRule is a CSSGroupingRule subclass, so the manual definition of the <code class="highlight">cssRules</code> attribute and related machinery was removed. (<a href="https://github.com/w3c/csswg-drafts/issues/8940">Issue 8940</a>)</p> <li data-md> <p>Clarified the effect of the <em>implied</em> nesting selector on specificity. (<a href="https://github.com/w3c/csswg-drafts/issues/9069">Issue 9069</a>)</p> <li data-md> <p>Declarations intermixed with rules (or all declarations in nested group rules) are now automatically wrapped in <code class="highlight"><c- n>@nest</c-></code> rules. (Also the <code class="highlight"><c- n>@nest</c-></code> rule was added.) (<a href="https://github.com/w3c/csswg-drafts/issues/8738">Issue 8738</a>)</p> <li data-md> <p>Replaced <code class="highlight"><c- n>@nest</c-></code> with <a data-link-type="dfn" href="#nested-declarations-rule①" id="ref-for-nested-declarations-rule①①④">nested declarations rules</a>. (<a href="https://github.com/w3c/csswg-drafts/issues/10234">Issue 10234</a>)</p> </ul> </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> <details class="wpt-tests-block" dir="ltr" lang="en" open> <summary>Tests</summary> <p>Tests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.</p> <ul class="wpt-tests-list"></ul> <hr> </details> <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="#selectordef-">&</a><span>, in § 4</span> <li><a href="#contain-the-nesting-selector">contain the nesting selector</a><span>, in § 3.1</span> <li><a href="#cssnesteddeclarations">CSSNestedDeclarations</a><span>, in § 6.1</span> <li><a href="#nested-declarations-rule①">nested declarations rule</a><span>, in § 5</span> <li><a href="#nested-group-rules">nested group rules</a><span>, in § 3.3</span> <li><a href="#nested-style-rule">nested style rule</a><span>, in § 3</span> <li><a href="#nesting-selector">nesting selector</a><span>, in § 4</span> <li><a href="#nested-style-rule">nesting style rule</a><span>, in § 3</span> <li><a href="#dom-cssnesteddeclarations-style">style</a><span>, in § 6.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-BACKGROUNDS-3]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="f5eca8c9">background</span> </ul> <li> <a data-link-type="biblio">[CSS-CASCADE-5]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="94b8f87c">@layer</span> </ul> <li> <a data-link-type="biblio">[CSS-CASCADE-6]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="3024450a"><scope-end></span> <li><span class="dfn-paneled" id="2b1bb297"><scope-start></span> <li><span class="dfn-paneled" id="84b13f54">@scope</span> </ul> <li> <a data-link-type="biblio">[CSS-COLOR-4]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="73ea1d43">color</span> </ul> <li> <a data-link-type="biblio">[CSS-CONDITIONAL-3]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="5f1b7f60">@media</span> <li><span class="dfn-paneled" id="c1ebc639">@supports</span> <li><span class="dfn-paneled" id="bf3ca8a7">conditional group rule</span> </ul> <li> <a data-link-type="biblio">[CSS-CONDITIONAL-5]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="4ecd1e40">@container</span> </ul> <li> <a data-link-type="biblio">[CSS-PSEUDO-4]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="fd0c9e35">::after</span> <li><span class="dfn-paneled" id="5869f885">::before</span> </ul> <li> <a data-link-type="biblio">[CSS-SYNTAX-3]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="b845e85c"><block-contents></span> <li><span class="dfn-paneled" id="860c17f8"><delim-token></span> <li><span class="dfn-paneled" id="65c9f2cf"><rule-list></span> <li><span class="dfn-paneled" id="762610c7">at-rule</span> <li><span class="dfn-paneled" id="76c4403d">parse</span> <li><span class="dfn-paneled" id="4fcdc12a">rule</span> <li><span class="dfn-paneled" id="5a58bbb0">style rule</span> </ul> <li> <a data-link-type="biblio">[CSS-UI-4]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="95a44e84">bar</span> </ul> <li> <a data-link-type="biblio">[CSSOM-1]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="ebaeb088">CSSRule</span> <li><span class="dfn-paneled" id="f9bcb636">CSSStyleProperties</span> <li><span class="dfn-paneled" id="6052f41c">CSSStyleRule</span> <li><span class="dfn-paneled" id="29c3f2fe">computed flag</span> <li><span class="dfn-paneled" id="a06e5a78">CSS declaration block</span> <li><span class="dfn-paneled" id="ab65c5d7">cssRules</span> <li><span class="dfn-paneled" id="e4ffca7f">declarations</span> <li><span class="dfn-paneled" id="67ed446d">insertRule(rule)</span> <li><span class="dfn-paneled" id="eab73120">owner node</span> <li><span class="dfn-paneled" id="8056dead">parent CSS rule</span> <li><span class="dfn-paneled" id="6eabcb67">readonly flag</span> <li><span class="dfn-paneled" id="2c2c4b46">serialize a CSS declaration block</span> <li><span class="dfn-paneled" id="8c57eaed">serialize a CSS rule</span> <li><span class="dfn-paneled" id="c475bc01">specified order</span> <li><span class="dfn-paneled" id="b0fef56e">style</span> </ul> <li> <a data-link-type="biblio">[SELECTORS-4]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="b4d48921">:is()</span> <li><span class="dfn-paneled" id="dc55c3d9">:scope</span> <li><span class="dfn-paneled" id="d4c9ac12">:where()</span> <li><span class="dfn-paneled" id="fd154ab3"><forgiving-selector-list></span> <li><span class="dfn-paneled" id="ea722d19"><relative-selector-list></span> <li><span class="dfn-paneled" id="71aed09f"><selector-list></span> <li><span class="dfn-paneled" id="f4fc17d1">combinator</span> <li><span class="dfn-paneled" id="24408a11">compound selector</span> <li><span class="dfn-paneled" id="5f4f98ab">descendant combinator</span> <li><span class="dfn-paneled" id="3a1154bf">featureless</span> <li><span class="dfn-paneled" id="4cd9dfd7">relative selector</span> <li><span class="dfn-paneled" id="2fd70eda">simple selector</span> <li><span class="dfn-paneled" id="bb2056aa">specificity</span> <li><span class="dfn-paneled" id="32c45571">type selector</span> </ul> <li> <a data-link-type="biblio">[WEBIDL]</a> defines the following terms: <ul> <li><span class="dfn-paneled" id="889e932f">Exposed</span> <li><span class="dfn-paneled" id="21ecf38f">PutForwards</span> <li><span class="dfn-paneled" id="a5c91173">SameObject</span> <li><span class="dfn-paneled" id="4013a022">this</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-4">[CSS-CASCADE-4] <dd>Elika Etemad; Tab Atkins Jr.. <a href="https://drafts.csswg.org/css-cascade-4/"><cite>CSS Cascading and Inheritance Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-cascade-4/">https://drafts.csswg.org/css-cascade-4/</a> <dt id="biblio-css-cascade-6">[CSS-CASCADE-6] <dd>Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. <a href="https://drafts.csswg.org/css-cascade-6/"><cite>CSS Cascading and Inheritance Level 6</cite></a>. URL: <a href="https://drafts.csswg.org/css-cascade-6/">https://drafts.csswg.org/css-cascade-6/</a> <dt id="biblio-css-color-4">[CSS-COLOR-4] <dd>Chris Lilley; Tab Atkins Jr.; Lea Verou. <a href="https://drafts.csswg.org/css-color-4/"><cite>CSS Color Module Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-color-4/">https://drafts.csswg.org/css-color-4/</a> <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-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-css21">[CSS21] <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-cssom-1">[CSSOM-1] <dd>Daniel Glazman; Emilio Cobos Álvarez. <a href="https://drafts.csswg.org/cssom/"><cite>CSS Object Model (CSSOM)</cite></a>. URL: <a href="https://drafts.csswg.org/cssom/">https://drafts.csswg.org/cssom/</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> <dt id="biblio-selectors-4">[SELECTORS-4] <dd>Elika Etemad; Tab Atkins Jr.. <a href="https://drafts.csswg.org/selectors/"><cite>Selectors Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/selectors/">https://drafts.csswg.org/selectors/</a> <dt id="biblio-webidl">[WEBIDL] <dd>Edgar Chen; Timothy Gu. <a href="https://webidl.spec.whatwg.org/"><cite>Web IDL Standard</cite></a>. Living Standard. URL: <a href="https://webidl.spec.whatwg.org/">https://webidl.spec.whatwg.org/</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-backgrounds-3">[CSS-BACKGROUNDS-3] <dd>Elika Etemad; Brad Kemper. <a href="https://drafts.csswg.org/css-backgrounds/"><cite>CSS Backgrounds and Borders Module Level 3</cite></a>. URL: <a href="https://drafts.csswg.org/css-backgrounds/">https://drafts.csswg.org/css-backgrounds/</a> <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-conditional-5">[CSS-CONDITIONAL-5] <dd>Chris Lilley; et al. <a href="https://drafts.csswg.org/css-conditional-5/"><cite>CSS Conditional Rules Module Level 5</cite></a>. URL: <a href="https://drafts.csswg.org/css-conditional-5/">https://drafts.csswg.org/css-conditional-5/</a> <dt id="biblio-css-pseudo-4">[CSS-PSEUDO-4] <dd>Daniel Glazman; Elika Etemad; Alan Stearns. <a href="https://drafts.csswg.org/css-pseudo-4/"><cite>CSS Pseudo-Elements Module Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-pseudo-4/">https://drafts.csswg.org/css-pseudo-4/</a> <dt id="biblio-css-ui-4">[CSS-UI-4] <dd>Florian Rivoal. <a href="https://drafts.csswg.org/css-ui-4/"><cite>CSS Basic User Interface Module Level 4</cite></a>. URL: <a href="https://drafts.csswg.org/css-ui-4/">https://drafts.csswg.org/css-ui-4/</a> </dl> <h2 class="no-num no-ref heading settled" id="idl-index"><span class="content">IDL Index</span><a class="self-link" href="#idl-index"></a></h2> <pre class="idl highlight def">[<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#Exposed"><c- g>Exposed</c-></a>=<c- n>Window</c->] <c- b>interface</c-> <a href="#cssnesteddeclarations"><code class="highlight"><c- g>CSSNestedDeclarations</c-></code></a> : <a data-link-type="idl-name" href="https://drafts.csswg.org/cssom-1/#cssrule"><c- n>CSSRule</c-></a> { [<a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#SameObject"><c- g>SameObject</c-></a>, <a class="idl-code" data-link-type="extended-attribute" href="https://webidl.spec.whatwg.org/#PutForwards"><c- g>PutForwards</c-></a>=<a class="idl-code" data-link-type="attribute"><c- n>cssText</c-></a>] <c- b>readonly</c-> <c- b>attribute</c-> <a data-link-type="idl-name" href="https://drafts.csswg.org/cssom-1/#cssstyleproperties"><c- n>CSSStyleProperties</c-></a> <a class="idl-code" data-link-type="attribute" data-readonly data-type="CSSStyleProperties" href="#dom-cssnesteddeclarations-style"><c- g>style</c-></a>; }; </pre> <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"> The preceding paragraph needs to move to Selectors when we move <a class="css" data-link-type="maybe" href="#selectordef-">&</a> itself to Selectors; I’m monkey-patching for convenience here. <a class="issue-return" href="#issue-03f974e2" title="Jump to section">↵</a></div> <div class="issue"> We’d like to relax this restriction, but need to do so simultaneously for both <a class="css" data-link-type="maybe" href="https://drafts.csswg.org/selectors-4/#matches-pseudo">:is()</a> and <a class="css" data-link-type="maybe" href="#selectordef-">&</a>, since they’re intentionally built on the same underlying mechanisms. (<a href="https://github.com/w3c/csswg-drafts/issues/7433">Issue 7433</a>) <a class="issue-return" href="#issue-62c479a8" 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 = { "21ecf38f": {"dfnID":"21ecf38f","dfnText":"PutForwards","external":true,"refSections":[{"refs":[{"id":"ref-for-PutForwards"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://webidl.spec.whatwg.org/#PutForwards"}, "24408a11": {"dfnID":"24408a11","dfnText":"compound selector","external":true,"refSections":[{"refs":[{"id":"ref-for-compound"},{"id":"ref-for-compound\u2460"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#compound"}, "29c3f2fe": {"dfnID":"29c3f2fe","dfnText":"computed flag","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyledeclaration-computed-flag"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-computed-flag"}, "2b1bb297": {"dfnID":"2b1bb297","dfnText":"<scope-start>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-scope-start"},{"id":"ref-for-typedef-scope-start\u2460"}],"title":"3.3.1. \nNested @scope Rules"}],"url":"https://drafts.csswg.org/css-cascade-6/#typedef-scope-start"}, "2c2c4b46": {"dfnID":"2c2c4b46","dfnText":"serialize a CSS declaration block","external":true,"refSections":[{"refs":[{"id":"ref-for-serialize-a-css-declaration-block"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#serialize-a-css-declaration-block"}, "2fd70eda": {"dfnID":"2fd70eda","dfnText":"simple selector","external":true,"refSections":[{"refs":[{"id":"ref-for-simple"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/selectors-4/#simple"}, "3024450a": {"dfnID":"3024450a","dfnText":"<scope-end>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-scope-end"}],"title":"3.3.1. \nNested @scope Rules"}],"url":"https://drafts.csswg.org/css-cascade-6/#typedef-scope-end"}, "32c45571": {"dfnID":"32c45571","dfnText":"type selector","external":true,"refSections":[{"refs":[{"id":"ref-for-type-selector"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#type-selector"}, "3a1154bf": {"dfnID":"3a1154bf","dfnText":"featureless","external":true,"refSections":[{"refs":[{"id":"ref-for-featureless"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#featureless"}, "4013a022": {"dfnID":"4013a022","dfnText":"this","external":true,"refSections":[{"refs":[{"id":"ref-for-this"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://webidl.spec.whatwg.org/#this"}, "4cd9dfd7": {"dfnID":"4cd9dfd7","dfnText":"relative selector","external":true,"refSections":[{"refs":[{"id":"ref-for-relative-selector"},{"id":"ref-for-relative-selector\u2460"}],"title":"3. Nesting Style Rules"},{"refs":[{"id":"ref-for-relative-selector\u2461"},{"id":"ref-for-relative-selector\u2462"},{"id":"ref-for-relative-selector\u2463"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-relative-selector\u2464"}],"title":"3.2. \nExamples"},{"refs":[{"id":"ref-for-relative-selector\u2465"}],"title":"6. CSSOM"}],"url":"https://drafts.csswg.org/selectors-4/#relative-selector"}, "4ecd1e40": {"dfnID":"4ecd1e40","dfnText":"@container","external":true,"refSections":[{"refs":[{"id":"ref-for-at-ruledef-container"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-conditional-5/#at-ruledef-container"}, "4fcdc12a": {"dfnID":"4fcdc12a","dfnText":"rule","external":true,"refSections":[{"refs":[{"id":"ref-for-css-rule"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-syntax-3/#css-rule"}, "5869f885": {"dfnID":"5869f885","dfnText":"::before","external":true,"refSections":[{"refs":[{"id":"ref-for-selectordef-before"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-pseudo-4/#selectordef-before"}, "5a58bbb0": {"dfnID":"5a58bbb0","dfnText":"style rule","external":true,"refSections":[{"refs":[{"id":"ref-for-style-rule"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-style-rule\u2460"},{"id":"ref-for-style-rule\u2461"},{"id":"ref-for-style-rule\u2462"},{"id":"ref-for-style-rule\u2463"},{"id":"ref-for-style-rule\u2464"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-style-rule\u2465"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-syntax-3/#style-rule"}, "5f1b7f60": {"dfnID":"5f1b7f60","dfnText":"@media","external":true,"refSections":[{"refs":[{"id":"ref-for-at-ruledef-media"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-at-ruledef-media\u2460"},{"id":"ref-for-at-ruledef-media\u2461"},{"id":"ref-for-at-ruledef-media\u2462"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-conditional-3/#at-ruledef-media"}, "5f4f98ab": {"dfnID":"5f4f98ab","dfnText":"descendant combinator","external":true,"refSections":[{"refs":[{"id":"ref-for-descendant-combinator"}],"title":"2. \nExplainer"}],"url":"https://drafts.csswg.org/selectors-4/#descendant-combinator"}, "6052f41c": {"dfnID":"6052f41c","dfnText":"CSSStyleRule","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstylerule"}],"title":"6. CSSOM"}],"url":"https://drafts.csswg.org/cssom-1/#cssstylerule"}, "65c9f2cf": {"dfnID":"65c9f2cf","dfnText":"<rule-list>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-rule-list"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-syntax-3/#typedef-rule-list"}, "67ed446d": {"dfnID":"67ed446d","dfnText":"insertRule(rule)","external":true,"refSections":[{"refs":[{"id":"ref-for-dom-cssgroupingrule-insertrule"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-insertrule"}, "6eabcb67": {"dfnID":"6eabcb67","dfnText":"readonly flag","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyledeclaration-readonly-flag"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-readonly-flag"}, "71aed09f": {"dfnID":"71aed09f","dfnText":"<selector-list>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-selector-list"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/selectors-4/#typedef-selector-list"}, "73ea1d43": {"dfnID":"73ea1d43","dfnText":"color","external":true,"refSections":[{"refs":[{"id":"ref-for-propdef-color"},{"id":"ref-for-propdef-color\u2460"},{"id":"ref-for-propdef-color\u2461"}],"title":"3.4. Mixing Nesting Rules and Declarations"},{"refs":[{"id":"ref-for-propdef-color\u2462"}],"title":"4. Nesting Selector: the & selector"},{"refs":[{"id":"ref-for-propdef-color\u2463"},{"id":"ref-for-propdef-color\u2464"},{"id":"ref-for-propdef-color\u2465"},{"id":"ref-for-propdef-color\u2466"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-color-4/#propdef-color"}, "762610c7": {"dfnID":"762610c7","dfnText":"at-rule","external":true,"refSections":[{"refs":[{"id":"ref-for-at-rule"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/css-syntax-3/#at-rule"}, "76c4403d": {"dfnID":"76c4403d","dfnText":"parse","external":true,"refSections":[{"refs":[{"id":"ref-for-css-parse-something-according-to-a-css-grammar"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/css-syntax-3/#css-parse-something-according-to-a-css-grammar"}, "8056dead": {"dfnID":"8056dead","dfnText":"parent CSS rule","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyledeclaration-parent-css-rule"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-parent-css-rule"}, "84b13f54": {"dfnID":"84b13f54","dfnText":"@scope","external":true,"refSections":[{"refs":[{"id":"ref-for-at-ruledef-scope"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-at-ruledef-scope\u2460"},{"id":"ref-for-at-ruledef-scope\u2461"},{"id":"ref-for-at-ruledef-scope\u2462"}],"title":"3.3.1. \nNested @scope Rules"}],"url":"https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope"}, "860c17f8": {"dfnID":"860c17f8","dfnText":"<delim-token>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-delim-token"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/css-syntax-3/#typedef-delim-token"}, "889e932f": {"dfnID":"889e932f","dfnText":"Exposed","external":true,"refSections":[{"refs":[{"id":"ref-for-Exposed"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://webidl.spec.whatwg.org/#Exposed"}, "8c57eaed": {"dfnID":"8c57eaed","dfnText":"serialize a CSS rule","external":true,"refSections":[{"refs":[{"id":"ref-for-serialize-a-css-rule"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#serialize-a-css-rule"}, "94b8f87c": {"dfnID":"94b8f87c","dfnText":"@layer","external":true,"refSections":[{"refs":[{"id":"ref-for-at-ruledef-layer"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-cascade-5/#at-ruledef-layer"}, "95a44e84": {"dfnID":"95a44e84","dfnText":"bar","external":true,"refSections":[{"refs":[{"id":"ref-for-valdef-caret-shape-bar"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/css-ui-4/#valdef-caret-shape-bar"}, "a06e5a78": {"dfnID":"a06e5a78","dfnText":"CSS declaration block","external":true,"refSections":[{"refs":[{"id":"ref-for-css-declaration-block"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#css-declaration-block"}, "a5c91173": {"dfnID":"a5c91173","dfnText":"SameObject","external":true,"refSections":[{"refs":[{"id":"ref-for-SameObject"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://webidl.spec.whatwg.org/#SameObject"}, "ab65c5d7": {"dfnID":"ab65c5d7","dfnText":"cssRules","external":true,"refSections":[{"refs":[{"id":"ref-for-dom-cssgroupingrule-cssrules"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-cssrules"}, "b0fef56e": {"dfnID":"b0fef56e","dfnText":"style","external":true,"refSections":[{"refs":[{"id":"ref-for-dom-cssstylerule-style"},{"id":"ref-for-dom-cssstylerule-style\u2460"},{"id":"ref-for-dom-cssstylerule-style\u2461"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style"}, "b4d48921": {"dfnID":"b4d48921","dfnText":":is()","external":true,"refSections":[{"refs":[{"id":"ref-for-matches-pseudo"},{"id":"ref-for-matches-pseudo\u2460"},{"id":"ref-for-matches-pseudo\u2461"},{"id":"ref-for-matches-pseudo\u2462"},{"id":"ref-for-matches-pseudo\u2463"},{"id":"ref-for-matches-pseudo\u2464"},{"id":"ref-for-matches-pseudo\u2465"},{"id":"ref-for-matches-pseudo\u2466"},{"id":"ref-for-matches-pseudo\u2467"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#matches-pseudo"}, "b845e85c": {"dfnID":"b845e85c","dfnText":"<block-contents>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-block-contents"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-syntax-3/#typedef-block-contents"}, "bb2056aa": {"dfnID":"bb2056aa","dfnText":"specificity","external":true,"refSections":[{"refs":[{"id":"ref-for-specificity"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#specificity"}, "bf3ca8a7": {"dfnID":"bf3ca8a7","dfnText":"conditional group rule","external":true,"refSections":[{"refs":[{"id":"ref-for-conditional-group-rule"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-conditional-3/#conditional-group-rule"}, "c1ebc639": {"dfnID":"c1ebc639","dfnText":"@supports","external":true,"refSections":[{"refs":[{"id":"ref-for-at-ruledef-supports"}],"title":"3.3. Nesting Other At-Rules"}],"url":"https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports"}, "c475bc01": {"dfnID":"c475bc01","dfnText":"specified order","external":true,"refSections":[{"refs":[{"id":"ref-for-concept-declarations-specified-order"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#concept-declarations-specified-order"}, "contain-the-nesting-selector": {"dfnID":"contain-the-nesting-selector","dfnText":"contain the nesting selector","external":false,"refSections":[{"refs":[{"id":"ref-for-contain-the-nesting-selector"},{"id":"ref-for-contain-the-nesting-selector\u2460"},{"id":"ref-for-contain-the-nesting-selector\u2461"}],"title":"3.1. Syntax"}],"url":"#contain-the-nesting-selector"}, "cssnesteddeclarations": {"dfnID":"cssnesteddeclarations","dfnText":"CSSNestedDeclarations","external":false,"refSections":[{"refs":[{"id":"ref-for-cssnesteddeclarations"},{"id":"ref-for-cssnesteddeclarations\u2460"},{"id":"ref-for-cssnesteddeclarations\u2461"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"#cssnesteddeclarations"}, "d4c9ac12": {"dfnID":"d4c9ac12","dfnText":":where()","external":true,"refSections":[{"refs":[{"id":"ref-for-where-pseudo"}],"title":"3.4. Mixing Nesting Rules and Declarations"}],"url":"https://drafts.csswg.org/selectors-4/#where-pseudo"}, "dc55c3d9": {"dfnID":"dc55c3d9","dfnText":":scope","external":true,"refSections":[{"refs":[{"id":"ref-for-scope-pseudo"}],"title":"4. Nesting Selector: the & selector"}],"url":"https://drafts.csswg.org/selectors-4/#scope-pseudo"}, "dom-cssnesteddeclarations-style": {"dfnID":"dom-cssnesteddeclarations-style","dfnText":"style","external":false,"refSections":[{"refs":[{"id":"ref-for-dom-cssnesteddeclarations-style"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"#dom-cssnesteddeclarations-style"}, "e4ffca7f": {"dfnID":"e4ffca7f","dfnText":"declarations","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyledeclaration-declarations"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-cssstyledeclaration-declarations\u2460"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-declarations"}, "ea722d19": {"dfnID":"ea722d19","dfnText":"<relative-selector-list>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-relative-selector-list"},{"id":"ref-for-typedef-relative-selector-list\u2460"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/selectors-4/#typedef-relative-selector-list"}, "eab73120": {"dfnID":"eab73120","dfnText":"owner node","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyledeclaration-owner-node"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-owner-node"}, "ebaeb088": {"dfnID":"ebaeb088","dfnText":"CSSRule","external":true,"refSections":[{"refs":[{"id":"ref-for-cssrule"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssrule"}, "f4fc17d1": {"dfnID":"f4fc17d1","dfnText":"combinator","external":true,"refSections":[{"refs":[{"id":"ref-for-selector-combinator"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/selectors-4/#selector-combinator"}, "f5eca8c9": {"dfnID":"f5eca8c9","dfnText":"background","external":true,"refSections":[{"refs":[{"id":"ref-for-propdef-background"},{"id":"ref-for-propdef-background\u2460"},{"id":"ref-for-propdef-background\u2461"},{"id":"ref-for-propdef-background\u2462"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-backgrounds-3/#propdef-background"}, "f9bcb636": {"dfnID":"f9bcb636","dfnText":"CSSStyleProperties","external":true,"refSections":[{"refs":[{"id":"ref-for-cssstyleproperties"},{"id":"ref-for-cssstyleproperties\u2460"}],"title":"6.1. The CSSNestedDeclarations Interface"}],"url":"https://drafts.csswg.org/cssom-1/#cssstyleproperties"}, "fd0c9e35": {"dfnID":"fd0c9e35","dfnText":"::after","external":true,"refSections":[{"refs":[{"id":"ref-for-selectordef-after"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"https://drafts.csswg.org/css-pseudo-4/#selectordef-after"}, "fd154ab3": {"dfnID":"fd154ab3","dfnText":"<forgiving-selector-list>","external":true,"refSections":[{"refs":[{"id":"ref-for-typedef-forgiving-selector-list"}],"title":"3.1. Syntax"}],"url":"https://drafts.csswg.org/selectors-4/#typedef-forgiving-selector-list"}, "nested-declarations-rule①": {"dfnID":"nested-declarations-rule\u2460","dfnText":"nested declarations rule","external":false,"refSections":[{"refs":[{"id":"ref-for-nested-declarations-rule\u2460"},{"id":"ref-for-nested-declarations-rule\u2460\u2460"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-nested-declarations-rule\u2460\u2461"},{"id":"ref-for-nested-declarations-rule\u2460\u2462"}],"title":"3.4. Mixing Nesting Rules and Declarations"},{"refs":[{"id":"ref-for-nested-declarations-rule\u2460\u2463"},{"id":"ref-for-nested-declarations-rule\u2460\u2464"},{"id":"ref-for-nested-declarations-rule\u2460\u2465"},{"id":"ref-for-nested-declarations-rule\u2460\u2466"},{"id":"ref-for-nested-declarations-rule\u2460\u2467"},{"id":"ref-for-nested-declarations-rule\u2460\u2468"},{"id":"ref-for-nested-declarations-rule\u2460\u2460\u24ea"},{"id":"ref-for-nested-declarations-rule\u2460\u2460\u2460"}],"title":"5. \nThe Nested Declarations Rule"},{"refs":[{"id":"ref-for-nested-declarations-rule\u2460\u2460\u2461"},{"id":"ref-for-nested-declarations-rule\u2460\u2460\u2462"}],"title":"6.1. The CSSNestedDeclarations Interface"},{"refs":[{"id":"ref-for-nested-declarations-rule\u2460\u2460\u2463"}],"title":"6.2. Changes"}],"url":"#nested-declarations-rule\u2460"}, "nested-group-rules": {"dfnID":"nested-group-rules","dfnText":"nested group rules","external":false,"refSections":[{"refs":[{"id":"ref-for-nested-group-rules"},{"id":"ref-for-nested-group-rules\u2460"},{"id":"ref-for-nested-group-rules\u2461"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-nested-group-rules\u2462"}],"title":"3.3.1. \nNested @scope Rules"},{"refs":[{"id":"ref-for-nested-group-rules\u2463"},{"id":"ref-for-nested-group-rules\u2464"}],"title":"3.4. Mixing Nesting Rules and Declarations"},{"refs":[{"id":"ref-for-nested-group-rules\u2465"},{"id":"ref-for-nested-group-rules\u2466"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"#nested-group-rules"}, "nested-style-rule": {"dfnID":"nested-style-rule","dfnText":"nested style rules","external":false,"refSections":[{"refs":[{"id":"ref-for-nested-style-rule"}],"title":"3. Nesting Style Rules"},{"refs":[{"id":"ref-for-nested-style-rule\u2460"},{"id":"ref-for-nested-style-rule\u2461"},{"id":"ref-for-nested-style-rule\u2462"},{"id":"ref-for-nested-style-rule\u2463"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-nested-style-rule\u2464"},{"id":"ref-for-nested-style-rule\u2465"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-nested-style-rule\u2466"},{"id":"ref-for-nested-style-rule\u2467"}],"title":"3.4. Mixing Nesting Rules and Declarations"},{"refs":[{"id":"ref-for-nested-style-rule\u2468"},{"id":"ref-for-nested-style-rule\u2460\u24ea"}],"title":"4. Nesting Selector: the & selector"},{"refs":[{"id":"ref-for-nested-style-rule\u2460\u2460"}],"title":"5. \nThe Nested Declarations Rule"},{"refs":[{"id":"ref-for-nested-style-rule\u2460\u2461"}],"title":"6. CSSOM"}],"url":"#nested-style-rule"}, "nesting-selector": {"dfnID":"nesting-selector","dfnText":"nesting selector","external":false,"refSections":[{"refs":[{"id":"ref-for-nesting-selector"}],"title":"3. Nesting Style Rules"},{"refs":[{"id":"ref-for-nesting-selector\u2460"},{"id":"ref-for-nesting-selector\u2461"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-nesting-selector\u2462"}],"title":"3.3. Nesting Other At-Rules"},{"refs":[{"id":"ref-for-nesting-selector\u2463"}],"title":"3.4. Mixing Nesting Rules and Declarations"},{"refs":[{"id":"ref-for-nesting-selector\u2464"},{"id":"ref-for-nesting-selector\u2465"},{"id":"ref-for-nesting-selector\u2466"},{"id":"ref-for-nesting-selector\u2467"},{"id":"ref-for-nesting-selector\u2468"},{"id":"ref-for-nesting-selector\u2460\u24ea"},{"id":"ref-for-nesting-selector\u2460\u2460"}],"title":"4. Nesting Selector: the & selector"},{"refs":[{"id":"ref-for-nesting-selector\u2460\u2461"}],"title":"6. CSSOM"},{"refs":[{"id":"ref-for-nesting-selector\u2460\u2462"}],"title":"6.2. Changes"}],"url":"#nesting-selector"}, "selectordef-": {"dfnID":"selectordef-","dfnText":"&","external":false,"refSections":[{"refs":[{"id":"ref-for-selectordef-"},{"id":"ref-for-selectordef-\u2460"},{"id":"ref-for-selectordef-\u2461"},{"id":"ref-for-selectordef-\u2462"}],"title":"2. \nExplainer"},{"refs":[{"id":"ref-for-selectordef-\u2463"},{"id":"ref-for-selectordef-\u2464"}],"title":"3.1. Syntax"},{"refs":[{"id":"ref-for-selectordef-\u2465"}],"title":"3.3.1. \nNested @scope Rules"},{"refs":[{"id":"ref-for-selectordef-\u2466"},{"id":"ref-for-selectordef-\u2467"},{"id":"ref-for-selectordef-\u2468"},{"id":"ref-for-selectordef-\u2460\u24ea"},{"id":"ref-for-selectordef-\u2460\u2460"}],"title":"4. Nesting Selector: the & selector"},{"refs":[{"id":"ref-for-selectordef-\u2460\u2461"},{"id":"ref-for-selectordef-\u2460\u2462"},{"id":"ref-for-selectordef-\u2460\u2463"},{"id":"ref-for-selectordef-\u2460\u2464"},{"id":"ref-for-selectordef-\u2460\u2465"}],"title":"5. \nThe Nested Declarations Rule"}],"url":"#selectordef-"}, }; 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-ref-hints */ "use strict"; { let refsData = { "#contain-the-nesting-selector": {"displayText":"contain the nesting selector","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"contain the nesting selector","type":"dfn","url":"#contain-the-nesting-selector"}, "#cssnesteddeclarations": {"displayText":"CSSNestedDeclarations","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"CSSNestedDeclarations","type":"interface","url":"#cssnesteddeclarations"}, "#dom-cssnesteddeclarations-style": {"displayText":"style","export":true,"for_":["CSSNestedDeclarations"],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"style","type":"attribute","url":"#dom-cssnesteddeclarations-style"}, "#nested-declarations-rule①": {"displayText":"nested declarations rule","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"nested declarations rule","type":"dfn","url":"#nested-declarations-rule\u2460"}, "#nested-group-rules": {"displayText":"nested group rules","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"nested group rules","type":"dfn","url":"#nested-group-rules"}, "#nested-style-rule": {"displayText":"nested style rule","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"nested style rule","type":"dfn","url":"#nested-style-rule"}, "#nesting-selector": {"displayText":"nesting selector","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"nesting selector","type":"dfn","url":"#nesting-selector"}, "#selectordef-": {"displayText":"&","export":true,"for_":[],"level":"1","normative":true,"shortname":"css-nesting","spec":"css-nesting-1","status":"local","text":"&","type":"selector","url":"#selectordef-"}, "https://drafts.csswg.org/css-backgrounds-3/#propdef-background": {"displayText":"background","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-backgrounds","spec":"css-backgrounds-3","status":"current","text":"background","type":"property","url":"https://drafts.csswg.org/css-backgrounds-3/#propdef-background"}, "https://drafts.csswg.org/css-cascade-5/#at-ruledef-layer": {"displayText":"@layer","export":true,"for_":[],"level":"5","normative":true,"shortname":"css-cascade","spec":"css-cascade-5","status":"current","text":"@layer","type":"at-rule","url":"https://drafts.csswg.org/css-cascade-5/#at-ruledef-layer"}, "https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope": {"displayText":"@scope","export":true,"for_":[],"level":"6","normative":true,"shortname":"css-cascade","spec":"css-cascade-6","status":"current","text":"@scope","type":"at-rule","url":"https://drafts.csswg.org/css-cascade-6/#at-ruledef-scope"}, "https://drafts.csswg.org/css-cascade-6/#typedef-scope-end": {"displayText":"<scope-end>","export":true,"for_":[],"level":"6","normative":true,"shortname":"css-cascade","spec":"css-cascade-6","status":"current","text":"<scope-end>","type":"type","url":"https://drafts.csswg.org/css-cascade-6/#typedef-scope-end"}, "https://drafts.csswg.org/css-cascade-6/#typedef-scope-start": {"displayText":"<scope-start>","export":true,"for_":[],"level":"6","normative":true,"shortname":"css-cascade","spec":"css-cascade-6","status":"current","text":"<scope-start>","type":"type","url":"https://drafts.csswg.org/css-cascade-6/#typedef-scope-start"}, "https://drafts.csswg.org/css-color-4/#propdef-color": {"displayText":"color","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-color","spec":"css-color-4","status":"current","text":"color","type":"property","url":"https://drafts.csswg.org/css-color-4/#propdef-color"}, "https://drafts.csswg.org/css-conditional-3/#at-ruledef-media": {"displayText":"@media","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-conditional","spec":"css-conditional-3","status":"current","text":"@media","type":"at-rule","url":"https://drafts.csswg.org/css-conditional-3/#at-ruledef-media"}, "https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports": {"displayText":"@supports","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-conditional","spec":"css-conditional-3","status":"current","text":"@supports","type":"at-rule","url":"https://drafts.csswg.org/css-conditional-3/#at-ruledef-supports"}, "https://drafts.csswg.org/css-conditional-3/#conditional-group-rule": {"displayText":"conditional group rule","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-conditional","spec":"css-conditional-3","status":"current","text":"conditional group rule","type":"dfn","url":"https://drafts.csswg.org/css-conditional-3/#conditional-group-rule"}, "https://drafts.csswg.org/css-conditional-5/#at-ruledef-container": {"displayText":"@container","export":true,"for_":[],"level":"5","normative":true,"shortname":"css-conditional","spec":"css-conditional-5","status":"current","text":"@container","type":"at-rule","url":"https://drafts.csswg.org/css-conditional-5/#at-ruledef-container"}, "https://drafts.csswg.org/css-pseudo-4/#selectordef-after": {"displayText":"::after","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-pseudo","spec":"css-pseudo-4","status":"current","text":"::after","type":"selector","url":"https://drafts.csswg.org/css-pseudo-4/#selectordef-after"}, "https://drafts.csswg.org/css-pseudo-4/#selectordef-before": {"displayText":"::before","export":true,"for_":[],"level":"4","normative":true,"shortname":"css-pseudo","spec":"css-pseudo-4","status":"current","text":"::before","type":"selector","url":"https://drafts.csswg.org/css-pseudo-4/#selectordef-before"}, "https://drafts.csswg.org/css-syntax-3/#at-rule": {"displayText":"at-rule","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"at-rule","type":"dfn","url":"https://drafts.csswg.org/css-syntax-3/#at-rule"}, "https://drafts.csswg.org/css-syntax-3/#css-parse-something-according-to-a-css-grammar": {"displayText":"parse","export":true,"for_":["CSS"],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"parse","type":"dfn","url":"https://drafts.csswg.org/css-syntax-3/#css-parse-something-according-to-a-css-grammar"}, "https://drafts.csswg.org/css-syntax-3/#css-rule": {"displayText":"rule","export":true,"for_":["CSS"],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"rule","type":"dfn","url":"https://drafts.csswg.org/css-syntax-3/#css-rule"}, "https://drafts.csswg.org/css-syntax-3/#style-rule": {"displayText":"style rule","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"style rule","type":"dfn","url":"https://drafts.csswg.org/css-syntax-3/#style-rule"}, "https://drafts.csswg.org/css-syntax-3/#typedef-block-contents": {"displayText":"<block-contents>","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"<block-contents>","type":"type","url":"https://drafts.csswg.org/css-syntax-3/#typedef-block-contents"}, "https://drafts.csswg.org/css-syntax-3/#typedef-delim-token": {"displayText":"<delim-token>","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"<delim-token>","type":"type","url":"https://drafts.csswg.org/css-syntax-3/#typedef-delim-token"}, "https://drafts.csswg.org/css-syntax-3/#typedef-rule-list": {"displayText":"<rule-list>","export":true,"for_":[],"level":"3","normative":true,"shortname":"css-syntax","spec":"css-syntax-3","status":"current","text":"<rule-list>","type":"type","url":"https://drafts.csswg.org/css-syntax-3/#typedef-rule-list"}, "https://drafts.csswg.org/css-ui-4/#valdef-caret-shape-bar": {"displayText":"bar","export":true,"for_":["caret-shape"],"level":"4","normative":true,"shortname":"css-ui","spec":"css-ui-4","status":"current","text":"bar","type":"value","url":"https://drafts.csswg.org/css-ui-4/#valdef-caret-shape-bar"}, "https://drafts.csswg.org/cssom-1/#concept-declarations-specified-order": {"displayText":"specified order","export":false,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"specified order","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#concept-declarations-specified-order"}, "https://drafts.csswg.org/cssom-1/#css-declaration-block": {"displayText":"CSS declaration block","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"css declaration block","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#css-declaration-block"}, "https://drafts.csswg.org/cssom-1/#cssrule": {"displayText":"CSSRule","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"CSSRule","type":"interface","url":"https://drafts.csswg.org/cssom-1/#cssrule"}, "https://drafts.csswg.org/cssom-1/#cssstyledeclaration-computed-flag": {"displayText":"computed flag","export":true,"for_":["CSSStyleDeclaration"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"computed flag","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-computed-flag"}, "https://drafts.csswg.org/cssom-1/#cssstyledeclaration-declarations": {"displayText":"declarations","export":true,"for_":["CSSStyleDeclaration"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"declarations","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-declarations"}, "https://drafts.csswg.org/cssom-1/#cssstyledeclaration-owner-node": {"displayText":"owner node","export":true,"for_":["CSSStyleDeclaration"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"owner node","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-owner-node"}, "https://drafts.csswg.org/cssom-1/#cssstyledeclaration-parent-css-rule": {"displayText":"parent CSS rule","export":true,"for_":["CSSStyleDeclaration"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"parent css rule","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-parent-css-rule"}, "https://drafts.csswg.org/cssom-1/#cssstyledeclaration-readonly-flag": {"displayText":"readonly flag","export":true,"for_":["CSSStyleDeclaration"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"readonly flag","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#cssstyledeclaration-readonly-flag"}, "https://drafts.csswg.org/cssom-1/#cssstyleproperties": {"displayText":"CSSStyleProperties","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"CSSStyleProperties","type":"interface","url":"https://drafts.csswg.org/cssom-1/#cssstyleproperties"}, "https://drafts.csswg.org/cssom-1/#cssstylerule": {"displayText":"CSSStyleRule","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"CSSStyleRule","type":"interface","url":"https://drafts.csswg.org/cssom-1/#cssstylerule"}, "https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-cssrules": {"displayText":"cssRules","export":true,"for_":["CSSGroupingRule"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"cssRules","type":"attribute","url":"https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-cssrules"}, "https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-insertrule": {"displayText":"insertRule(rule)","export":true,"for_":["CSSGroupingRule"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"insertRule(rule)","type":"method","url":"https://drafts.csswg.org/cssom-1/#dom-cssgroupingrule-insertrule"}, "https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style": {"displayText":"style","export":true,"for_":["CSSStyleRule"],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"style","type":"attribute","url":"https://drafts.csswg.org/cssom-1/#dom-cssstylerule-style"}, "https://drafts.csswg.org/cssom-1/#serialize-a-css-declaration-block": {"displayText":"serialize a CSS declaration block","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"serialize a css declaration block","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#serialize-a-css-declaration-block"}, "https://drafts.csswg.org/cssom-1/#serialize-a-css-rule": {"displayText":"serialize a CSS rule","export":true,"for_":[],"level":"1","normative":true,"shortname":"cssom","spec":"cssom-1","status":"current","text":"serialize a css rule","type":"dfn","url":"https://drafts.csswg.org/cssom-1/#serialize-a-css-rule"}, "https://drafts.csswg.org/selectors-4/#compound": {"displayText":"compound selector","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"compound selector","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#compound"}, "https://drafts.csswg.org/selectors-4/#descendant-combinator": {"displayText":"descendant combinator","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"descendant combinator","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#descendant-combinator"}, "https://drafts.csswg.org/selectors-4/#featureless": {"displayText":"featureless","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"featureless","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#featureless"}, "https://drafts.csswg.org/selectors-4/#matches-pseudo": {"displayText":":is()","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":":is()","type":"selector","url":"https://drafts.csswg.org/selectors-4/#matches-pseudo"}, "https://drafts.csswg.org/selectors-4/#relative-selector": {"displayText":"relative selector","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"relative selector","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#relative-selector"}, "https://drafts.csswg.org/selectors-4/#scope-pseudo": {"displayText":":scope","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":":scope","type":"selector","url":"https://drafts.csswg.org/selectors-4/#scope-pseudo"}, "https://drafts.csswg.org/selectors-4/#selector-combinator": {"displayText":"combinator","export":true,"for_":["selector"],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"combinator","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#selector-combinator"}, "https://drafts.csswg.org/selectors-4/#simple": {"displayText":"simple selector","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"simple selector","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#simple"}, "https://drafts.csswg.org/selectors-4/#specificity": {"displayText":"specificity","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"specificity","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#specificity"}, "https://drafts.csswg.org/selectors-4/#type-selector": {"displayText":"type selector","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"type selector","type":"dfn","url":"https://drafts.csswg.org/selectors-4/#type-selector"}, "https://drafts.csswg.org/selectors-4/#typedef-forgiving-selector-list": {"displayText":"<forgiving-selector-list>","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"<forgiving-selector-list>","type":"type","url":"https://drafts.csswg.org/selectors-4/#typedef-forgiving-selector-list"}, "https://drafts.csswg.org/selectors-4/#typedef-relative-selector-list": {"displayText":"<relative-selector-list>","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"<relative-selector-list>","type":"type","url":"https://drafts.csswg.org/selectors-4/#typedef-relative-selector-list"}, "https://drafts.csswg.org/selectors-4/#typedef-selector-list": {"displayText":"<selector-list>","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":"<selector-list>","type":"type","url":"https://drafts.csswg.org/selectors-4/#typedef-selector-list"}, "https://drafts.csswg.org/selectors-4/#where-pseudo": {"displayText":":where()","export":true,"for_":[],"level":"4","normative":true,"shortname":"selectors","spec":"selectors-4","status":"current","text":":where()","type":"selector","url":"https://drafts.csswg.org/selectors-4/#where-pseudo"}, "https://webidl.spec.whatwg.org/#Exposed": {"displayText":"Exposed","export":true,"for_":[],"level":"1","normative":true,"shortname":"webidl","spec":"webidl","status":"current","text":"Exposed","type":"extended-attribute","url":"https://webidl.spec.whatwg.org/#Exposed"}, "https://webidl.spec.whatwg.org/#PutForwards": {"displayText":"PutForwards","export":true,"for_":[],"level":"1","normative":true,"shortname":"webidl","spec":"webidl","status":"current","text":"PutForwards","type":"extended-attribute","url":"https://webidl.spec.whatwg.org/#PutForwards"}, "https://webidl.spec.whatwg.org/#SameObject": {"displayText":"SameObject","export":true,"for_":[],"level":"1","normative":true,"shortname":"webidl","spec":"webidl","status":"current","text":"SameObject","type":"extended-attribute","url":"https://webidl.spec.whatwg.org/#SameObject"}, "https://webidl.spec.whatwg.org/#this": {"displayText":"this","export":true,"for_":[],"level":"1","normative":true,"shortname":"webidl","spec":"webidl","status":"current","text":"this","type":"dfn","url":"https://webidl.spec.whatwg.org/#this"}, }; 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>