Stylus, a better CSS

26.05.2012 15:41Comments
There are a lot of wrong things about CSS, but in the there’s been other languages created to empower CSS, and once you get used to any of these there’s no going back. The most common are SASS and LESS which have been around for a while. While these languages are very good (in particular SASS) and they do most of the things that Stylus does, there’s one aspect of CSS that they don’t address by design: the syntax. Both SASS and LESS try to stay as close as CSS original syntax as possible to minimize the impact of having to learn a new language. While this is something positive, in my opinion Stylus approach is much better. A few of the most cool features these languages provide:
  • Variables
  • Functions
  • Nesting rules
Stylus not only empowers CSS but it also improves the syntax for much better readability, for example:
  • Braces are optional.
  • Colons to separate property from values are optional.
  • Semi colons at the end of lines are optional.
Here’s an example of how the style of a vertical menu could look like: menu Needless to say that this looks clean, simple and concise. As opposed to: menu-css

Semantic Markup

For me one of the most important reasons why I wanted to use SASS, LESS (or Stylus in this case), is that it allows you to really start coding html with semantic markup. From wikipedia, semantic markup is:
Semantic HTML is the use of HTML markup to reinforce the semantics, or meaning, of the information in webpages rather than merely to define its presentation (look).
This basically means that you can write your html in a way that describes the meaning of what it holds, rather than the style. As an example of this, you won’t need to use classes like “span_12”, “vertical”, “horizontal”, “right”, “left” anymore; all these represent presentational concepts rather than explaining the meaning of the content. Writing html in a semantic way, makes much more sense and allows for safer refactorings and redesigns of your websites.

Stylus in with Expressjs

Using stylus with Expressjs could really not be any simpler. All you have to do is add the “stylus” module to the package.json file like this: package Then, just add the following like of code right before you set up the static middleware for your express application:
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
Should look somethig like this: configure Stylus is smart enough that it will compile the “.styl” files whenever these files change into “.css” files so that from your views you will only have to reference the “.css” file version. So go ahead and create a “site.styl” file inside of your “stylesheets” folder, and put the following code:
body
    body: red
Now run your node application and browse to http://localhost:3000/stylesheets/site.css and you should see something like this: site Now that we have stylus working let’s do a more realistic scenario.

Introducing Semantic.gs

Semantic.gs is a grid system which has a version built for stylus that allows you to create all kinds of grid systems and layouts, even fluid, fixed and/or responsive. I like it because it is extremely easy to setup and use. Download the files from the website and copy the grid.styl file that is in the zip file into your “stylesheets” folder (and while you are at it you might as well use the reset.css). Next, we need to import the grid.styl file into our site.styl file with this line in the top of the file:
@import grid
Now let’s see how to work with stylus and semantic.gs to make a fluid layout and semantic markup. One of the ways in which you can tell whether you are being semantic is if you code your markup without worrying about how it will look later. So in my case this is the markup (in jade format) that I really want to have in my page:
doctype 5
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/site.css')
  body

    #container
      header
        h1 My Super Layout

      #menu
        ul
          li Home
          li About us
          li Contact us

      #sidebar
        ul
          li Option 1
          li.selected Option 2
          li Option 3

      #content
        body!= body
So nothing out of the ordinary really, if you want to see what it looks like you can see it here, just a container with the header, a menu and then a side bar and a content section. Suppose that I would like to have this site in a fluid layout with a maximum width of 960px with a grid system of 12 columns. Using semantic.gs this is extremely simple to do, we already imported the grid.styl, and now we have to specify the amount of columns by setting the following property (which actually is 12 by default):
columns = 12
Now we are going to tell it that we want to be fluid:
/* semantic.gs make the grid fluid */
total-width=100%
And for having a max width of 960 and the content centered, we’ll apply the following style to the container:
#container
    max-width: 960px
    margin-left: auto
    margin-right: auto
Honestly, it couldn’t be any easier. Now let’s keep on with the rest of the layout. I want the header to occupy the entire width of the layout, so that’s 12 columns in the grid system we chose:
header
    column(12)
So normally, if we would have wanted to do this in plain old CSS, we would have have to add the “header” selector to some rule shared with every other element we wanted to occupy the entire with, and we would end up with a pretty messed up CSS pretty quick. We want the menu to be horizontal, and to take the entire width so we create a class “horizontal” with the common css for styling horizontal lists, and we extend it with the menu specific properties:
.horizontal
    li
        list-style: none outside none
        
        margin-left: 10px
        padding-left: $padding
        &:first-child
            padding-left: 0
            margin-left: 0

#menu
    column(12)
    ul
        @extend .horizontal
        margin: 15px 0px
        li
            border-left: 1px solid grey
            &:first-child
                border-left: 0
Even when we are using a class that has presentational meaning, we are not touching our markup (which is what we wanted Smile) Same thing for the Side Bar, except this time, we only want the side bar to occupy a part of the width in our page. How much? Let’s say 3 columns, which leaves us with 9 columns for the actual content of the page. And we want to add an extra rule that says that if the list item is selected, then it should have a red line in the right border. Notice the use of the “&” character in order to access the parent “li” with the extra “selected” class. By doing this the entire style for the side bar resides in one single block of code.
.vertical
    li
        list-style: none outside none
        display: block
        margin-bottom: 10px

#sidebar
    column(3)
    ul
        @extend .vertical
        li
            border-bottom: 1px solid grey
            &.selected
                border-right: 3px solid red;

#content
    column(9)
And in case you were wondering how the entire file looks like here it is (much cleaner and prettier than CSS, LESS or SASS in my opinion):
@import "reset.css"
@import grid

/* semantic.gs make the grid fluid */
total-width=100%

/* some common variables */
$font_xl = 36px
$padding = 10px
$theme_color = red

body
    font: 14px "Lucida Grande", Helvetica, Arial, sans-serif

h1
    font-size: $font_xl
    margin: $padding 0

/* since it's fluid, let's put a max width and center the content */
#container
    max-width: 960px
    min-height: 480px
    margin-left: auto
    margin-right: auto

header
    column(12)
    border-bottom: 1px solid grey

/* this can be reused whenever we need a horizontal list */
.horizontal
    li
        list-style: none outside none
        
        margin-left: 10px
        padding-left: $padding
        &:first-child
            padding-left: 0
            margin-left: 0

#menu
    column(12)
    ul
        @extend .horizontal
        margin: 15px 0px
        li
            border-left: 1px solid grey
            &:first-child
                border-left: 0

/* this can be reused whenever we need a vertical list */
.vertical
    li
        list-style: none outside none
        display: block
        margin-bottom: 10px

/* between the side bar and the content we should have 12 columns */
#sidebar
    column(3)
    ul
        @extend .vertical
        li
            border-bottom: 1px solid grey
            &.selected
                border-right: 3px solid $theme_color

#content
    column(9)
 

comments powered by Disqus