@@ -20,6 +20,8 @@ WPT Display: open
2020<pre class=link-defaults>
2121spec:infra; type:dfn; text:list
2222spec:infra; type:dfn; for:list; text:append
23+ spec:css-borders-4; type:property;
24+ text:border-width;
2325spec:css-cascade-5; type:dfn;
2426 text:inherit
2527 text:computed value
@@ -1149,11 +1151,13 @@ to ensure that references to them work correctly across elements and inheritance
11491151[=Hygienic renaming=] changes the names
11501152of [=local variables=] and [=mixin parameters=]
11511153to an unobservable, guaranteed non-clashing name,
1152- its <dfn>hygienic name</dfn> .
1154+ its <dfn noexport>hygienic name</dfn> .
1155+ (They remember their <dfn noexport>original name</dfn> , however.)
11531156
1154- If a ''var()'' references a [=custom property=]
1155- whose name matches a [=hygienically renamed=] [=local variable=] or [=mixin parameter=] ,
1156- it is instead interpreted as referencing the [=hygienic name=] .
1157+ If a ''var()'' in the [=mixin body=]
1158+ would reference a [=local variable=] or [=mixin parameter=]
1159+ with its [=original name=] ,
1160+ the reference is rewritten to use the [=hygienic name=] instead.
11571161The same applies to [=variable unit references=]
11581162and ''style()'' references in an ''if()'' test.
11591163
@@ -1162,21 +1166,30 @@ If future features allow referencing the value of a custom property on an elemen
11621166they will also be interpreted as referencing the [=hygienic name=]
11631167when used inside a [=mixin=] .
11641168
1165- The ''inherit()'' function is an exception to this;
1166- as it intrinsically reaches "outside" of an element
1167- (and thus the mixin scope),
1168- it cannot be referring to a [=local variable=] or [=mixin parameter=]
1169- and is not reinterpreted.
1170- However, if the outer context is another [=mixin=] ,
1171- [=hygienic renaming=] might still apply in <em> that</em> context.
1169+ [=Hygienic renaming=] extends to nested [=mixins=] and to invoked [=custom functions=] ,
1170+ if they contain "unbound" variable references
1171+ that would match a [=hygienically renamed=] [=local variable=] or [=mixin parameter=] .
1172+ (This preserves the ability of mixins to "override" custom properties
1173+ implicitly used by nested mixins or functions,
1174+ the same way that nested function calls can.)
1175+
1176+ Otherwise, such "unbound" references are left undisturbed,
1177+ so they'll still match the appropriate [=custom property=] in the element context.
1178+
1179+ Note: For example, the ''inherit()'' function intrinsically reaches outside of the current context,
1180+ referencing the value one "level" up.
1181+ Even if a [=local variable=] with the same name exists in the current [=mixin=] ,
1182+ it won't cause the ''inherit()'' 's reference to be rewritten.
1183+ (But if it ends up referencing a [=local variable=] higher in the "call stack",
1184+ it'll be rewritten to coordinate with that one.)
11721185
11731186<div class=example>
11741187 For example, given the following styles and mixin:
11751188
11761189 <xmp highlight=css>
11771190 @mixin --triple-border(--size <length> ) {
11781191 @result {
1179- &, & > h1 , & > h1 > small {
1192+ &, & > * , & > * > * {
11801193 border-width: var(--size);
11811194 }
11821195 }
@@ -1218,33 +1231,94 @@ However, if the outer context is another [=mixin=],
12181231 as the author intended.
12191232</div>
12201233
1234+ Note: While [=hygienic renaming=] ensures that descendants won't accidentally pick up the wrong variable value,
1235+ and [[#evaluating-mixins]] ensures that element-dependent arguments passed to the mixin
1236+ (like ''@apply --foo(1em);'' )
1237+ will resolve against the applying element too,
1238+ using <em> any other</em> element-dependent reference in the [=mixin result=]
1239+ will evaluate as normal for their placement in the styles.
1240+
1241+ <div class=example>
1242+ For example, in the following variant of the previous example:
1243+
1244+ <xmp highlight=css>
1245+ @mixin --triple-border() {
1246+ @result {
1247+ &, & > *, & > * > * {
1248+ border-width: .2em;
1249+ }
1250+ }
1251+ }
1252+ section {
1253+ font-size: 10px;
1254+ @apply --triple-border;
1255+ }
1256+ section > h1 {
1257+ font-size: 20px;
1258+ }
1259+ section > h1 > small {
1260+ font-size: 15px;
1261+ }
1262+ </xmp>
1263+
1264+ The applied mixin will be equivalent to:
1265+
1266+ <xmp highlight=css>
1267+ section {
1268+ font-size: 10px;
1269+ border-width: .2em;
1270+ }
1271+ section > h1 {
1272+ font-size: 20px
1273+ border-width: .2em;
1274+ }
1275+ section > h1 > small {
1276+ font-size: 15px;
1277+ border-width: .2em;
1278+ }
1279+ </xmp>
1280+
1281+ Which will give three different 'border-width' values: ''2px'' , ''4px'' , and ''3px'' .
1282+ </div>
1283+
12211284<div class=issue>
12221285
1223- Do we need hygienic renaming for other element references, like ''em'' ?
1224- Presumably, if ''@apply --foo(var(--bar))'' is potentially confusing,
1225- then ''@apply --foo(1em)'' would be too,
1226- if the [=mixin parameter=] ends up being used on a child element in the [=mixin result=] .
1227- But you can also want ''1em'' inside the [=mixin result=]
1228- to apply to the element it's actually set on,
1229- not necessarily the parent context receiving the ''@apply'' .
1230- This might need some additional syntax support,
1231- to ensure that all use-cases are adequately addressed.
1232- For now, no additional renaming is done;
1233- ''em'' /etc values are resolved "normally",
1234- based on the element their styles are actually used on.
1235-
1236- While theoretically an author could also want to reference the element's value of a [=custom property=] ,
1237- ignoring a [=local variable=] ,
1238- [=custom functions=] already shadow in this fashion.
1239- You can escape <em> one</em> level of the shadowing in functions via ''inherit()'' ,
1240- and that feature is preserved in mixins,
1241- but ultimately the functin/mixin stack has control
1242- over what custom properties are visible in their bodies.
1243- Note that if a custom property name isn't a [=local variable=] or [=mixin parameter=] ,
1244- it won't be [=hygienically renamed=] within this mixin,
1245- so an author <em> can</em> refer to an element's own style
1246- as long as the mixin isn't invoked inside of another mixin
1247- that shadows it intentionally.
1286+ This is likely often a desirable behavior,
1287+ but if it's not,
1288+ we should have a workaround.
1289+ The following *doesn't* work,
1290+ due to the mixin body becoming the function body of an anonymous function,
1291+ which is evaluated on each element
1292+ and thus inherits that element's ''em'' length.
1293+
1294+ <xmp highlight=css>
1295+ @function --as-length(--x <length> ) returns <length> { result: var(--x); }
1296+ @mixin --triple-border() {
1297+ --em: --as-length(1em);
1298+ @result {
1299+ &, & > *, & > * > * {
1300+ border-width: calc(0.2 * var(--em));
1301+ }
1302+ }
1303+ }
1304+ </xmp>
1305+
1306+ I think the only way that works is to have an extra argument
1307+ that you don't expect the user to pass,
1308+ since arguments get lifted onto the applying element
1309+ and hygienically renamed:
1310+
1311+ <xmp highlight=css>
1312+ @mixin --triple-border(--em <length> : 1em) {
1313+ @result {
1314+ &, & > *, & > * > * {
1315+ border-width: calc(0.2 * var(--em));
1316+ }
1317+ }
1318+ }
1319+ </xmp>
1320+
1321+ But this is clumsy. :(
12481322</div>
12491323
12501324
0 commit comments