0

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.

Community
  • 1
  • 1
sempiedram
  • 137
  • 12
  • *".w3-container is undefined in..."* - see [Import File Extensions](http://lesscss.org/features/#import-directives-feature-file-extensions). – seven-phases-max Apr 24 '16 at 14:07
  • 1
    Aside of this it's important to warn (before you waste to much time with this approach) that even if Less allows you to re-use existing CSS styles s mixins or via `exatend`, it's usually pretty useless feature in a long run except some very basic cases and examples. I.e. it's not a method one would build a whole project/app/site around. For more details see [this collection](https://gist.github.com/seven-phases-max/cefc873a78fa12924462) of answers and comments there (they mostly about Bootstrap but the same applies to W3 lib since it uses similar selector structuring). – seven-phases-max Apr 24 '16 at 14:24
  • 1
    For example calling `.w3-btn` within your `.my-button` class won't create any connected styles (like `.w3-btn.w3-disabled`, `.w3-btn:hover` etc etc.). `Extend` may give better results, but still, sooner you find your code to try to re-use existing selectors (written solely to be used in HTML in mind, and *not* as building blocks for another CSS ) starts to outweigh the actual CSS code in those selectors. (It probably will work if your project uses the very minimal amount of entities, but still you're putting your self into a trap by assuming the same will work for "something else later") – seven-phases-max Apr 24 '16 at 14:38
  • wow thanks, I thought I had already tried `@import (less) "w3.css;"` but that was it, that's the answer I was looking for. And you are right, this method doesn't feel reliable anyway – sempiedram Apr 24 '16 at 21:40

2 Answers2

0

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.

Aaron Newton
  • 2,124
  • 1
  • 28
  • 31
  • Thanks for your answer, but I don't think you understood what I intended. I know that it would be required to add `class="w3-container"` but I am trying to avoid that using something else. Also, I think I understand CSS enough. – sempiedram Apr 24 '16 at 03:49
  • 1
    "But I am trying to avoid that using something else"... your options are limited to using valid CSS selectors using a higher specificity. Therefore, if you don't want to add any classes you'll need to use a more specific selector based on path, such as _section header {...}_ as per my example. 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. Does that answer your question? – Aaron Newton Apr 24 '16 at 03:57
  • Yeah, you are right, now I get it. I'll do what I was thinking about doing, and that is copying w3.css into style.less and add my stuff at the bottom and compile. I don't think I should accept the first answer, if you edit it to say what is on your comment I'll accept it. (or submit another answer?) Thank you. – sempiedram Apr 24 '16 at 04:19
  • 1
    No problem. Regarding _I'll do what I was thinking about doing, and that is copying w3.css into style.less and add my stuff at the bottom and compile_ you should still be able to use an import. There is an example of importing a CSS file into a LESS file here: http://stackoverflow.com/a/16830938/201648. Using an import gives you the same results as copying and pasting the CSS directly into the file, but it means you can keep the W3.css code separate from your own code. – Aaron Newton Apr 24 '16 at 07:21
  • 1
    I've updated my answer into two parts - addressing the issues with the undefined mixin - since it's still in your question - and reiterating what I said in my first comment as per your request. – Aaron Newton Apr 24 '16 at 07:30
  • _Using an import gives you the same results as copying and pasting the CSS directly into the file_ Well, that is what I wanted, but I couldn't make it work. It kept complaining about not finding `.w3-container` – sempiedram Apr 24 '16 at 08:34
  • Ah - I've just added _Question part 3_ to my answer. If you use the syntax described here it should resolve your issues. There's a subtle difference between the syntax for using a mixin and the syntax for targeting a class. – Aaron Newton Apr 24 '16 at 09:13
0
@import (less) "w3.css";

header {
  .w3-container;
}