49

I'm using the roots theme for wordpress: https://github.com/retlehs/roots/

It already comes with a precompiled bootstrap.css and recommends to use app.css for any customizations. As I don't have the options to add the classes to the buttons via html or javascript, I'd like to use the LESS sources to reference a css class, for example, I want to give a submit button the bootstrap button style:

input#submit{
.btn;
.btn-primary;
}

If I use @import 'bootstrap.less'; it adds the entire bootstrap css into app.css. How can I just use the bootstrap.less as reference for compiling?

ScottS
  • 71,703
  • 13
  • 126
  • 146
FLX
  • 4,634
  • 14
  • 47
  • 60
  • so, you want to reference only the classes that you use on app.css? – Tomas Ramirez Sarduy Jan 22 '13 at 08:04
  • i don't think it is possible. please read this: http://stackoverflow.com/a/4060413/1761123 –  Jan 31 '13 at 14:01
  • Why don't you just add an import rule to bootstrap.css itself to your newly created css? – Ayyash Feb 02 '13 at 07:36
  • @user1761123: the answer you direct to is only applicable to pure CSS. With LESS, you can mixin an existing classes code into another selector as FLX is doing. The problem is not in that functionality, but in not wanting to import all the bootstrap.less code to the final style sheet that is using the `input#submit` code. – ScottS Feb 07 '13 at 10:46
  • @Ayyash: doing that is going to cause all the bootstrap code to be in the final style sheet. Imagine that all FLX wants in the final style sheet is the `input#submit` selector (I'm sure he has other code, but this illustrates the point of the question). He want's to use the code from bootstrap to build the properties for that selector, but he _does not want_ all the rest of the bootstrap code to be part of his final css style sheet. – ScottS Feb 07 '13 at 10:50
  • 1
    well then, why not remove the other unwanted imports and keep the mixins and functions? if you intend to use the same class again, then do expect that u need it, duplicating it in the output is the whole idea behind LESS – Ayyash Feb 08 '13 at 14:52
  • @FLX: My bounty did not yield much more help (other than a second voice to say it does not work). So I am actually going to delete my answer, since it is not valid. – ScottS Feb 12 '13 at 21:34

4 Answers4

55

The core question you ask is

"How can I just use the bootstrap.less as reference for compiling?"

As of LESS version 1.5

For LESS 1.5 it is now possible to import a file purely as a reference. Like so:

@import (reference) 'bootstrap.less';

No actual code will output from that file as CSS, but all becomes available to use as mixins.

Original Answer (kept for context for all the comments)

[DISCLAIMER: it is uncertain if this would work as of 1.3.3, but this original answer I do believe has some usefulness in later versions as well. However, for truly getting what the OP wanted, the new capability in LESS 1.5 is recommended.]

Current versions of LESS (1.3.3) can accommodate this through the use of a namespace. Like so:

#bootstrapRef() {
  @import: 'bootstrap.less':
}

input#submit{
  #bootstrapRef > .btn;
  #bootstrapRef > .btn-primary;
}

By making the namespace a mixin (the addition of the parentheses after the name), it will still import the file (I know of no way to access it externally without importing), but it should not compile the actual bootstrap code into your final css file output. What this technique should do is allow you access to bootstrap's classes, mixins, etc., through the namespace call #bootstrapRef >, making it possible to use those in your own defined classes, etc.

I have not fully tested if there are any bugs to this, it should just work theoretically.

ScottS
  • 71,703
  • 13
  • 126
  • 146
  • This seems like a great solution, but I'm getting errors with the latest version of lessc: lessc app.less > ../app.css NameError: #bootstrapRef > .btn is undefined in /assets/css/less/app.less:170:2 169 input#submit{ 170 #bootstrapRef > .btn; 171 #bootstrapRef > .btn-primary; 2 @import: 'bootstrap.less': 3 } – FLX Jan 22 '13 at 21:26
  • Unfortunately, I'm unable to test it. Here are three things you need to look at: 1) I used [this online compiler](http://less2css.org/) to make sure `#bootstrapRef` would be recognized; so it could be a compiler difference, but check that functionality by just putting your own class in and seeing if you can access it; 2) it looks like the `bootstrap.less` file might not be loading, 3) if #2 okay, double check that the `.btn` classes are not more deeply nested, which would require a longer namespace call (like `#bootstrapRef > #someWrapperInBootStrap > .btn`). – ScottS Jan 22 '13 at 23:38
  • None of these suggestions unfortunately solve the problem. I set up a simple import test for myself and none of the import scenarios work. Check the results here: http://pastebin.com/VnLJcQ77 – FLX Jan 23 '13 at 01:15
  • Just to confirm, you show `import` commands rather than `@import` (you did not show an `@` sign in your pastebin). If that was your actual code ran, then that may be your problem. Can you verify that. – ScottS Jan 23 '13 at 01:20
  • @FLX: besides the note about checking the `@` sign above, your `SCENARIO 2: IMPORT FROM FILE WITH EXTERNAL BUNDLE` (2nd Scenario 2) should have worked. What I am not sure of is whether the `@import` can be nested in a namespace block in the target file exactly as I showed above. Of course, the missing `@` will affect both. – ScottS Jan 23 '13 at 01:40
  • The second scenario works when using `@import`, but proves not to have value as I'd like to use this namespace on bootstrap.less, which holds @import statements to all the other Bootstrap components :( – FLX Jan 23 '13 at 01:43
  • @FLX: Check out [this resolved issue](https://github.com/cloudhead/less.js/issues/656) which indicates the method I proposed should work, though it apparently is controlled by the `--strict-imports` option according to comments in that post. You might check that. – ScottS Jan 23 '13 at 02:18
  • This is just using an import inside a selector, not using the namespace. I tried `--strict-imports`, but it still telling me `NameError: #bundle-name > .mixin-one is undefined` :( – FLX Jan 23 '13 at 18:38
  • @FLX: Just to clarify, the `--strict-imports` (as I read that) should be "off" (as it does not allow what you are trying to do). Note that in LESS, there is no difference between a namespace and a selector or mixin (note that it uses an `id` sign `#` just like an `id` selector). – ScottS Jan 23 '13 at 18:41
  • I have it turned off, it doesn't matter :( Have you tested this yourself? Does it work for you? – FLX Jan 23 '13 at 19:47
  • The short answer is "no," (as I noted in my answer, "not fully tested"). I have not replicated your exact situation. – ScottS Jan 23 '13 at 20:45
  • Could you do me a favor and test a simple version of it for me? I'm curious if it works for you: http://pastebin.com/HKa5jaMc – FLX Jan 23 '13 at 22:20
  • @FLX: I would love to, I just have not been able to. My present set up does not afford me the opportunity to. I have been seeking an online compiler to test with, but the only one I have found that allows testing of `@import` is not on the latest version of LESS, so it does not allow a namespace call from a mixin. So I have yet to locate an online compiler that will let me test the specific use case. – ScottS Jan 23 '13 at 23:13
  • Hey Scott, I understand, but I simply cannot get it to work, I cannot accept this as an answer, sorry :( – FLX Jan 26 '13 at 20:57
  • @FLX: If you cannot get it to work, then I would not expect you to accept it. Like I stated, it should work theoretically, but it appears there is some issue that is hanging it up from working fully as expected. Since I cannot test it further, I cannot add any info to tweak my answer or guide you to getting it to work. I'm sorry I could not be of further help. – ScottS Jan 26 '13 at 21:14
  • @FLX: I got another upvote, which is great, but wholly not useful to resolving the problem. I've added an introductory comment to my answer to help people not just look at it and give me an upvote, but to actually test it. – ScottS Jan 31 '13 at 10:55
  • @FLX: Just out of curiosity, is your "the latest version of lessc" running the latest version of LESS itself (1.3.3)? There are so many LESS compilers out there, but not all keep up to date with their version of LESS itself. I'm considering offering a second bounty on this question to try to get answers, but I need to know if your issue may be a compiler issue. – ScottS Feb 03 '13 at 03:44
  • The version of lessc that I'm running is using LESS 1.3.3, so unfortunately it should be compatible. I would really appreciate a second bounty, thanks for all the help Scott :) – FLX Feb 05 '13 at 00:27
  • @FLX: Does your compiler correctly _nest_ `bootstrap.less` via `@import` if you use just a selector `#bootStrapRef` (NOTE: _no parentheses_, so a selector rather than mixin)? In other words, is it the attempt to import the code into a _mixin_ rather than just a _selector_ that is failing? I realize namespacing it into a selector rather than a mixin does not solve your issue (it still leaves you with a css file containing all the bootstrap code), but I am trying to isolate if, for you, the issue is purely one of trying to import into a mixin or not. Make sure strict imports is set to false. – ScottS Feb 08 '13 at 10:49
  • This does not work, .btn is a class and not a function/mixin, meaning you get `NameError: #bootstrapRef > .btn is undefined` – Declan Cook Feb 12 '13 at 00:31
  • @DeclanCook: Thanks for feedback. It is not so much that `.btn` is a class (I can get a class to reference just fine in a namespace, as classes can be "mixed in" as well with LESS), but I could not confirm if the import is functioning. The error you get is telling me that it is not importing into the namespace when the namespace is a mixin. What compiler were you using? – ScottS Feb 12 '13 at 02:30
4

Doing this in LESS is a bit tricky but can be achieved like so:

#bootstrap() {
    .btn() {
        @import "bootstrap/variables.less";
        @import "bootstrap/mixins.less";
        @import "bootstrap/buttons.less";
    }
}

input#submit{
  #bootstrap > .btn;
}

resulting in some additional classes being declared from mixins.less and variables.less. Mostly just .clearfix and then all of the .btn classes are added to input#submit

See the long output here:

http://pastebin.com/ZBAZZ3kS

thomaux
  • 19,133
  • 10
  • 76
  • 103
Declan Cook
  • 6,066
  • 2
  • 35
  • 52
  • So you have no issues getting the `variables.less` etc. to import inside the doubly nested mixin of `#bootstrap() {} .btn(){}`? That is interesting. I am sure the output is not what the OP desires (he does not want the classes of bootstrap nested under `input#submit`, but rather taking on the characteristics of the particular class), but the fact that you do get `@import` to work in the mixin is an important point to me. What compilier are you using? – ScottS Feb 12 '13 at 03:48
  • lessc 1.3.3, This is I think the best you can do. It results in all of the buttons.less classes being added to `input#submit`. – Declan Cook Feb 12 '13 at 09:16
  • The problem is the OP does not want the _classes_ added to the `input#submit`, he wants the _properties_ from those classes mixed into the selector itself. – ScottS Feb 12 '13 at 10:27
  • If you remove the `.btn()` mixin wrapper from your code, and just import the three files into the `#bootstrap()` mixin, then call `#bootstrap > .btn` does it mix the properties from the `.btn` class into the `input#submit`? – ScottS Feb 12 '13 at 12:17
  • No this results in `btn is undefined`. I don't think less handles the import and exposes the class to the mixin/namespace. I can't get it to work in that way using an import. If the classes are not imported this method will work. – Declan Cook Feb 12 '13 at 12:45
  • Can you run one more test. Try defining the mixin and calling it inside the namespace: `#bootstrap() { .nestedMixin(){ imports here } .nestedMixin(); }` then `input#submit { #bootstrap > .btn }`. If you could try this both with an import of `bootstrap.less` and if that does not work, your smaller subset of `.less` files in your answer. I'm curious if the defining then calling of the nested mixin _within_ the namespace mixin circumvents the issue. – ScottS Feb 12 '13 at 13:43
  • `.btn is undefined` still on the line `#bootstrap > .btn` I don't think it is currently supported. – Declan Cook Feb 12 '13 at 14:22
  • Even though you did not quite fulfill all the requirements I was seeking, neither did anyone else. Since you were the only one to offer any other extended help on this, I'm going to give you the bounty. Thanks for your time. – ScottS Feb 12 '13 at 21:23
  • Thanks! was an interesting issue. Shame we couldn't get it fully resolved. – Declan Cook Feb 12 '13 at 22:36
3

I'm not sure if there is a tool for import only current referring css rules inside an external file, but Boostrap has a very organized structure, so check if the styles you are looking for are on mixins.less, so you don't have to import the entire bootstrap.less file.

Also, check this related question, there are some good Best Practices for customize Boostrap.

EDIT: As @PavloMykhalov suggest, maybe is better to look at buttons.less

Note: It will be awesome a tool for this sort of things. Some day I will work on that

Community
  • 1
  • 1
Tomas Ramirez Sarduy
  • 17,294
  • 8
  • 69
  • 85
1

Don't know what made you believe that LESS currently supports that, for this to be possible the option must be a lot more explicit, it currently really simply imports, parses, saves chunks, executes chunks into output text.

Unless there is nothing explicit to stop this sequence, it will not do it any differently.

I have just logged a feature request under LESS, don't know for sure if this has been requested before though, searched and found nothing, hope I don't get slapped for repetition!

https://github.com/cloudhead/less.js/issues/1169

UPDATE The issues turned out to be a duplicate, the issue open is here: https://github.com/cloudhead/less.js/issues/622

Ayyash
  • 4,257
  • 9
  • 39
  • 58
  • I'm not sure I totally understand your statment about a "stop to this sequence". [This issue](https://github.com/cloudhead/less.js/issues/656) resolved having an import in a selector, and current testing on [this compiler](http://less2css.org/) shows a namespace can be a mixin (e.g. `#test() { .mixin {color: red;}} .class {#test > .mixin;}` works as expected). But I have not confirmed that the two work together, mainly because I cannot confirm if an import into a mixin is allowed (though obviously, I'm suspecting not). – ScottS Feb 08 '13 at 16:27
  • I think we all misunderstood the question the first time, it really isnt about how to write the rules in mixins, it is about how to output styles in the output css according to what you wish, not what your css imports... so, the question was: can I import just to use the definitions? without having the whole style output? imports inside mixins will not exclude styles from being output, will they? – Ayyash Feb 10 '13 at 11:31
  • Yes, my solution (if the `import` into a mixin would work), keeps the style from outputting until you specifically call the mixin or something from within the mixin through a namespace call. So the mixin is in LESS, but will not show up in the CSS. The problem with my solution is that it seems to not actually work (the `import` does not seem to be acknowledged within a mixin), but no one has confirmed anything on their tests of it. – ScottS Feb 10 '13 at 13:06