How to access a variable defined in another scope in less? - css

To avoid style conflicts, I've put Bootstrap in a separate namespace as described in this answer:
.bootstrap-styles {
#import 'bootstrap';
}
Now using a Bootstrap variable such as #gray-lighter gives an error:
.footer {
// NameError: variable #gray-lighter is undefined in ...
border-top: 1px solid #gray-lighter;
}
How can I access a variable defined in a different (non-parent) scope in less?

In that way you can't (see #1848).
If a namespace contains only variables you could do it like:
.footer {
.bootstrap-styles(); // copy that namespace into this scope
border-top: 1px solid #gray-lighter;
}
But since .bootstrap-styles also contains styles this will also put all its styles onto .footer. So if you really need to re-use BS variables in a namespaced manner you need to import them separately from styles, e.g. like this:
.bootstrap-styles {
#import 'bootstrap';
}
.bootstrap {
#import (multiple) 'variables';
}
.footer {
.bootstrap(); // using Bootstrap variables here
border-top: 1px solid #gray-lighter;
}
---
Also note that by wrapping the whole bootstrap.less into a namespace you actually break many of its styles (see #2052 etc., so using it this way is quite questionable).

Related

SassError: Undefined variable

I have a variable file that has two definitions of themes I want to overwrite:
_vars.scss
body {
$bg-color: #fff
}
body.theme-dark {
$bg-color: #333
}
I´m calling the variables in my Angular button component:
button.scss
#import '_vars.scss';
.button {
background-color: $bg-color;
}
But I´m getting the following compiling error:
SassError: Undefined variable.
background-color: $bg-color;
Whats is the right way to overwrite variables depending on my body theme class?
Thanks
You define $bg-color depending on the theme, but never $font-size-18.
On a side note, I would consider to use CSS Custom Properties instead of SASS variables if I was in your shoes. Codyhouse have an interesting and easy to understand article about this, which also talks about color themes.
If you want to dig deeper into this topic you may want to read this article.
First of all variables inside scope valid only in that scope not universally. Now for your question see below :-
_vars.scss
Instead of making variables inside body scope create it in global scope.
$bg-color: #fff;
body {
background-color: $bg-color;
}
and then import it in your button.scss without underscore "_"
#use "vars" as *;
button {
background-color: $bg-color;
}

Css variables declared in :root block in styles.scss are invalid

In my angular 11 app I am trying to globally use css variables to declare global colors.
In my styles.scss I have:
:root{
--primary : #0b68e8;
--secondary:#ABCFFF;
}
.test-class{
background: var(--primary);
}
When I am applying that class in one of mine components I can see that var was not properly taken from declared variables:
I tried to find any solution , but cant resolve it. Do you maybe know what is wrong here?
try
.test-class{
background: #{var(--primary)};
}
BTW, if you're using sccs, why not use sass variables?
$primary: #0b68e8;
.test-class{
background: $primary;
}

LESS variable overrides and import order

In our app.less file, we import a few variable files, and then the individual component style sheets.
app.less
#import variables.less /* Original app styles/colors */
#import corp-colors.less /* corporate color variables */
#import light-theme.less /* Theme definitions */
#import '../components/style' /* This file contains imports of every component in the app */
The variables.less file defines #link-color...
variables.less
#link-color: #1997CA;
And the light-theme.less redefines it by pulling in the corp color.
light-theme.less
body.light-theme {
#link-color: #corp-blue;
}
corp-colors.less
```less
#corp-blue: #2a60c8;
```
Finally, in my component, I digest the variable for a tab bottom border.
x-component/style.less
li {
&.is-selected {
.tab-label {
border-bottom: 3px solid #link-color;
}
}
}
As the light-theme is imported after variables, I'd expect to see the border color as #2a60c8, but am seeing the original #1997CA instead.
However, if I change the component style to use #corp-blue instead of #link-color, it shows correctly.
Am I overlooking something with import and override ordering?
LESS variables work not like CSS variables, they calculate their values on the compilation stage, not in runtime. It seems like you need to change:
body.light-theme {
#link-color: #corp-blue;
}
to:
#link-color: #corp-blue;

Using css modules how do I define a global class

I am using css modules, however a library I use in a component to append tweets with JavaScript adds some elements to my component in the following structure:
<div class='user'></div>
<div class='tweet'></div>
I want to now style these elements in my css module for the component, as follows:
MyComponent.css
.user {
/* styles */
}
.tweet {
/* styles */
}
However of course now my .user class changes to .MyComponent__user___HZWfM due to the hash naming in the webpack loader.
How can I set a global style in my css module?
According to the css modules docs, :global switches to the global scope for the current selector. e.g.
:global(.example-classname)
So this should work:
:global(.tweet) {
text-align: left;
}
:global(.user) {
text-align: left;
}
Or define a global block
:global {
.tweet {
text-align: left;
}
.user {
text-align: left;
}
}
Can use module class with static class with this way.
myStyle.module.css
.moduleClass_g1m59k:global(.StaticClass) {
background-color: orange;
}
Output will generate like this
.moduleClass_g1m59k.StaticClass {
background-color: orange;
}
Many people have struggled with this and there doesn't seem to be any one agreed upon solution. The one I have settled with involves some tweaking of your bundler and specifically addresses the need to import libraries as-is without having to wrap them or edit them manually.
In my webpack config I have set it to scan all files ending css except those within the 'node_modules' and 'src/static' folders. I import my libraries from here and they dont suffer the classname transforms so I am free to use regular classnames for global css and the className={styles.element} convention as usual for modular css (which will compile down to .component_element__1a2b3 or something similar).
Here is an example of a working production webpack config with this solution:
http://pastebin.com/w56FeDQA

LESS issues (scope and explicit node name)

Is there any way to bypass LESS scoping? It's becoming annoying. Basically, I have a .text-box which defines background, border, etc. Then, in a sub-section there's a one-off change to add a margin-top: .text-box { margin-top: 10px }. Now I can't use .text-box within that section and get my original box styles; instead, all I get is the margin-top. How can I get the definition higher in the heirarchy? I suppose I could make it a function, and call that function in both places, but being that I'm using LESS, I want to do less and KISS. In PHP, you'd get to the global namespace by using / prefix, or in C++ using :: prefix.
Additionally, it doesn't seem like any definitions with the node name work for prototyping. Meaning, I can't declare it ul.products, and then use ul.categories { ul.products }. I have to omit the node name in order to re-use it. Meaning: .categories { .products }. Is this an oversight/impossibility?
Thanks
ok so let's say you've got your mixin defined, for example:
.text-box {
background: #eee;
border: 1px solid #ccc;
color: #333;
margin-top: 5px;
}
now you want to add property or modify it in some subsection, then simply do this:
div.content {
div.sub_section {
.text-box;
margin-top: 10px; // this will override 5px defined in the mixin.
}
}
...which is putting your mixin in place, and adding some property you need to add (which will override any property from the mixin itself BUT make sure the overriding property is defined AFTER the mixin is called.
it's not ideal solution, as it creates two declarations in the output css file (there will be one from mixin followed by the one you defined in .sub_section), but otherwise I don't know a solution to this problem other than defining a parametric mixin..
--
your second issue - I think that less doesn't support scope-limited definitions on purpose... if you really need to know that certain mixin is to be used by a specific tag, I would deal with it like so:
.ul_products { ... }
.ul_categories { .ul_products; ... }
ul.categories { .ul_categories; }
you can also define a bundle and call stuff from there:
#ul {
.products { ... }
.categories { ... }
}
ul.categories { #ul > categories; }
i hope i got it right.. ?

Resources