Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

an idea to combine less function and css variable. Please help a little #3600

Closed
arvinxx opened this issue Feb 1, 2021 · 5 comments
Closed

Comments

@arvinxx
Copy link

arvinxx commented Feb 1, 2021

As we know, less function can't work with css variables. There are lots of related Issues, like #3563 #3551 #3537 #3394 .

These issuses show we really want a way to combine less variable and css variable. Because less is a great tool to compile css in a programming way and css variable has the feature of dynamtic value and is a good way to switch theme.

It's true that is less can't use css variables in less function. But want we really want is to hook less variable and css variable.

At compile time, Less doesn't know anything about your HTML, let alone how a custom property is cascading down to a particular element, which is affected not only by the document tree, but inline styles, the cascade, and the sum total of all your stylesheets. In other words, the final value is only determined by the browser, and Less's compilation environment is, primarily, a Node.js one.

And thus, I come up a "theory" method to combine less function and css variable. Here it is.

First, declare less variable in less function way.

// palettes/index.less

@import "colorPalette"; // colorPalettes is a less funtion to generate color palette by one color

@blue-base: #1890ff;
@blue-1: color(~`colorPalette('@{blue-6}', 1) `);
@blue-2: color(~`colorPalette('@{blue-6}', 2) `);
@blue-3: color(~`colorPalette('@{blue-6}', 3) `);
@blue-4: color(~`colorPalette('@{blue-6}', 4) `);
@blue-5: color(~`colorPalette('@{blue-6}', 5) `);
@blue-6: @blue-base;
@blue-7: color(~`colorPalette('@{blue-6}', 7) `);
@blue-8: color(~`colorPalette('@{blue-6}', 8) `);
@blue-9: color(~`colorPalette('@{blue-6}', 9) `);
@blue-10: color(~`colorPalette('@{blue-6}', 10) `);

Secondly, declare css variables with less variable

@import "palettes/index";

@brand-color: #233ad2;

:root {
  @blue-base: @brand-color; //  here is a override of `@blue-base`

  --blue-1: @blue-1;
  --blue-2: @blue-2;
  --blue-3: @blue-3;
  --blue-4: @blue-4;
  --blue-5: @blue-5;
  --blue-6: @blue-6;
  --blue-7: @blue-7;
  --blue-8: @blue-8;
  --blue-9: @blue-9;
  --blue-10: @blue-10;
}

// here is a dark mode token
:root [theme^="dark"] {
  @import "palettes/dark"; // a dark mode file containing basic method to handle `@blue-*` variable with dark mode

  @dark-mode-primary-color: mix(@brand-color, @component-background, 85%);

  @blue-base: @dark-mode-primary-color;  //  dark mode override of `@blue-base`

  --blue-1: @blue-1;
  --blue-2: @blue-2;
  --blue-3: @blue-3;
  --blue-4: @blue-4;
  --blue-5: @blue-5;
  --blue-6: @blue-6;
  --blue-7: @blue-7;
  --blue-8: @blue-8;
  --blue-9: @blue-9;
  --blue-10: @blue-10;
}

by this method, we can get a generated css:

/* stylelint-disable no-duplicate-selectors */
/* stylelint-disable */
/* stylelint-disable declaration-bang-space-before,no-duplicate-selectors,string-no-newline */
:root {
  --blue-1: #f0f4ff;
  --blue-2: #cfdbff;
  --blue-3: #a1b5f7;
  --blue-4: #738beb;
  --blue-5: #4962de;
  --blue-6: #233ad2;
  --blue-7: #1524ab;
  --blue-8: #091285;
  --blue-9: #02055e;
  --blue-10: #010138;
}
:root [theme^="dark"] {
  --blue-1: #121321;
  --blue-2: #141733;
  --blue-3: #181e44;
  --blue-4: #1a235d;
  --blue-5: #1c297d;
  --blue-6: #1f2f9d;
  --blue-7: #3d50b1;
  --blue-8: #6377c6;
  --blue-9: #8d9ed5;
  --blue-10: #bbc5e4;
}

image

By this method , we can delcare a new less variable to hook less variable and css variable. and it will work geart with light mode and dark mode.

@primary-color: var(--blue-6);

.use-color {
  color: @primary-color;
}

The reason to we want to use less variable ohter than css variable is that css variable has too much syntax noise. It's much easier to write with a single @ than var(--.

However, It's not enough. Because the purpose is to hook @blue-1 with var(--blue-1).

And actually what want I just need is change the declare of @blue-*: less function to @blue-*: var(--blue-*) after executing less function.

the modifyVars param is used to replace value before less function executes, What I really need is a param to modify variable after executing less function.
(There is a little scope of modify variable to avoid circular dependency,for example we don't want --blue-1: @blue-1 to --blue-1: var(--blue-1)).

So is there any way to achieve this? For example a plugin?
I need more information to solve this problem, I think it will be a really meaning feature.

@matthew-dean
Copy link
Member

This is really out of the scope of Github issues. A better place to ask this type of question ("Is there any way to...") is Stack Overflow.

@matthew-dean
Copy link
Member

Closing to reduce issue noise. You're welcome to post a link to the related Stack Overflow question.

@arvinxx
Copy link
Author

arvinxx commented Feb 1, 2021

I post a question about it.
https://stackoverflow.com/questions/65997822/an-idea-to-combine-less-function-and-css-variable-is-therr-any-way-to-handle-th

Acutally I don't think stackoverflow is the right place. Because the maintainer of this repo know the lifecircle of less's executing processing most.

What I want to know is just is there any way to modify less code after executing less function. If there is,it will help a lot. Otherwise,Ifx this can be a feature of it?

@matthew-dean
Copy link
Member

@arvinxx I'm currently the primary maintainer. To be honest, I don't totally understand your question. But if it's essentially a feature request, Less is basically just in bug-fixing mode at this point.

@rgnyldz
Copy link

rgnyldz commented Dec 8, 2022

This could be nice. I like to use @somevar instead of long and a bit harder to write var(--somevar) in my less file

What we want is basically to print out the variable text instead of the actual value so we can access it from the dom. I for example want to let the visitor to change a "@primarycolor" value to a darker shade with a picker.

So in the less file we have ;

:root{
    --primary-color: #AF1763;
}

@primaryColor: var(--primary-color);

.somediv{
    color: @primaryColor;
}

this prints:

.somediv{
    color: #AF1763;
}

this not changing if I change the --primary-color: #AF1763; variable in dom. because less printed out the color hardcoded

So what would be nice is that it prints our like this;

.somediv{
    color: var(--primary-color);
}

This way if we change --primary-color: #AF1763; in root with JS or whatever the text color will be updated everywhere @primarycolor has been used in the less file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants