Can Stylus interpolate a variable inside another variable? - css

I'm trying to set up a mixin for a selector interpolation in Stylus to tweak the themes of an external website (Logseq), particularly the position of different objects in different divs. Here's a simplified version of my code for just list bullets (object) in two divs (area):
// selectors for bullets, as constants for different themes
content-list = '.content-list-1,.content-list-2'
sidebar-list = '.sidebar-list-1,.sidebar-list-2'
// positions of bullets, for tweaking
content-list-margin-top : 0.4em
sidebar-list-margin-right : 0.1em
// the mixin for the interpolation in question
position(object, area)
{{area}-list} // to be replaced with .sidebar-list-1,.sidebar-list-2
position : relative
top : {area}-{object}-margin-top
right : {area}-{object}-margin-right
.bullet
position(bullet, content)
position(bullet, sidebar)
I'm basing this off of the example provided by the official documentation here and here:
border(side, args...)
if side
border-{side} args
else
border args
mySelectors = '#foo,#bar,.baz'
{mySelectors}
background: #000
However, my code gets an error at {{area}-list}, that the next block (after right : ...) expected : but got }.
I suppose that my use of {} is wrong, or that inserting a variable into another variable is impossible in the first place. I tried replacing {} with () as suggested here, but the error persists.

Related

Why is my nested web component adding vertical space in Lit?

I have a weird issue where when I add padding-left: 32px to an element, vertical space gets added. If the CSS says 0, and I add the space manually in Chrome debugger, the vertical space isn't there. This is only happening with nested components. I'm not sure if I'm misusing something or if I have found a bug.
I have code like this:
<cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Not Nested A</cai-setting-row
><cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Not Nested B</cai-setting-row
>
<cai-setting-row-account></cai-setting-row-account>
The render of cai-setting-row-account is just the same markup:
render() {
return html`<cai-setting-row
class="itemGroupMiddle doubleIndent"
data-type="A"
>Nested A</cai-setting-row
><cai-setting-row class="itemGroupMiddle doubleIndent" data-type="A"
>Nested B</cai-setting-row
>`;
}
It renders like this:
The "Not Nested" elements look right. The "Nested" ones have extra space and you can see a weird border on top that is the distance of the padding.
I have a functioning sandbox here:
https://studio.webcomponents.dev/edit/8u0cg76BNEiSoHXQT8by/
I misunderstood how class is used on a custom component. Doing <my-component class="foo"> adds foo to the :host. My code in sandbox needed to change the magic of const parentClass = this.getAttribute('class') ?? ''; to const parentClass = this.getAttribute('itemClass') ?? '';, such that I wouldn't accidentally be applying classes to the :host and the intended element.

SASS/SCSS variable not working with CSS variable assignment

I have the following SCSS code:
#mixin foo($bar: 42) {
--xyzzy: $bar;
}
bar {
#include foo;
}
I would expect that I get CSS variable --xyzzy set to 42 on all bar elements. Instead of this, I get CSS stating bar { --xyzzy: $bar; }. The variable was not interpreted. I would need to use #{…} syntax instead to get the variable set.
Is this a feature of the SCSS/SASS? A bug? Can I get the interpretation working without enclosing the variable name in #{…}?
Actual result:
bar {
--xyzzy: $bar;
}
Expected:
bar {
--xyzzy: 42;
}
It's not a bug, it's how the Sass compiler works regarding CSS custom properties, known as CSS variables. The syntax #{…} is called interpolation, and it is the only way to inject dynamic values into a custom property. Here is a quote from the doc:
CSS custom properties, also known as CSS variables, have an unusual declaration syntax: they allow almost any text at all in their declaration values. What’s more, those values are accessible to JavaScript, so any value might potentially be relevant to the user. This includes values that would normally be parsed as SassScript.
Because of this, Sass parses custom property declarations differently than other property declarations. All tokens, including those that look like SassScript, are passed through to CSS as-is. The only exception is interpolation, which is the only way to inject dynamic values into a custom property.
That's the reason why you have that behavior, and only doing so works:
#mixin foo($bar: 42) {
--xyzzy: $bar; // does not work
--xyzzy: #{$bar}; // works
}

Escapes, Fades and Variable Colors [LESS] [duplicate]

It seems that evaluated color strings are not working with some built-in LESS functions.
I have tried using e() and ~"" and any combination of both.
I might find a workaround for my particular case, I’m just asking if this is this expected behaviour, or if there is a fault in my reasoning? Any insight appreciated.
For example here, the color is created from an evaluated string; note the 'missing' # in the hex value that gets added later :
.broken-mixin(#hexcode: '9719e1') {
#color: e("##{hexcode}");
// this works as expected
background-color: #color;
// this does work too
.very-simple-mixin(#color);
// Undefined_methodError: error evaluating function `fade`:
// Object #<Object> has no method 'toHSL'
background-color: fade(#color,30%);
// SyntaxError: error evaluating function `red`:
// Cannot read property '0' of undefined
background-color: rgba(red(#color), green(#color), blue(#color), 0.5);
}
Otherwise built-in functions work normally work with variables in mixins, for example :
.mixin-works(#myColor: #00ff00) {
// works just fine
background-color: fade(#myColor,30%);
// or this, works too
background-color: rgba(red(#myColor), green(#myColor), blue(#myColor), 0.5);
}
What am I missing ?
Quoting the LESS website's Function Reference:
fade
Set the absolute transparency of a color. Can be applied to colors whether they already have an opacity value or not.
Parameters:
color: A color object.
amount: A percentage 0-100%.
The fade function requires a color object as input to it and hence passing an evaluated string as a parameter to the function doesn't work.
It can be solved by using the built-in color function which converts a string into an equivalent color object like below:
background-color: fade(color("#{color}"),30%);
The other built-in functions also are not working for the same reason (that is, they expect a color object as an input).
red:
Extracts the red channel of a color object.
Parameters: color - a color object.

Built-in functions not working with evaluated strings, why?

It seems that evaluated color strings are not working with some built-in LESS functions.
I have tried using e() and ~"" and any combination of both.
I might find a workaround for my particular case, I’m just asking if this is this expected behaviour, or if there is a fault in my reasoning? Any insight appreciated.
For example here, the color is created from an evaluated string; note the 'missing' # in the hex value that gets added later :
.broken-mixin(#hexcode: '9719e1') {
#color: e("##{hexcode}");
// this works as expected
background-color: #color;
// this does work too
.very-simple-mixin(#color);
// Undefined_methodError: error evaluating function `fade`:
// Object #<Object> has no method 'toHSL'
background-color: fade(#color,30%);
// SyntaxError: error evaluating function `red`:
// Cannot read property '0' of undefined
background-color: rgba(red(#color), green(#color), blue(#color), 0.5);
}
Otherwise built-in functions work normally work with variables in mixins, for example :
.mixin-works(#myColor: #00ff00) {
// works just fine
background-color: fade(#myColor,30%);
// or this, works too
background-color: rgba(red(#myColor), green(#myColor), blue(#myColor), 0.5);
}
What am I missing ?
Quoting the LESS website's Function Reference:
fade
Set the absolute transparency of a color. Can be applied to colors whether they already have an opacity value or not.
Parameters:
color: A color object.
amount: A percentage 0-100%.
The fade function requires a color object as input to it and hence passing an evaluated string as a parameter to the function doesn't work.
It can be solved by using the built-in color function which converts a string into an equivalent color object like below:
background-color: fade(color("#{color}"),30%);
The other built-in functions also are not working for the same reason (that is, they expect a color object as an input).
red:
Extracts the red channel of a color object.
Parameters: color - a color object.

CSS Sprite Not Working - Displays Only First Image in Set

Yes, I have been here: CSS Sprite not working
No, I don't get it. What does he mean by 'points'?:
"In other words:
For each ID value, apply 100 points
For each class value (or pseudo-class or attribute selector), apply 10 points
For each element reference, apply 1 point"
What are these 'points'? I read the articles and I get that there is order in specifying CSS codes, but I still don't understand. Right as this is I am only getting the very first sprite in the set. FYI-I used a sprite generator. (This one to be exact)
You can view the source code here. I would suggest zooming in on your browser to see everything properly.
Ricky: The img tag is occluding the background. I recommend changing it to a div. Also, you didn't include the NOS object in your code. Here's what I came up with:
<script>
var NOS = {
itemno: 0,
menuClasses: [
'img-blog',
'img-files',
'img-forums',
'img-login',
'img-logout',
'img-mail',
'img-news',
'img-profile',
'img-reg',
'img-settings',
'img-shop',
'img-status'
],
toggle: function() {
$('#menuimg').removeAttr('class').addClass(function() {
++NOS.itemno;
if (NOS.itemno > NOS.menuClasses.length - 1) {
NOS.itemno = 0;
}
return NOS.menuClasses[NOS.itemno];
});
}
}
</script>

Resources