@@ -1087,7 +1087,7 @@ outside the ''@result'' rule),
10871087[=mixin parameters=]
10881088(the values passed to the [=mixin=] ,
10891089 or set to default values),
1090- and custom properties defined at the [= call site=]
1090+ and custom properties defined at the call site
10911091(the element recieving the mixin styles,
10921092or another [=mixin=] calling this [=mixin=] ).
10931093
@@ -1504,7 +1504,7 @@ with the following properties:
15041504 (The function's invocation has some adjustments; see below.)
15051505* The [=function body=] is identical to the [=mixin body=] ,
15061506 minus any ''@result'' rules,
1507- plus a 'result' descriptor
1507+ plus a 'result!!descriptor ' descriptor
15081508 containing the original value of the property this anonymous function is replacing.
15091509
15101510Additionally, the arguments passed to the mixin
@@ -1552,7 +1552,7 @@ rather than unexpectedly evaluating in a descendant element's context:
15521552
15531553 This will desugar into approximately:
15541554
1555- <xmp>
1555+ <xmp highight=css >
15561556 @property --magic-arg1 {
15571557 syntax: "<length> ";
15581558 inherits: true;
@@ -1583,9 +1583,307 @@ and a direct substitution used instead.
15831583It's required only to make variables
15841584and other element-relative values resolve correctly.
15851585
1586- Issue: TODO add a few examples derived from <a href="https://github.com/w3c/csswg-drafts/issues/12927">issue 12927</a> .
1586+ <div class=example>
1587+ When [=mixins=] are nested
1588+ (one invoked via ''@apply'' inside the ''@result'' of another),
1589+ the desugaring nests as well,
1590+ in the obvious way.
1591+ For example:
1592+
1593+ <xmp highlight=css>
1594+ div {
1595+ @apply --colorized-squish(tomato);
1596+ }
1597+
1598+ /* "wraps" an element in colored arrows */
1599+ @mixin --squish(--left-color <color> ,
1600+ --right-color <color> : var(--left-color)) {
1601+ @result {
1602+ &::before {
1603+ content: "🡆";
1604+ background-color: var(--left-color);
1605+ }
1606+ &::after {
1607+ content: "🡄";
1608+ background-color: var(--right-color);
1609+ }
1610+ }
1611+ }
1612+
1613+ /* colors the element, and auto-generates a border color
1614+ and the "squish" colors from it */
1615+ @mixin --colorized-squish(--color <color> ) {
1616+ @result {
1617+ background-color: var(--color);
1618+ border: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1619+ @apply --squish(oklch(from var(--color) calc(l - 0.3) c h),
1620+ oklch(from var(--color) calc(l - 0.2) c h));
1621+ }
1622+ }
1623+ </xmp>
1624+
1625+ This desugars in two steps, inside-out.
1626+ First, the ''--squish()'' is unfolded
1627+ into the ''--colorized-squish()'' mixin:
1628+
1629+ <xmp highlight=css>
1630+ div {
1631+ @apply --colorized-squish(tomato);
1632+ }
1633+
1634+ @mixin --colorized-squish(--color <color> ) {
1635+ /* Lift the `@apply squish();` arguments out into local vars */
1636+ --s-arg1: oklch(from var(--color) calc(l - 0.3) c h);
1637+ --s-arg2: oklch(from var(--color) calc(l - 0.2) c h);
1638+ @result {
1639+ background-color: var(--color);
1640+ border: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1641+ /* Replace the `@apply --squish();` with its @result,
1642+ transformed to wrap the property values in
1643+ anonymous functions. */
1644+ &::before {
1645+ content: --s1(var(--s-arg1), var(--s-arg2));
1646+ background-color: --s2(var(--s-arg1), var(--s-arg2));
1647+ }
1648+ &::after {
1649+ content: --s3(var(--s-arg1), var(--s-arg2));
1650+ background-color: --s4(var(--s-arg1), var(--s-arg2));
1651+ }
1652+ }
1653+ }
1654+ @function --s1(--left-color <color> ,
1655+ --right-color <color> : var(--left-color)) {
1656+ result: "🡆";
1657+ }
1658+ @function --s2(--left-color <color> ,
1659+ --right-color <color> : var(--left-color)) {
1660+ result: var(--left-color);
1661+ }
1662+ @function --s3(--left-color <color> ,
1663+ --right-color <color> : var(--left-color)) {
1664+ result: "🡄";
1665+ }
1666+ @function --s4(--left-color <color> ,
1667+ --right-color <color> : var(--left-color)) {
1668+ result: var(--right-color);
1669+ }
1670+ </xmp>
1671+
1672+ Then the ''--colorized-squish()'' mixin is unfolded into the ''div'' rule:
1673+
1674+ <xmp highlight=css>
1675+ div {
1676+ /* Lift the `@apply --colorized-squish();` argument out into a var */
1677+ --cs-arg1: tomato;
1678+ /* Replace the `@apply --colorized-squish();` with (part of)
1679+ its @result, again with values wrapped in anonymous functions. */
1680+ background-color: --cs1(var(--cs-arg1));
1681+ border: --cs2(var(--cs-arg1));
1682+ &::before {
1683+ /* Note that --cs-arg1 is inherited here from div */
1684+ content: --cs3(var(--cs-arg1));
1685+ background-color: --cs4(var(--cs-arg1));
1686+ }
1687+ &::after {
1688+ content: --cs5(var(--cs-arg1));
1689+ background-color: --cs6(var(--cs-arg1));
1690+ }
1691+ }
1692+ @function --cs1(--color <color> ) {
1693+ result: var(--color);
1694+ }
1695+ @function --cs2(--color <color> ) {
1696+ result: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1697+ }
1698+
1699+ /* These four generated functions all look identical, they
1700+ just call into the correct generated function from
1701+ --squish()'s unfolding. */
1702+ @function --cs3(--color <color> ) {
1703+ /* The --colorized-squish() local vars (created by the
1704+ first desugaring) are turned into function local vars. */
1705+ --s-arg1: oklch(from var(--color) calc(l - 0.3) c h);
1706+ --s-arg2: oklch(from var(--color) calc(l - 0.2) c h);
1707+ result: --s1(var(--s-arg1), var(--s-arg2));
1708+ }
1709+ @function --cs4(--color <color> ) {
1710+ --s-arg1: oklch(from var(--color) calc(l - 0.3) c h);
1711+ --s-arg2: oklch(from var(--color) calc(l - 0.2) c h);
1712+ result: --s2(var(--s-arg1), var(--s-arg2));
1713+ }
1714+ @function --cs5(--color <color> ) {
1715+ --s-arg1: oklch(from var(--color) calc(l - 0.3) c h);
1716+ --s-arg2: oklch(from var(--color) calc(l - 0.2) c h);
1717+ result: --s3(var(--s-arg1), var(--s-arg2));
1718+ }
1719+ @function --cs6(--color <color> ) {
1720+ --s-arg1: oklch(from var(--color) calc(l - 0.3) c h);
1721+ --s-arg2: oklch(from var(--color) calc(l - 0.2) c h);
1722+ result: --s4(var(--s-arg1), var(--s-arg2));
1723+ }
1724+
1725+ /* These are copied from the previous desugaring */
1726+ @function --s1(--left-color <color> ,
1727+ --right-color <color> : var(--left-color)) {
1728+ result: "🡆";
1729+ }
1730+ @function --s2(--left-color <color> ,
1731+ --right-color <color> : var(--left-color)) {
1732+ result: var(--left-color);
1733+ }
1734+ @function --s3(--left-color <color> ,
1735+ --right-color <color> : var(--left-color)) {
1736+ result: "🡄";
1737+ }
1738+ @function --s4(--left-color <color> ,
1739+ --right-color <color> : var(--left-color)) {
1740+ result: var(--right-color);
1741+ }
1742+ </xmp>
1743+
1744+ Note that all the custom property and function names
1745+ are given short, somewhat meaningful names here, for readability,
1746+ but actually are [=hygienically renamed=]
1747+ and guaranteed to be unreferencable by author code.
1748+ Only the user agent ever sees or can use them,
1749+ to do this desugaring.
1750+
1751+ <details>
1752+ <summary> Desugaring outside-in</summary>
1753+
1754+ Equivalently, the mixins can be desugared outside-in,
1755+ for the same result:
1756+
1757+ <xmp highlight=css>
1758+ /* Initial Code, same as main example */
1759+ div {
1760+ @apply --colorized-squish(tomato);
1761+ }
1762+
1763+ /* "wraps" an element in colored arrows */
1764+ @mixin --squish(--left-color <color> ,
1765+ --right-color <color> : var(--left-color)) {
1766+ @result {
1767+ &::before {
1768+ content: "🡆";
1769+ background-color: var(--left-color);
1770+ }
1771+ &::after {
1772+ content: "🡄";
1773+ background-color: var(--right-color);
1774+ }
1775+ }
1776+ }
1777+
1778+ /* colors the element, and auto-generates a border color
1779+ and the "squish" colors from it */
1780+ @mixin --colorized-squish(--color <color> ) {
1781+ @result {
1782+ background-color: var(--color);
1783+ border: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1784+ @apply --squish(oklch(from var(--color) calc(l - 0.3) c h),
1785+ oklch(from var(--color) calc(l - 0.2) c h));
1786+ }
1787+ }
1788+
1789+
1790+ /* First desugar, unfolding --colorized-squish()*/
1791+
1792+ div {
1793+ /* Pull out the --colorized-squish() argument */
1794+ --cs-arg1: tomato;
1795+ /* Swap the @apply with the --colorized-squish() @result,
1796+ with values wrapped in anonymous functions. */
1797+ background-color: --cs1(var(--cs-arg1));
1798+ border: --cs2(var(--cs-arg1));
1799+ /* The equivalent transform here is wrapping the
1800+ @apply args in anonymous functions. */
1801+ @apply --squish(--cs3(--cs-arg1),
1802+ --cs4(--cs-arg1));
1803+ }
1804+ @function --cs1(--color <color> ) {
1805+ result: var(--color);
1806+ }
1807+ @function --cs2(--color <color> ) {
1808+ result: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1809+ }
1810+ @function --cs3(--color <color> ) {
1811+ result: oklch(from var(--color) calc(l - 0.3) c h);
1812+ }
1813+ @function --cs4(--color <color> ) {
1814+ result: oklch(from var(--color) calc(l - 0.2) c h);
1815+ }
1816+ @mixin --squish(--left-color <color> ,
1817+ --right-color <color> : var(--left-color)) {
1818+ @result {
1819+ &::before {
1820+ content: "🡆";
1821+ background-color: var(--left-color);
1822+ }
1823+ &::after {
1824+ content: "🡄";
1825+ background-color: var(--right-color);
1826+ }
1827+ }
1828+ }
15871829
15881830
1831+ /* Second desugar, unfolding --squish() */
1832+ div {
1833+ --cs-arg1: tomato;
1834+ background-color: --cs1(var(--cs-arg1));
1835+ border: --cs1(var(--cs-arg1));
1836+ /* Pull out the --squish() args now. */
1837+ --s-arg1: --cs3(--cs-arg1);
1838+ --s-arg2: --cs4(--cs-arg1);
1839+ /* And swap the @apply with the --squish() @result,
1840+ with values wrapped in anonymous functions. */
1841+ &::before {
1842+ content: --s1(var(--s-arg1), var(--s-arg2));
1843+ background-color: --s2(var(--s-arg1), var(--s-arg2));
1844+ }
1845+ &::after {
1846+ content: --s3(var(--s-arg1), var(--s-arg2));
1847+ background-color: --s4(var(--s-arg1), var(--s-arg2));
1848+ }
1849+ }
1850+ @function --cs1(--color <color> ) {
1851+ result: var(--color);
1852+ }
1853+ @function --cs2(--color <color> ) {
1854+ result: 2px solid oklch(from var(--color) calc(l - 0.1) c h);
1855+ }
1856+ @function --cs3(--color <color> ) {
1857+ result: oklch(from var(--color) calc(l - 0.3) c h);
1858+ }
1859+ @function --cs4(--color <color> ) {
1860+ result: oklch(from var(--color) calc(l - 0.2) c h);
1861+ }
1862+ @function --s1(--left-color <color> ,
1863+ --right-color <color> : var(--left-color)) {
1864+ result: "🡆";
1865+ }
1866+ @function --s2(--left-color <color> ,
1867+ --right-color <color> : var(--left-color)) {
1868+ result: var(--left-color);
1869+ }
1870+ @function --s3(--left-color <color> ,
1871+ --right-color <color> : var(--left-color)) {
1872+ result: "🡄";
1873+ }
1874+ @function --s4(--left-color <color> ,
1875+ --right-color <color> : var(--left-color)) {
1876+ result: var(--right-color);
1877+ }
1878+ </xmp>
1879+
1880+ The desugaring is slightly different in details,
1881+ like the --s-arg1/2 custom properties are stored on ''div''
1882+ rather than inside of the functions,
1883+ but because they're unobservable and [=hygienically renamed=] ,
1884+ the behavior is identical.
1885+ </details>
1886+ </div>
15891887
15901888
15911889
0 commit comments