CSS are boring for most of the developers. They don't like it. They prefer development, because they hate supporting Internet Explorer, they find no pleasure in writing CSS and they are right : CSS is boring. Writing CSS means most of the time repeating code, supporting browsers and creating static code.
There are also the frontend required optimizations, who prevent the developer from generating beautiful and DRY CSS : sprite generation, put all CSS in one file, compress assets, and so on.
Most of the time, they prefer to have a "ready-to-use" HTML production. This approach is not the most optimal, because you need to adapt CSS, to add new rules, to refactor some parts. CSS are part of the application, as the PHP, as the HTML. When a separation like this occurs, lot of time is spent fixing CSS issues, and going through the CSS sounds like a headache.
Once upon a time, some people created some concepts for the development : Don't Repeat Yourself, Keep It Simple Stupid. Those concepts looks like forgotten when developers create CSS.
Let's see how to bring them back to the scene, let's power the CSS production.
1. Small files, please
First, whatever the context is, when you produce some code : create small and separated files.
For example, separate by purpose, as isolated as possible:
reset.css
main.css
banner.css
header.css
footer.css
- etc.
When I search something, I know the file to open, The feature is isolated. The refactoring of a feature would be fast, easy and isolated enough.
2. Sass : it's f#~king awesome
Sass is an extension of CSS adding new features to the language : mixins, variables, inheritance and more.
A Sass file looks like this:
@mixin message-color($color, $bg)
color: $color
border: 1px solid $color
background-color: $bg
#messages
.error, .success
margin: 1em
padding: 1em
.error
@include message-color(red, #ffaaaa)
.success
@include message-color(green, #aaffaa)
Sass allows to produce meaningful stylesheet code. Here we see different concepts in Sass. But to be fully impressed by Sass, you should visit the website and see examples.
The main idea is avoid repeating or computing values. Each time you are about to repeat something (a selector, a CSS ruleset), there is a method for it in Sass.
For example, to avoid computing:
$headerHeight: 50px
$menuHeight: 20px
#header
position: relative
height: $headerHeight
#menu
position: absolute
top: $headerHeight - $menuHeight
right: 0
height: $menuHeight
Here you can modify later the $menuHeight
or $headerHeight
, there is no
need to modify 20 different lines, no need to search where the value is used,
and no meaningless value in your CSS (height: 42px
, what's this value ?).
Another useful command, when you already have existing CSS is sass-convert
.
This command will convert to CSS to Sass files :
sass-convert my-file.css my-file.sass
This command has no magic inside, and cannot guess computed values, but it's a good start for Sass.
3. Compass, a framework over Sass
Sass provides the language. Compass provides the tools!
Compass is a CSS authoring framework. It provides
you helpers and utilities like image-width
, and sprite-*
methods. A
reference guide is available
with every methods.
A quick-example of features available with it:
@include "compass/reset" // Reset CSS
$logoUrl: "/logo.png"
$bgColor: blue
#header
color: $bgColor
background-color: lighten($bgColor, 40%)
#logo
width: image-width($logoUrl)
height: image-height($logoUrl)
background: url($logoUrl)
span
display: none
Sprite-generation also become very easy with Compass. Here's a small sample of sprite-generation used for the menu of this website:
$menu: sprite-map("sprites/menu-*.png");
#menu
li
background-image: sprite-url($menu)
li.blog
background-position: sprite-position($menu, "blog")
li.cv
background-position: sprite-position($menu, "cv")
li.contact
background-position: sprite-position($menu, "contact")
Awesome, heh ?
The sprite-image is generated automatically, so no need to refactor the CSS and the sprite-image when you modify an image.
4. Assetic : the magic key
Kris Wallsmith created an awesome tool for asset management: Assetic. For a brief introduction on "how it works" and "what's in it", please see his presentation on Symfony Live (slides here).
First of all, separate two things: Assetic and AsseticBundle.
Assetic is the library providing the filters, the asset manager, the formula loader, and so on. It comes with many pre-configured filters for Sass, Compass and others. It also provides the tools for combining assets.
AsseticBundle is the integration in Symfony2 providing iteration of templates to find formula, automatic generation of them in development, CLI tools, and so on.
Sample with Symfony2, Sass & Compass
Let's see how to create a Symfony2 project with some Sass files.
First, install Sass & Compass (cf Sass website <http://sass-lang.com/>
_ and Compass install guide
<http://compass-style.org/install/>
_).
Then, enable filters in your application in app/config/config.yml
. Here, I
indicate to Compass where all my images are located. So when I say
url('/images/logo.png')
, he knows it means
/my/project/web/images/logo.png
.
parameters:
# Assetic
assetic.filter.compass.images_dir: %kernel.root_dir%/../web/images
assetic.filter.compass.http_path: /images
assetic:
debug: %kernel.debug%
use_controller: false
filters:
sass: ~
compass: ~
Then, create a stylesheets.html.twig
containing your assets definition :
{% stylesheets filters="compass"
"@AlomMainBundle/Resources/assets/css/main.sass"
"@AlomMainBundle/Resources/assets/css/header.sass"
"@AlomMainBundle/Resources/assets/css/footer.sass"
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
And I include it in my layout:
<!- ... -->
<head>
{% include "::stylesheets.html.twig" %}
</head>
And that's all.
For the development environment, stylesheets are generated automatically. For the production environment, you need to generate assets before, by running :
./app/console assetic:dump --env=prod --no-debug
And that's all.
Conclusion
Mastering CSS is important for a project. Develop them the same way you develop the rest of the application is very important if you want to make the code evolve and want something reusable. This article shows you how to take benefit from modern technologies : Sass, Compass, Assetic, and Symfony2.
Even if you are not using Assetic and Symfony2, Sass & Compass are too awesome to be unused : you can use them for generating HTML templates by using Compass CLI tools.
29 November 2012 - Update
You may have problems when launching assetic command, getting exceptions. If it is so, I recommend you to complete the reading with this excellent article from Luis Cordova.
Paths should not be expressed using @AcmeDemoBundle/Resources/...
but should be expressed with
bundles/acmedemo/...
.