1

In base.less:

html{font-size:16px}
body{color:green}

In theme.less:

html{color:red}

In main.less:

@import "base.less"
@import "theme.less"

When compiled it outputs:

html{font-size:16px}
body{color:green}
html{color:red}

How can I output this?

html{font-size:16px;color:red;}
body{color:green}

I tried this in theme.less without success:

html:extend(html) { color:red }

Do I need to use a CSS optimizer or is there something in LESS I can use?

Siguza
  • 21,155
  • 6
  • 52
  • 89
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
  • ***Why?*** This seems like a pre-mature optimisation. Is saving 8/10/30 characters really worth that much, especially as they will be cached client-side if you serve them as compiled CSS anyway? –  May 19 '14 at 05:57
  • @LegoStormtroopr It’s not about optimization. Consider this: `.ca{color:red} .cb{color:green} .ca{color:yellow}` `yolo` – David Hellsing May 19 '14 at 06:00
  • And that's exactly the reason Less does not merge such (`.ca` like) selectors. There's [special syntax proposal](https://github.com/less/less.js/issues/1468) for this kind of stuff but AFAIK it's not going to be implemented any time soon. *There's* a method to emulate this behaviour via mixins though. – seven-phases-max May 19 '14 at 06:07
  • In that case your style rules include conflicting information and you are asking for a technological solution to a developer problem. Which rule would be kept red or yellow? SASS and LESS are designed to be improved types of CSS to make CSS less verbose so its harder to make these mistakes. A conflict like this should be resolved in testing and code review, not in a compiler. –  May 19 '14 at 06:09
  • I agree with both of you, I’m not asking for a computed automagic selector-merge (I know about the cascade part of CSS), I was looking for a way to manually merge (or extend) a selector in another less document (such as bootstrap). – David Hellsing May 19 '14 at 06:12
  • 1
    @LegoStormtroopr The example is not *invalid*, CSS computes it’s cascade using simple rules. The example will be yellow, simply because it was defined after red. That is the reason why I need to control this in some way. – David Hellsing May 19 '14 at 06:22
  • I didn't say it was invalid, I said it was conflicting, which it is, as you have 2 rules for a body. –  May 19 '14 at 06:23
  • @LegoStormtroopr yes, well, this is a very common case if you are using a CSS framework. Even bootstrap have duplicate selectors in it’s compiled CSS. Not saying it’s the the most kosher way to go, just that it’s not necessarily a conflict that a developer needs to "solve", more like "work with". – David Hellsing May 19 '14 at 06:26

2 Answers2

1

Manual Way

I found an answer, Devilo.us. I tried your code and it outputs what you want. This is an external tool though. You've to do it manually.


Grunt Way

Zach Moazeni made a tool that handles this. Check that page for docs.

If you're using Grunt, you can add the grunt-csscss task which allows you to compile LESS to CSS (without redundancy) just by saving your LESS when grunt watch is running. I guess this is definitively what you're looking for.

Community
  • 1
  • 1
Kevin Cittadini
  • 1,449
  • 1
  • 21
  • 30
  • I have no problems compiling less (I use gulp) but compiling alone doesn’t merge the selectors. The link you posted kind of "works", but of course I need to automate this, preferably using only less. – David Hellsing May 19 '14 at 05:30
  • @David I understand. To me is handier doing the grunt/gulp way. Save -> Job done. What could be the benefits for you using only LESS? Let me understand so maybe I can help you better. – Kevin Cittadini May 19 '14 at 07:14
0

It is possible to force "consolidated" selector styles via mixins:

html    {.html()}

.html() {font-size: 16px}

body    {color: green}

.html() {color: red}

.html() {background-color: blue}

// etc.

Though usually this kind of theming is achieved via variables:

// base.less

@text-color: blue;

html {
    font-size: 16px;
    color:     @text-color;
}

// theme.less:

@text-color: yellow;
seven-phases-max
  • 11,765
  • 1
  • 45
  • 57
  • But that would require me to edit the `base.less` file, right? – David Hellsing May 19 '14 at 06:19
  • Yes. If you can't modify "base.less" then it is not possible in pure Less. – seven-phases-max May 19 '14 at 06:25
  • Ok, well I "can" do it, but this comes from bootstrap core so I would prefer not modifying the source, just like you wouldn’t modify the jquery core when adding a plugin. But thanks for your insight. – David Hellsing May 19 '14 at 06:27
  • Well, in case of Bootstrap I wonder what are exact styles you need to hack (since in Bootstrap those things are usually controlled via variables, e.g. instead of setting `html` color you simply override `@text-color` variable for `body`). But in general yes, if some styles are not meant to be customized in a library then we can only override it via cascading (which is expected since Less was crafted for creating style sheets, not for hacking existing ones :) – seven-phases-max May 19 '14 at 06:40