I'm confused about how LESS files work. Can I just create a bunch of them and they're just magically included? How do I know they're being included in the right cascading order? What is the significance of the .import.less suffix? I have these files:
client/stylesheets/variables.import.less
#headline-font: 'Khula', Helvetica, Arial, sans-serif;
client/stylesheets/main.less
h1 {
font-family: #headline-font;
}
And Meteor does not like this:
While building the application:
client/stylesheets/main.less:14:16: Less compiler error: variable
#headline-font is undefined
The default Less compiler for Meteor compiles every file with the .less extension into a single CSS file. Partial files with variables and mixins should not be compile into a single file, but imported into your project only.
The .import.less suffix prevents your files from being compiled into a CSS files, but can imported into your other Less files still.
See also: Overide bootstrap base class attributes in less and meteor
In your situation you will possible need the following line of code in your main.less file:
#import "client/stylesheets/variables.import.less"
You need to include variables.import.less in main.less.
You may find this answer useful: https://stackoverflow.com/a/23527787/3624916
Related
For example I am trying to import .navbar-nav from bootstrap's _navbar.scss and not the whole _navbar.scss file to my compiled css file. Is there a way to do it?
Sorry if this was asked before.
You can try doing an extend:
.your-class{
#extend .navbar-nav;
}
However, this would only work if you had imported the _navbar.scss somewhere else or the bootstrap.scss.
Additional
// main.scss
#import ../wherever bootstrap file is/_navbar.scss;
#import _custom.scss;
// _custom.scss
.your-class{
#extend .navbar-nav;
}
One of the way to import .scss in javascript is
import { navbar-nav } from '_navbar.scss'
When using in your component you can do.
<div className={navbar-nav} />
if you want to import it in your .scss file then you can do.
#import '_navbar.scss'
.class {
#extend .navbar-nav
}
As you are learning Sass here are some explanations which may help:
Better wording helps ...
At first some wording to get a correct understandable communication here and anywhere else you are talking about coding:
SASS don't minify a given CSS, it writes the CSS. Minify means the process that a given CSS code is compressed by a postprocessor to a shorter way to write it, - i.e. comments and spaces will be removed ... But yes: as SASS writes CSS it is able to write code in a minified format.
What you mean is to 'reduce code' or 'avoid not needed code' as you only try to import, use and write! the only needed parts of a given module which is a good practice.
.navbar is a CSS class. SASS don't load CSS classes, it writes CSS classes. It doesn't matter if you 'write the code on your own to a SCSS file' or 'get the code from a framework/module' ... SASS writes the however prepared CSS classes to your CSS file.
What you mean is the SASS includes/imports files with code from a framework/module to write that code/classes to css. So yes: maybe you can say you 'load' that module/scss-file ... but you don't load as css class. (This is as important as 'classes' in coding allways means a special construct of excutable code which does something in your programm. CSS classes don't execute anything, in SASS they are content you want to write/output to css.)
Please: these wordings are important to understand each other and to understand the mechanic of the process how SASS works is going on as well.
Reducing code by importing only selected file is good practice
So, I am not sure if I did understand your question right:
No. You are not able to include/import/load a part of the code of a single scss-file only. If you do #import 'somefile.scss' you always get the whole code of the whole file.
Yes. you are able to include/import/load parts of a given framework/module as you are able to load only the special FILES(!) of a framework/module you need for your project.
Yes. That is a really good practice.
As you mentioned Bootstrap indeed is developed and allows you to do that. But head up. If you import i.e. the part navbar.scss (or other selected elements) it only works if you also load the other files navbar.scss depends on. That are almost variables, functions, mixins and sometimes needed JS components to this element as well. Please note, that importing the files the elements are based on (i.e. vars, functions, mixins) has to be done BEFORE you load the element (i.e. like navbars, grid,...) itself.
A way to organize your project
Yes. A good way to organize your project is to have a single(!!!) file which brings all the code together you write in other partial files yourself or which you import from other framework/modules.
In case of Bootstrap this can be (simplified example):
// ###> file: your 'custom.scss'
// Note: file is without leading underscore
// as this files GENERATES/WRITE the css to custom.css
// Files with underscore as _partial-footer-styling.scss
// are not compiled to write css on their own
// that files are only compiled to css when they are imported to files without underscore
#import 'path/your-own-vars';
// Note: technique importing files
// you don't need to write underscore and '.scss'
// Note: function of this file
// the file '_your-own-vars.scss' is to organize you needed vars special to your project
// it includes your own vars and bootstrap vars as well
// --> the Bootstrap vars in this file will overwrite the vars of Bootstrap which will be included next
#import 'bootstrap-path/functions';
#import 'bootstrap-path/variables';
#import 'bootstrap-path/mixins';
#import 'bootstrap-path/your-selected-component-1';
#import 'bootstrap-path/your-selected-component-2';
#import 'bootstrap-path/your-selected-component-3';
...
#import 'path/partial-your-own-additional-css-special-section';
#import 'path/partial-your-own-additional-css-footer-settings';
....
A detailed explanation how to include and use Bootstrap (partly if you like to do so) to your project is here: https://getbootstrap.com/docs/4.6/getting-started/theming/
I have a global CSS file that contains all generic CSS.
I want to be able to extend all the classes present in this global CSS file in any of my SCSS files.
Right now it throws an error .xyz class does not exist and build fails. I tried importing this file but still build fails.
Adding !options next to class is one way for the build to pass but is there any other better way?
Bit more context for Vue users. I use VueCli3. I use <style lang="scss"> for writing SCSS and want to use extend here. Vue documentation suggesting adding prependData for adding variables. I imported the global CSS in a SCSS file and imported that file in the prependData but Vue build still fails.
It sounds like you want to globally include a CSS file with content that the SCSS blocks in each component can read. (Variables, style definitions, etc).
#extend works like a variable, meaning SCSS needs the definition style to be available as part of its compilation. So that means getting "SCSS Global Variables" working should solve your Extend problem too.
In that case, you need to tweak how Webpack deals with your components. You can do it manually as described here. Or my preference is to use a Vue Cli plugin called vue-cli-plugin-sass-resources-loader. Make sure that your component <style> section contains lang="SCSS" though I assume you're already doing that.
Using #import CSS file into SCSS file not possible to #extend any class.
But you can follow below steps for extends class from your pure css code.
Convert .css file into .scss.
import that global.scss file into another .scss file.
Then after you can use #extend for extend class in new file.
If your file have more then 1k line of code then it will get trouble for extend class.
Currently using Bootstrap, compiling with Codekit, and also have a separate style.less that I'm working on.
In variables.less:
#blue: #0096EF;
In style.less, I have the following:
.title-text {color: #blue;}
#import: "variables.less";
In bootstrap.less:
#import: "style.less";
#import: "variables.less";
Am I doing this right? To my mind, when bootstrap is compiled it results in variables.less occurring twice.
you should be able to go with import of variables.less once in bootstrap as first import instance, and do not include it second time in actual style.less. Because you are right on your assumption, it will import variable.less again. meaning you are importing same variables in two locations.
P.S. as long as variables.less that defines variables that you will be using is imported before you access variables themselves you will be fine.
#color-black: #000;
.color {
color: #color-black;
}
I discovered this is also a Codekit issue too, as I am using Codekit to compile the less files.
Solution:
Create style.less and edit it as intended, reference #blue variable
(not declared in current document)
On save, Codekit returns a compile error, due to un-declared variable in style.less. Ignore the error.
In bootstrap.less #import style.less
Save bootstrap.less, it compiles without issue
Call bootstrap.css in the html doc
Incidentally, I encountered a Codekit bug between step 2 and 3. After step 2, Codekit no longer watches or compiles anything. To solve, I needed to remove the watched project and then re-add it to Codekit.
I started using LESS today. But it's kinda weird. This code does not work. I get an error:
! Variable Name Error: #linkColor in a is undefined.
My bootstrap:
#import "variables.less";
#import "normalize.less";
variables.less:
#linkColor: #08c;
#linkColorHover: darken(#linkColor, 15%);
normalize.less:
a {
color: #linkColor;
}
a:visited {
color: #linkColor;
}
a:hover {
color: #linkColorHover;
}
When I make an
#import "variables.less"
in the normalize.less file, everything works fine.
Thanks for your help :)
This other question ultimately led me to the right answer.
It looks like the LESS compiler is silently failing if files are encoded with a BOM. (That's a Byte Order Mark for those not familiar with the term.) This is the default setting in some editors, such as Visual Studio.
The compiler barfs up an error on the BOM if it's in your root file, but seems to fail silently for #import-ed files.
Try saving your files as UTF-8 without a BOM, and see if that solves your problem.
This error can also occur via bad imports in the files you're importing.
I also encountered this issue, when using multiple layers of import, and the 'lessc' compiler from Node.js:
The original file imported a file (which we will call 'child')
The child file imported a file (which we will call 'grandchild')
The grandchild was imported
I attempted to compile the original file, and received the same 'undefined variable' behavior. I could see the variable was defined in the child and the syntax lookedcorrect.
No prior errors were displayed.
The problem turned out that the child was not importing the grandchild properly. Ie,
#import grandchild.less
rather than:
#import "grandchild.less";
Fixing the child importing the grandchild made the original see the variables defined in the child.
This seems like a bug in less - ie, the bad import should show up in the 'lessc' output, so one day it will probably be fixed. Until then, I hope this helps.
There may be another possible root cause.
Here is my original Gruntfile.js:
less: {
compile: {
files: {
'css/less.css': 'less/**/*.less'
}
}
},
The wildcard makes LESS compiler compile all .less files under that folder and merge all results into one CSS. And I got errors running grunt less:compile:
NameError: .transition is undefined in less/core/html.less on line 38, column 3
Once I changed 'less/**/*.less' into 'less/css.less', the compilation succeeds.
I encountered the same problem using Winless compiler.
Some of the .less files i was importing into master.less were empty. when i removed these from the list of imported files my variables were recognized!
To help any others that may come across this not want duplicate CSS generated from multiple imports, you have two options.
Either #import-once the variables / mixins files you need in each file you need to use them in.
Use #import-once "filename.less"; to prevent duplicates.
Upgrade to LESS > 1.4.0, when it arrives; From the less website:
"The statement #import acts differently before and after 1.4.0. It acts as #import-multiple in all older versions and as #import-once in all less.js versions after 1.4.0."
You can also get this error if you are trying to import the file twice (not a good idea) and the first import is before your variables referenced in your.less file have been loaded
Note: I'm using django compress
in index.html i had:
{% compress css %}
<link href="{{ STATIC_URL }}less/timepicker.less" rel="stylesheet" type="text/less">
<link href="{{ STATIC_URL }}less/style.less" rel="stylesheet" type="text/less">
{% endcompress %}
then in styles.less i had
...
#import "timepick.less";
I think it is because of which master less file you are compiling. Likewise
If you have Less/Project_name/project.less and in this project.less you import the variable less and all the other files which has in the directory.
You just have to compile project.less into your css, not all less files. If you try to compile project.less and variables.less at a time you will have this error. And you can avoid redundant declaration of importing the variable less files
I would use the nested rules in the normalize.less :
a {
color: #linkColor;
&:visited {color: #linkColor;}
&:hover {color: #linkColorHover;}
}
And in the #import, you don't need to use the ".less", it's optional :
#import "variables";
#import "normalize";
I don't know if this can help...
One other weirdly specific situation in which this occurs: if you're using .NET and dotless, the compiler will choke on nested media queries with variable specifiers. If you have code like this:
#media (min-width: #aVariable) {
.some-class{
margin: 10px;
#media (min-width: #anotherVariable) {
margin: 20px;
}
}
... then dotless will tell you that it can't find the definition for #anotherVariable, even if it's used three lines above.
For me its happened when using #Import-once and nothing help.
but with #Import its worked.
as i read in the last version of the Less the Import will work as Import-once.
I have 2 LESS CSS files called core.less and style.less
core.less is located under: \css\core.less and its contents are below:
body {
background: #bg_color;
color: #font_color;
}
style.less is located under: \css\green\style.less and its contents are below:
#bg_color: #0F0;
#font_color: #FFF;
#import "../../core.less";
The core.less file contains all the css rules, in LESS format, but does not provide the definitions for the variables.
The style.less defines all the variables referenced in core.less, and then imports the core.less file.
I have no problems compiling style.less as it imports all the rules from the core file. The core.less file cannot be compiled - it will generate errors since it does not contain the variable definitions.
I would now like to compile the core.css file as well (just to make sure there are no errors in my LESS rules). Is there any way of adding some kind of dummy/placeholder variables in the core.less file such that it can also be complied without generating errors and still work with the setup I have explained above?
I am open to suggestions on changing the format / structure of the files.
By importing core.less into style.less you are compiling the "LESS rules" of core.less.
Perhaps you should not define variables, needed in core.less, outside of core.less. I typically make "core" files (in any programming language, really) have no dependencies on the rest of the code.