Skip to content

Commit b81c8c5

Browse files
committed
[css-mixins-1][editorial] Add an example of nested mixins.
1 parent c3122a6 commit b81c8c5

File tree

1 file changed

+302
-4
lines changed

1 file changed

+302
-4
lines changed

‎css-mixins-1/Overview.bs‎

Lines changed: 302 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
10921092
or 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

15101510
Additionally, 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.
15831583
It's required only to make variables
15841584
and 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

Comments
 (0)