Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a general purpose selector as a mixin in LESS CSS

I know about mixins and parametric mixins. What we are looking for is a way to make any general purpose selectors in CSS / LESS into a mixin.

Eg in Twitter BootStrap, we have here

.navbar .nav > li {
  float: left;
} 

If I have to use it in a class say .mynavbar I want to be able to do this

INPUT->
.mynavbar {
  .navbar .nav >li;
}

OUTPUT->
.mynavbar {
  float:left;
}

Now I know this can't be done with the current version of LESS as the compiler flags a parser error. I wanted someone to help me out on changing the source code of less.js a little so that this is workable.

I've managed to reach the source code for the mixin parser. I've tried changing the RegExp there, but it interferes with other parts of the parser. I know we have to make only a few changes because, instead of just accepting .mixin and #mixin we have to accept any mixin like tags / attribute selectors like input[type=text].

It is currently needed for the development of a UI framework that uses Bootstrap. Unfortunately many places in bootstrap are littered with direct tag selectors instead of ids and classes.

like image 521
Gaurav Ramanan Avatar asked Nov 23 '12 18:11

Gaurav Ramanan


People also ask

What is the correct way to define a mixin in Less?

Mixins are a group of CSS properties that allow you to use properties of one class for another class and includes class name as its properties. In LESS, you can declare a mixin in the same way as CSS style using class or id selector. It can store multiple values and can be reused in the code whenever necessary.

Can CSS selectors be combined?

A CSS selector can contain more than one simple selector. Between the simple selectors, we can include a combinator. There are four different combinators in CSS: descendant selector (space)

Which kind of selector can only be used once on a page?

ID selectors can only be used once per page.


2 Answers

This is possible since version 1.4.0 (2013-06-05) of LESS that include the extend feature. Based on the original example

.navbar .nav > li {
  float: left;
}

.mynavbar:extend(.navbar .nav > li) {}

compiles to

.navbar .nav > li,
.mynavbar {
  float: left;
}

Documentation here and discussion & example use for the original question here

EDIT: Added Code Sample

like image 172
Gaurav Ramanan Avatar answered Nov 13 '22 17:11

Gaurav Ramanan


First off, I would strongly discourage doing such things. Instead, try to use the power of CSS and build your HTML such that the bootstrap rules apply, for example. Anyway, since you asked for it, here is the solution.

The problem is not the complexity of the selector, or the child rule, but the tag name selector part (i. e. the li). So, what we have to fix is the mixin parser only matching classes and ids. I guess we would not want to tamper with the first class or id test, since that is probably needed to distinguish mixins from normal CSS rules (although the tests run fine with that check commented out). (Actually, there is a parser preference in action, and the only thing tried after mixins are comments and directives, so we can safely remove that check as well). However, we can easily allow tag names in later parts of the mixin selector by adding a question mark after [#.] in the matching regular expression. So

while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) {

– i. e. line 825 – becomes

while (e = $(/^[#.]?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) {

The test cases still run through fine, afterwards, but subtle breakage my occur, so be cautious.

Edit: There is a GitHub Issue for the same problem. Apparently the less folks rather want the mixin feature to be more narrow and function-like, instead of allowing a more flexible … well … mixing in of rules. With regard to the CSS output, that's probably reasonable.

like image 24
Adrian Heine Avatar answered Nov 13 '22 17:11

Adrian Heine