LESS.JS Redundancy in CSS, Use of Mixins instead of selector inheritance?
I am using less.js with some regular use of mixins. E.g. I do have a basic class 'gradientBlack' like this.
.gradientBlack {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5a5a5a), color-stop(60%, #333333), color-stop(100%, #000000));
background: -webkit-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -o-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -ms-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5a5a5a', endColorstr='#000000', GradientType=0 );
background: linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
}
Then I reuse this class at several definitions, like
h3 {
.gradientBlack;
...
}
.darkBox {
.gradientBlack;
...
}
A disadvantage of this approach is, that it bloats the CSS with redundant definitions. E.g. the computed CSS might look similar to this.
h3 {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5a5a5a), color-stop(60%, #333333), color-stop(100%, #000000));
//... and maybe some more (redundant) definitions
}
.darkBox {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5a5a5a), color-stop(60%, #333333), color-stop(100%, #000000));
//... and maybe some more (redundant) 开发者_开发技巧definitions
}
For someone like me, who uses a lot of gradients, roundCorners etc, this adds up quickly.
Question (edited)
I found out that the known name for this topic is selector inheritance (see Sass) and as it seems isn't implemented right now. Usage and advantages are discussed here. The computed css of this syntax might look like this.
h3,
.darkBox,
.gradientBlack {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
...
}
Nevertheless, I would appreciate any suggestions, when to bother and when not to - as well as any other on-topic hints how to proceed as long as selector inheritance is not an option.
I think there are a few issues to consider:
- Size of the style sheet
- Efficiency of style sheet execution (how fast the browser executes)
- Maintainability of the style sheet
- Maintainability of the markup (html)
The approach that Mark Gemmill advocates (in /3) is really Nicole Sullivan's Object Oriented CSS. I used that pattern before switching to Sass, and still find some of it useful, but I think the Sass/Less way results in more maintainable CSS and more maintainable markup - there is no need to sprinkle presentational classes throughout the markup.
I think @extend
(selector inheritance) is one of the main advantages that Sass has over Less and does reduce the redundancy in the compiled style sheet.
To me, the benefits of more maintainable CSS and markup outweigh any downside of a slightly larger style sheet. I think you'll find that if you keep your selectors efficient (don't nest in Less/Sass more than you need to) and combine and minimize in production the performance hit will be less than you might imagine.
You can define your mixin, and then pass in variables that you want to override when you call it.
This is an example form the less website:
.box-shadow (@x: 0, @y: 0, @blur: 1px, @alpha) {
@val: @x @y @blur rgba(0, 0, 0, @alpha);
box-shadow: @val;
-webkit-box-shadow: @val;
-moz-box-shadow: @val;
}
So when you call it you could do something like
div.header {
.box-shadow(5px,5px,2px,.5);
}
This way you can have 1 mixin, but each time you call it, you can pass it different attributes.
Hope this helps.
I recently started using less css as well, and this exact question came to mind as well. My response was:
1/ The actual generated css is kind of besides the point as you are never likely to be looking at it (except perhaps to debug your less code), so if there is some redundancy in the output that's a trade off you get with what I think is a syntax that is much better to understand and maintain.
2/ The disadvantage is, as you've described, if you pass in those less css class style around as a mixin
you are bloating the size of your css output. If you are using less css on the front end, and it's generating the css in the browser this isn't a worry. However, if you are pre-generating your css, then it becomes a question of how that bloat effects download times. Unless your css file becomes huge as a result, and/or your site is doing very high volume, I wouldn't worry about it.
3/ An alternative to passing a class style around as a mixin
(or using selector inheritance) in your less css is to just use class inheritance
in your html, so rather than this in your less file:
.gradientBlack {
...
}
h3 {
.gradientBlack;
...
}
.darkBox {
.gradientBlack;
...
}
td.dark {
.gradientBlack;
...
}
You just define .gradientBlack
in your style sheet and then reference the class directly in the html:
<h3 class="gradientBlack"></h3>
<div class="darkBox gradientBlack></div>
<td class="dark gradientBlack"></td>
I think in the end, aside from a question of download time, the bottom line is what makes your code easier to understand and maintain in your given situation. I rather have 100 more lines in my generated css if it makes my less css easier to comprehend.
What about something like this?
h3, .darkBox, td.dark {
.gradientBlack;
}
h3, {
/*other styles here*/
}
.darkBox {
/*other styles here*/
}
td.dark {
/*other styles here*/
}
Alternatively you could consider using a CSS minifier and see if that gives you an acceptable size without compromising the cleanliness of your LESS file.
I'm using lessphp (which may be different than less.js in this example) but I've noticed that if I declare the mixin as though it had an empty parameter list it will never generate a style block.
So change this:
.gradientBlack {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5a5a5a), color-stop(60%, #333333), color-stop(100%, #000000));
background: -webkit-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -o-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -ms-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5a5a5a', endColorstr='#000000', GradientType=0 );
background: linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
}
To this:
.gradientBlack() {
background: #333333;
background: -moz-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5a5a5a), color-stop(60%, #333333), color-stop(100%, #000000));
background: -webkit-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -o-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
background: -ms-linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5a5a5a', endColorstr='#000000', GradientType=0 );
background: linear-gradient(top, #5a5a5a 0%, #333333 60%, #000000 100%);
}
and use it like this:
h3 {
.gradientBlack();
...
}
.darkBox {
.gradientBlack();
...
}
and it won't generate the unused block.
精彩评论