
Often, by creating less-files (which, incidentally, applies to other css preprocessors), we pursue the beauty and elegance of the less-code, when we often forget about the compiled css-code. Sometimes this entails critical consequences, when the volume of the final css increases by a factor of 1, and the code becomes completely unreadable.
Disclaimer1) This article is suitable for both SASS / SCSS developers and CSS writers.
2) The code examples given are not identical, but in most cases they are interchangeable and are written to illustrate the tips.
1) Do not make too long investments
When we write the usual css-code, usually this problem does not work. Hardly we will write in front of the css-properties a chain of 10 elements. But with a less-code tree structure, this is quite likely. Simplify your "ladder" code. Select individual blocks and take them out. This is especially true of generic classes and id. Long chains of selectors make the file of styles more difficult, make it difficult to read, sometimes the volume of the css-file may increase due to excessive nesting twice.
poorly | Good |
---|
#root { max-width: 1200px; margin: 0 auto; .wrapper { padding: 1rem; .cart { background: #eee; h1 { font-size: 2rem; margin: 1rem 0 2rem; &#green-header { color: green; } } .good { border: 0.1rem solid #ccc; } input { border: 1px solid #ccc; &.error { background: #99ffff; } } } } }
| #root { max-width: 1200px; margin: 0 auto; .wrapper { padding: 1rem; } } #green-header { color: green; } input.error { background: #99ffff; } .cart { background: #eee; h1 { font-size: 2rem; margin: 1rem 0 2rem; } .good { border: 0.1rem solid #ccc; } }
|
View compiled css codepoorly | Good |
---|
#root { max-width: 1200px; margin: 0 auto; } #root .wrapper { padding: 1rem; } #root .wrapper .cart { background: #eee; } #root .wrapper .cart h1 { font-size: 2rem; margin: 1rem 0 2rem; } #root .wrapper .cart h1#green-header { color: green; } #root .wrapper .cart .good { border: 0.1rem solid #ccc; } #root .wrapper .cart input { border: 1px solid #ccc; } #root .wrapper .cart input.error { background: #99ffff; }
| #root { max-width: 1200px; margin: 0 auto; } #root .wrapper { padding: 1rem; } #green-header { color: green; } input.error { background: #99ffff; } .cart { background: #eee; } .cart h1 { font-size: 2rem; margin: 1rem 0 2rem; } .cart .good { border: 0.1rem solid #ccc; }
|
2) Beware of selectors, separated by commas.
If we put two or more selectors separated by commas at the beginning of the nest of the selectors (from the example above), then all the rules will be duplicated as many times as we set the selectors first. Speaking of optimizing the weight of the resulting css-file, you can judge about tens of kilobytes.
It is especially dangerous to use selectors separated by commas, when they are already nested in selectors, which are also decorated with commas. One of the severe cases is presented below.
poorly | Good |
---|
form.type { &#typeAddress, &form#typeReview { textarea { background: #eee; } table { td { &.value { padding: 1rem; } &.title { padding: 0.5rem 1rem; margin: 0.5rem 0; } &.value, &.title { background: #eee; color: #444; a { text-decoration: none; padding: 0 0.4rem; } b { color: #ccc; } p { border-left: 0.25rem solid #ece; } } &.result { padding: 1rem 0; background: green; } } } } }
| form.type { textarea { background: #eee; } table { td { background: #eee; color: #444; padding: 1rem; a { text-decoration: none; padding: 0 0.4rem; } b { color: #ccc; } p { border-left: 0.25rem solid #ece; } &.title { padding: 0.5rem 1rem; margin: 0.5rem 0; } &.result { padding: 1rem 0; background: green; } } } }
|
View compiled css codepoorly | Good |
---|
form.type#typeAddress textarea, form.typeform#typeReview textarea { background: #eee; } form.type#typeAddress table td.value, form.typeform#typeReview table td.value { padding: 1rem; } form.type#typeAddress table td.title, form.typeform#typeReview table td.title { padding: 0.5rem 1rem; margin: 0.5rem 0; } form.type#typeAddress table td.value, form.typeform#typeReview table td.value, form.type#typeAddress table td.title, form.typeform#typeReview table td.title { background: #eee; color: #444; } form.type#typeAddress table td.value a, form.typeform#typeReview table td.value a, form.type#typeAddress table td.title a, form.typeform#typeReview table td.title a { text-decoration: none; padding: 0 0.4rem; } form.type#typeAddress table td.value b, form.typeform#typeReview table td.value b, form.type#typeAddress table td.title b, form.typeform#typeReview table td.title b { color: #ccc; } form.type#typeAddress table td.value p, form.typeform#typeReview table td.value p, form.type#typeAddress table td.title p, form.typeform#typeReview table td.title p { border-left: 0.25rem solid #ece; } form.type#typeAddress table td.result, form.typeform#typeReview table td.result { padding: 1rem 0; background: green; }
| form.type textarea { background: #eee; } form.type table td { background: #eee; color: #444; padding: 1rem; } form.type table td a { text-decoration: none; padding: 0 0.4rem; } form.type table td b { color: #ccc; } form.type table td p { border-left: 0.25rem solid #ece; } form.type table td.title { padding: 0.5rem 1rem; margin: 0.5rem 0; } form.type table td.result { padding: 1rem 0; background: green; }
|
')
3) Mixins
Create mixins more often
If you are writing code and there is a feeling of deja vu, feel free to add a mixin. This will save time in future projects. Do not immediately try to make mixin perfect, with a bunch of parameters. It should be simple and straightforward. Subsequently, you will expand it and make it more universal.
Use mixin parameterization
Any mixin you use can be parameterized. First, it is convenient. Secondly, it saves the resulting result in css.
When we add a mixin, let it be the design of the button, and then with simple css properties we change its dimensions or color, then in the compiled css in the selector there will first be the rules described in the mixin, and then the ones you described. It turns out unnecessary duplication of css-properties. This can be avoided by inserting the values โโof the parameters in the mixin: so the mixin will be compiled immediately with the necessary parameters. And do not forget to set the default parameters.
poorly | Good |
---|
@color-btn: #ea186e; @color-txt: #000; .btn-flat() { display: inline-block; text-align: center; text-decoration: none; margin: 1rem 0; padding: 0.5rem 1rem; background: @color-btn; color: @color-txt; border: 0.1rem solid darken(@color-btn,15%); } #root { a.btn { .btn-flat; } button { .btn-flat; background: #ccc; color: #303; padding: 0.75rem 1.5rem; margin: 1.5rem 0; border: 0.2rem solid darken(#ccc,15%); } }
| @color-btn: #ea186e; @color-txt: #000; .btn-flat(@bgcolor: @color-btn, @color: @color-txt, @pad: 1rem) { display: inline-block; text-align: center; text-decoration: none; margin: @pad 0; padding: @pad/2 @pad; background: @bgcolor; color: @color; border: @pad/10 solid darken(@bgcolor,15%); } #root { a.btn { .btn-flat; } button { .btn-flat(#ccc, #303, 1.5rem); } }
|
View compiled css codepoorly | Good |
---|
#root a.btn { display: inline-block; text-align: center; text-decoration: none; margin: 1rem 0; padding: 0.5rem 1rem; background: #ea186e; color: #000000; border: 0.1rem solid #a60f4d; } #root button { display: inline-block; text-align: center; text-decoration: none; margin: 1rem 0; padding: 0.5rem 1rem; background: #ea186e; color: #000000; border: 0.1rem solid #a60f4d; background: #ccc; color: #303; padding: 0.75rem 1.5rem; margin: 1.5rem 0; border: 0.2rem solid #a6a6a6; }
| #root a.btn { display: inline-block; text-align: center; text-decoration: none; margin: 1rem 0; padding: 0.5rem 1rem; background: #ea186e; color: #000000; border: 0.1rem solid #a60f4d; } #root button { display: inline-block; text-align: center; text-decoration: none; margin: 1.5rem 0; padding: 0.75rem 1.5rem; background: #cccccc; color: #330033; border: 0.15rem solid #a6a6a6; }
|
A good mixin is a small mixin.
Collect mixin as cubes. See duplicate pieces of code, use mixin. Many css-properties have vendor prefixes, so for each of these properties, add a mixin with the @arguments parameter. And then invest them in other mixins.
Use mixins for properties with vendor prefixes - save your time.
@pad: 0.5rem; @bpad: @pad/5; @color-back: #fff; @color-btn: maroon; .border(@color: #ccc) { border: @bpad solid @color; } .gradient(@c1,@c2){ background: @c1; background: -moz-linear-gradient(top, @c1 0%, @c2 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@c1), color-stop(100%,@c2)); background: -webkit-linear-gradient(top, @c1 0%,@c2 100%); background: -o-linear-gradient(top, @c1 0%,@c2 100%); background: -ms-linear-gradient(top, @c1 0%,@c2 100%); background: linear-gradient(to bottom, @c1 0%,@c2 100%); } .btn(@padding: @pad) { padding: @padding/2 @padding; display: inline-block; text-align: center; text-decoration: none; } .btn-simple(@color: @color-btn) { .btn; .border(darken(@color,7%)); .gradient(lighten(@color,3%), darken(@color,3%)); color: @color-back; color: lighten(@color,40%); &:hover { .gradient(darken(@color,3%), darken(@color,8%)); color: lighten(@color,50%); } &:active { .gradient(darken(@color,15%), darken(@color,15%)); color: lighten(@color,10%); .border(darken(@color,25%)); } }
4) Use your template
In any case, especially if you do not use css / less-frameworks, create your own template, include less-files, each of which has its own set of rules. One of them may be responsible for small mixins for vendor prefixes, the other will be css resetting properties of selectors, the third - connecting web fonts and icons.
5) Use variables
Variables for sizes, for color. It helps to adhere to the grid and alignment of elements.
I use the rem unit to set the block sizes and padding , they are good because they do not depend on the size of the parent font. Thus, horizontal indents become the same, even if we change the font size. And in addition, by setting the change in font size from the screen resolution for the html tag, all sizes will proportionally increase. This applies to tablets: the text and indents there should be a little more compared to the "telephone" scale. (works in modern browsers, ie9 +)
Summarize
- Do not pursue the purity of the less-code, watch how it will be compiled
- Do not get carried away with the tree-like nesting of selectors
- Use the list of selectors with caution, and only where it is really necessary
- Add variables wherever possible.
- Use rem if browser support allows for the project. So you will get rid of the problem with different indents for the blocks and adjusting the values โโ(do not forget about browser support)
- Make mixins like cubes: move from simple properties that replace one or two properties to complex ones that include other mixins.
- Create parameterized mixins everywhere, always specifying default values.
- Use mixins for buttons, interface elements, vendor properties
Of course, many things can be optimized through special css reducers and minimizers, but we have to write quality code!