Referencing class names between SASS modules - css

I'm confused how to reference my SASS module class name in another module. I have a Contact page module and a PhoneNumber module. In certain context on this page, I'd like to change the button inside the PhoneNumber. Using simplified example for clarity:
// src/pages/contact/index.module.scss
#use 'src/components/PhoneNumber/index.module' as phoneNumber;
.page {
phoneNumber.container {
:global(.button) {
background-color: pink;
}
}
}
It doesn't work, I'm not sure how to reference .container class name of PhoneNumber component.

There are 2 issues:
(1) If you include variables imported by directive #use ... as namespace you have to call them using the added namespace with character $ as well. So you have to call the variable with phoneNumber.$container, not: 'phoneNumber.container'.
(2) If you use a variable as element/id/class-name you have to wrap variables in #{$hereMyVariable} at all.
So try following code:
.page {
.#{phoneNumbers.$container}{
:global(.button) {
background-color: pink;
}
}
}
FURTHER EXPLANATION
Rule #use loads mixins, functions, and variables from other Sass stylesheets so you can use them. To separate same variables/mixins/functions names from different stylesheets you can separate them to different namespaces by #use scssFileName as myNamespace.
Now you can call i.e. variables with same name namespace1.$container and namespace2.$container from different stlesheetswith different values. Mixins works the same way just without $.
So: if you load #use filepath/filename as phoneNumber to your stylesheet and call phoneNumber.container SASS is looking to the other stylesheet for a function or mixin named container. From the context of you simplified example I assume you want to call a variable with the name of the class. Than you need to use $ and the brackets.
(Notice: But if you want just to name your class phoneNumber.container you should write .phoneNumber.containerso SASS will interpret it as classname and not as reference to the namespace of the other stylesheet ...)
Wider explanations how to use #use can be find in the excellent official docs: https://sass-lang.com/documentation/at-rules/use

Related

Tailwindcss + Nextjs problems with class + variables

Good afternoon, I need help with a big problem I'm having with tailwindcss + nextjs...
So the problem is when it comes to setting the classes, I need to use a variable, the class is set in the css, but the tailwind is not converting the class into a style.
I need it to be like this:
I already tried to set the class as constant, I tried to set the constant both inside the component and in getstaticprops, and none of them worked.
I've tried to set a class within the css itself and it didn't work either.
Tailwind uses regex to find class names, and because of this they need to exist as unbroken strings in your source code. A consequence of this is you cannot use string interpolation the way you're trying to do, as Tailwind will not be able to find the class name.
What you can do instead is map your props to static class names:
const Component = ({pokemon}) => {
const pokemonBgVariants = {
pikachu: 'bg-pokemontype-pikachu',
bulbasaur: 'bg-pokemontype-bulbasaur',
// ...
}
return (
<div className=`[...other classes] ${pokemonBgVariants[pokemon.types[0].type.name]}`></div>
)
}

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
}

What does :global (colon global) do?

In some SCSS files, I see the following:
:global {
/* ... */
}
I don't know if it is an SCSS feature or a CSS feature.
I tried searching about it but couldn't find any good results at first sight.
The :global operator is used in CSS Modules. Modular CSS uses a CSS Modules compiler to scope CSS styles within their respective modules (e.g., React component).
Here's an example from a React module (in the file ErrorMessaging.less for the ErrorMessaging.jsx React component):
:global(.ocssContainer) {
.ui_column {
padding-left: 0;
}
}
This gets compiled into:
.ErrorMessaging__alertContainer--1I-Cz .ocssContainer .ErrorMessaging__ui_column--3uMUS {
padding-left: 0;
}
But now I add a :global modifier onto .ui_column:
:global(.ocssContainer) {
:global(.ui_column) {
padding-left: 0;
}
}
And this is what it compiles to:
.ErrorMessaging__alertContainer--1I-Cz .ocssContainer .ui_column {
padding-left: 0;
}
Now .ui_column can apply to any child element with that style, including in a child React component, and not just .ui_column elements that are part of the ErrorMessaging React component.
It looks like they are using CSS Modules. If you follow the docs they say:
:global switches to global scope for the current selector resp.
identifier. :global(.xxx) resp. #keyframes :global(xxx) declares the
stuff in parenthesis in the global scope.
The :global selector keyword is used in css modules to specify that a class should not be scoped to the component in which it is defined. This selector allows the class to be used globally in the application, rather than just within a specific component. For example, let say you have a .is-global-class class defined in a CSS Module file, you can use :global(.is-global-class) to apply that class to an element and make it available globally.

LESS: mixin with non-class ruleset

In LESS, I am trying to define the button.c2 ruleset, to be applied to <button class="c2">...</button> elements. This ruleset is mainly based on the button.c1 ruleset. However, the following code produces a ParseError:
button.c2 {
button.c1;// Trying to import a ruleset
... // additional rules, such as font-size: 120%;
}
It seems to me that the ParseError is caused by the fact that the imported ruleset does not refer to a class or ID ("button.c1" does not start with a "." or a "#"). From the LESS documentation:
Any CSS class or id ruleset can be mixed-in that way.
Why is there such a limitation? Is there any way around it?
The limitation might just be ease of parsing, since . or # don't show up as the first character of a normal style rule the parser automatically knows that those should be mixed in.
You could get around it by defining .c1 as a mixin and using it for both buttons:
.c1() {
// c1 rules
}
button.c1 {
.c1;
}
button.c2 {
.c1;
// additional rules
}
However, coming up in LESS 1.4.0 are :extend selectors, which will allow you to do what you want. The syntax would be:
button.c2:extend(button.c1) {
// additional rules
}

How can I apply an external CSS class to a span created with dojo.create?

I'm creating a span in my web page with dojo.create, and need to apply CSS to it. I can see how to apply a style to it in the dojo reference, but I'd rather apply it via the external stylesheet (there's quite a few attributes I need to set and I'd rather not do it inline).
So given the example code below, how would I apply the CSS for the printSpan class?
var node = dojo.create("span", {innerHTML:_text, id:"printSpan", class:"printSpan"}, map);
You can write this in your external stylesheet:
.printSpan { color: red; }
This is called the class selector.
By the way, your code should be:
{ innerHTML : _text, id : "printSpan", "class" : "printSpan" }
Notice the colon was inside the "class" string, though it should be outside and printSpan is a different string.

Resources