Create LESS mixin with class in external file W3.css - html

I am creating a small personal project mainly with HTML and CSS, but I am new in this and have some problems. I want to use the W3.CSS framework but I don't want to explicitly use it in the html files (like <div class="w3-container">...) because I might want to use something else later and don't want to refactor every file. Googling I learned about less mixins I had the idea of using my own style.less file and from there import w3.css and inherit, for example, .w3-container class for header tags, which I believe cannot be done with only CSS. Anyway, what I am trying to do is:
#import "w3.css";
header {
.w3-container;
}
Both files, "style.less" and "w3.css", are on the same folder and I use the following command to try and compile it:
lessc style.less style.css
Which outputs the error:
NameError: .w3-container is undefined in <path to style.css> on line 3, column 2
I am probably not using less how it's supposed to be. I looked at other questions, for example this one but couldn't do it. I also noticed that my node.js and npm were really outdated: node: v0.12.4, latest: v5.11.0 npm: 2.10.1, latest: 3.8.7 but that wasn't it.
Why doesn't it work?
What other way can I avoid explicitly using classes such as "w3-container"?
Thanks.

Question part 1
With regards to the error:
NameError: .w3-container is undefined in on line 3, column 2
You've used .w3-container as a mixin, but the mixin hasn't been defined. You'd need to define the mixin like so:
#import "w3.css";
.w3-container() {
/*Styles to apply to the mixin would go here*/
}
header {
.w3-container;
}
However it doesn't sound like using a mixin was actually your goal.
Question part 2
With regards to your comment:
What other way can I avoid explicitly using classes such as "w3-container"
LESS compiles down to CSS, so there's no magic that LESS can provide in terms of selectors (such as aliasing W3.css), other than providing some extended functionality to reduce repetition and make your code more maintainable. If you don't want to add new CSS classes, your options are limited to using valid CSS selectors using a higher specificity. The example below is based on path. If w3.css contains:
header {
color: blue;
}
Then to target a header in a section you could use the more specific selector (in LESS):
section {
header {
color: orange;
}
}
This will compile to the CSS:
section header {
color: orange;
}
Question part 3
When you're trying to target an instance of an element of a particular class, it is important to prefix the class with & and include brackets for defining the properties to style like so:
header {
&.w3-container {
color: orange;
}
}
This will compile to the following CSS:
header.w3-container { color: orange; }
If you use .w3-container; by itself, LESS will assume you want to use a mixin here, and will throw the error from Question part 1 since there is no mixin defined with the name .w3-container.

#import (less) "w3.css";
header {
.w3-container;
}

Related

CSS #import with URL / Path specified as a custom property (variable)

I was thinking about a convenient way to create and use themes in HTML / CSS / JS. One possible solution I was thinking of was specifying the path to the theme file as a variable and importing the theme file in the main stylesheet via said variable so something along these lines:
:root {
--theme: url("default-theme.css");
}
#import var(--theme);
This way, if later the theme needs to be changed (for instance for Halloween or for the holiday season etc), the theme can be updated by either manually updating the value of the CSS variable or by using JS / TS to programmatically update the value.
I have tried a couple of different iterations of this including:
:root {
--theme: "default-theme.css";
}
#import var(--theme);
and
:root {
--theme: "default-theme.css";
}
#import url(var(--theme));
But sadly, nothing seems to work. I have also read through the documentation for CSS custom properties and CSS import and so far I have not really found anything.
Here is some editable sample code on StackBlitz. If anyone has any advice or suggestions or some wisdom to share, I will be extremely appreciative.

Use CSS class in another CSS file

I have Asp.net Core 5.0.1 app with multiple MVC views. I also have a CSS file, generated by an app. I want this file to be unmodified (as it will be changed in future using same app). I want separate CSS file, which styles certain elements (eg input or button) to be styled using classes from the generated CSS. I dont want to write class on each input or button etc element (there are 35 views needs to be styled).
For example if generated file has class dx-theme-text-color I want a CSS file which has something like input { color:.dx-theme-text-color}
How can I achieve this?
To clarify: the question is - how to use a class from one CSS in another by name not copy/pasting values etc
I can only think of #extend from SASS:
.dx-theme-text-color {
border: 1px solid red;
}
input, button {
#extend .dx-theme-text-color;
}
You can use css variables.
define css variavles in global scope:
:root {
--my-custom-color: #000;
}
use variables in every css file like this:
.my-element {
color: var(--my-costum-color)
}
You can also use css pre-proccesors like sass(scss), less and etc.

Angular is ignoring the style class set on less files

For some reason my Angular app doesn't use the styles I'm defining at my component's .less file. It simply ignore it.
As I am very newbie with CSS, I don't any way to debug it.
My layout is consisted by a lot of defined styles being imported by other less files. I am using trying to modify the style of a mapboxgl.
This is how the map current looks like:
And it's defined on HTML by:
<div eds-tile class="column xl-3">
<eds-tile-title>Location</eds-tile-title>
<eds-tile-actions>
<div class="action">
<eds-icon icon="maximize">
</eds-icon>
</div>
</eds-tile-actions>
<div class="map" id="map"></div>
</div>
On this component's less I have:
#import "~#eds/vanilla/variables/light";
#import (reference) "~#eds/vanilla/font/styles";
#import (reference, multiple) "~#eds/vanilla/variables/global";
#import "./map/map";
And on ./map/map.less I have a lot of theme stylization:
https://pastebin.com/b8CpakH9
My trouble is that there's some classes that are indeed being used by Angular, like this one:
.map {
min-height: 200px;
width: 100%;
height: 100%;
a {
color: #text;
}
}
But others are not, like this (you can see on image below that there's nothing related by that definition on browser's styles inspection):
.mapboxgl-ctrl-bottom-left {
display: none !important;
}
What is happening on my case?
I'm following another example that it's working fine. On the component.less file it uses:
#import (reference) "~#eds/vanilla/font/styles";
.dark {
#import "~#eds/vanilla/variables/dark";
#import (multiple) "./map/map";
}
.light {
#import "~#eds/vanilla/variables/light";
#import (multiple) "./map/map";
}
And the map.less file is the same except the by the min-height value.
The example:
You can clearly see that on this example it's using ".light .map {}" to set the style. Different that my case, that converts to ".map[_ng-content-c5] {}" for some reason. I don't have any clue of what this means.
Sorry by being so vague about the problem description. It's simply because I'm don't have enough experience even to name it.
I think I know what the problem is.
If you open your generated css file you see that there is no .mapboxgl-ctrl-bottom-left {
You will instead see something like: .mapboxgl-ctrl-bottom-left[_ngcontent...] {
That's how angular works, it adds some attributes to ensure a style only applies to one component.
You can control if styles are encapsulated or not with ViewEncapsulation
Most likely this happens because the content (in this case the map) is getting rendered with JS after the DOM is loaded and is not handled by angular itself, therefore it doesn't get the attributes.
Without any more information I can't help you any further since I don't know all the details. I don't know exactly which map you are using, maybe there is a tutorial on how to integrate it with angular somehow.

Polymer styling of elements with custom class doesn't work when vulcanized

I am trying to make a global theme for a polymer app.
I've defined some variables inside a theme file like this.
#global-theme.html
<style is="custom-style">
:root {
--default-primary-color: #00BBD3;
--primary-background-color: #FFF;
}
:root paper-button.primary {
color: var(--primary-background-color);
background-color: var(--default-primary-color);
}
</style>
Then in another element I use a paper-button with the .primary class... but no .primary class style is applied.
<paper-button class="primary" id="search" on-click="onSearch">Search</paper-button>
If I just put paper-button.primary definition in a normal .css file then it works except that I obviously can't use the variables when it's not inside the polymer system which defeats the purpose.
This all works fine when in development but doesn't work when vulcanized for production
How do I define the global styles correctly so that any paper-button with .primary class has my custom styles applied from within the custom-style definition that also works when vulcanized?
----- update -----
I've looked into my vulcanized html file (that is built with the default yeoman/polymer starter kit gulp tasks) and replaced my custom styles that were flattened there with a link to the actual element like <link rel="import" href="../custom/my-polymer-theme/my-polymer-theme.html"> it works!!
Why would flattening/vulcanization cause this to happen when it's exactly the same code and how would I get around it?
---- FIXED ----
Problem was a boundary between a mixin & variable when vulcanized...
:root {
/* dark theme mixin */
--dark-theme-colors: {
color: #fff;
background-color: var(--secondary-text-color);
};
--dark-theme-secondary-text-color: var(--divider-color);
...
}
When this was flattened to vulcanized html file it doesn't work any more.
To fix it was as simple as closing off the :root bracket and opening a new one.

How do I use LESS variables in CSS comments?

Is it possible to use LESS variables in CSS comments for mixins? I need that for spriting.
For example (not working / only the image path gets replaced):
.sprite (#width) {
/** sprite: sprite-#{width}; sprite-image: url('../img/#{width}/sprite-#{width}.png'); sprite-layout: vertical */
.picture {
background-image: url('../img/#{width}/picture.png'); /** sprite-ref: sprite-#{width}; */
}
}
.sprite(800);
Bonus question: Can I prevent the linebreak between background-image and the sprite-comment after compiling with lessc?
no, you can't do variables in comments.
what about adding a property 'comment' ignored by browsers.
you could try to use an escaped string e.g.
prop: ~"url('blah'); /* comment */";
but it produces 2 semicolons (valid CSS) and is pretty hacky.
I stumbled upon this question because I wanted to have automated semantic comments that are fed into Kentico (a .NET CMS). Because the accepted answer seemed a bit unsatisfying I tried a few things on my own and managed to somehow produce a better solution. Maybe this is due to changes in the less syntax since then...
// DEFINITIONS
#A: (~"A Standard");
#X-1: (~"1 General");
// BASIC DEFINITIONS
#start: (~"/*# ");
#end: (~" #*/");
#sep: (~" / ");
// FORMULA
#{start} #{A} #{sep} #{X-1} #{end}
* { text-decoration: none; }
The output is then:
/*# A Standard / 1 General #*/ * {
text-decoration: none;
}
The only thing that's bothering me is the missing new line after the comment. Unfortunately I'm using the dotless Compiler which is not able to evaluate js-functions. I added an empty comment at the end, that did the trick for me.
Should you use the browser-version, you can use the following variable to insert a new line:
#nl: (~`"\n"`)
...resulting in:
#{start} #{A} #{sep} #{X-1} #{end} #{nl}
I have a good solution:
create a file and name it start-comment.css, inside the file add exactly this content /*, then create another file end-comment.css, inside add only this */, and finally create another file e.g- description.txt in there, add all the content that you want in the comment, now in your .less file add the next code:
#import (inline) "start-comment.css";
#import (inline) "description.txt";
#import (inline) "end-comment.css";
at the end you will get something like this:
/*
(The content that i add in my text file)
*/