Journey into the heart of the three most known CSS preprocessors continues, though not in the way I originally planned.
CSS preprocessor is a tool that take code written in their own syntax and generates the CSS for the browser. The most popular preprocessors are SASS, LESS and Stylus. We have talked about installation and syntax + mixins. All three preprocessors have a fundamentally different way of mixins conception.
Each of them have gallery of finished mixins: For SASS there is a comprehensive Compass, the LESS has framework Twitter Bootstrap or small Elements a Stylus NIB.
… this was opening sentences of article I started write year and quarter ago and never finished. I came to the conclusion that all three preprocessors are useless. They required to do so many compromises that potential benefits seemed insignificant. Today I will explain it.
CSS preprocessor is not something I can use from scratch. I'm not a complete novice with CSS, I have a 10 year history, and now I have a mature system and preprocessor should fit in it. How does this system look like? According to me, nothing unusual.
If you look under the hood of this blog, you will find that the server sends
just one CSS file and just one JS, both minimized. And file
combined.css
contains styles for all devices, i.e. screen, printer,
mobile phones, retina, etc. Uncompressed looks like this:
@import "http://fonts.googleapis.com/css?family=Open+Sans:400&subset=latin,latin-ext";
@import "libs/reset.css";
@import "libs/classes.css";
@import "libs/fshl.css" screen;
@import "fancybox/jquery.fancybox.css" screen;
@import "layout.css" screen;
@import "homepage.css" screen;
@import "libs/print.css" print;
@import "print.css" print;
The entire stylesheet is divided into a number of smaller units. In the
libs
there is a small CSS framework that defines the basic rules
that shares all my projects (btw reset.css
is nothing weird as Eric
Meyer's reset, but rather something like this), there
are styles for used components and the rest of website. Most of the
@import
rules are media-dependent, so they are applied only to the
printer or screen etc.
In stylesheet I like to use indentation, which fundamentally improves readability:
a {
padding: 3px;
margin: 0 -3px;
text-decoration: none;
}
a:hover, a:active, a:focus {
color: white;
background-color: blue;
}
article {
margin: 2em 0;
}
article hr {
visibility: visible;
clear: none;
}
article footer {
margin-top: 2em;
}
I must emphasize that this all is plain CSS 2.0, which correctly displays
any browser. The only requirement is that the rules @import
must be
placed at the beginning of the file, before anything else. Inside included files
it is possible to include other files or use media queries, allowing tuning for
mobile devices or loading images in a higher resolution for retina displays (the
browser correctly combines media query in the file with the media specified
within @import
rule).
The whole structure could be uploaded to server and it will normally work. But I wrote a simple script which all the @imported files combines to a single file, minimizes it and then uploads to the server. It has a good impact on the speed of page loading, especially if you're reading in places with bad internet connection.
And to this ecosystem I wanted bring CSS preprocessor. It should, of course, take place of the CSS combinator and allow me better address some of the CSS lacks.
How foolish I was!
Preprocessors ignore @imported files unless you change their extension from
.css
to the proprietary one (ie .less
,
.scss
, .sass.
or .styl
). This is
annoying, you lost associations with applications, in some editors will not work
syntax highlighting etc. Well, what can I do. (It is entirely proper to use
proprietary extensions, I am just talking about @import
, which
cannot process CSS files, as SASS states, CSS is subset of SCSS syntax, and you
need to rename extension).
Suddenly I see that I have lost some images. Why? For example,
jquery.fancybox.css
contains a definition of
background-image: url ('fancybox_sprite.png')
, both files are
located in the subdirectory fancybox
. When we combine styles from
different directories into a single file, of course, we have to transpose all
relative paths. It gives common sense. And, of course, this is what the browsers
when evaluate @import
do, this do the mentioned 15 lines long
stupidos function in FTP deployment too, only preprocessors don't and generate
crippled output. Really ☹
I was unable to figured out a way how to bypass this defect. Make a mess in the folder and move all images to the root directory? Modify the paths in styles? In the styles of third parties?
But the misery is far from over…
CSS preprocessors can not handle even with media-dependent
@import
:
@import "fancybox/jquery.fancybox.css" screen;
You have to remove screen
from import and wrap the entire
contents of the included file in @media screen {... }
(Except for
SASS, it allows you use @media screen { @import "style.css"}
).
Besides to that I don't want to modify files, especially not third parties
files, because it complicates future updates, these modifications could be
non-trivial. For example, fancybox.css
itself contains@media
queries for retina and the question is, how preprocessor can handle nested media
queries. They have big problems with it.
And that's not all!
The significant is how reprocessors understand my existing CSS files (which
extension I was forced to change). Great, SASS and LESS was confused only with
=padding: 0
(LESS casually reported syntax error on quite a
different line), it is the legendary underscore hack for
IE6 in version for IE7. No problem, I deleted this obsolete rule and everything
worked.
Not so in the case of a Stylus (and I admit that it was my favourite one).
It crashes with indentation. It said unexpected 'indent'
and
finito. Just ordinary comment
makes Stylus cry in a corner.
My friends, I could use CSS preprocessor, but I have to totally fuck up my clean directory structure and drastically modify styles and styles of third parties. For benefits of mixins and variables? No, thank you 🙂
And I am not talking about tons of bugs in LESS and Stylus. Stylus is unable
to do as basic tasks as move @import
rules to the top of the file
and generate valid CSS. Sad. *(Please do not write me that you are using a
preprocessor and everything works for you, it's just as silly as when doctor
refuses to treat fracture of your leg, because his leg does not hurt at
all.) *
A year and quarter later
This happened a year and quarter ago. Very long time for hot technologies development. That time I reported all discovered bugs and today I'd like to see what is new with our three friends.
- SASS maintains sassus quo, all the weaknesses and strengths remain.
- Stylus? Total disappointment. It can now deal with relative paths (with
option
-r
) but no bug was solved and author now works on new preprocessor. - LESS. A year ago outsider, today it generates perfect CSS. Wow!
LESS makes me very happy! Yes, I did not use any advanced features and I am
just happy about the fact that LESS understand CSS at least as IE6 did, and can
generate (with option -ru
) valid merged file, a skeptic might argue
that this is not so revolutionary achievement, but in the world of CSS
preprocessors it is amazin success, it warmed my heart, years of intensive
development was not useless!
HAPPY END.
Comments
Martin Andersson #1
Thank you for your insightful thoughts!
This article has been closed. It is no longer possible to add comments.