micro-css

A CSS preprocessor that provides a simplified object orientated approach to css. The syntax is very similar to CSS but encourages better reuse of classes and discourages high specificity.

Micro CSS

A CSS preprocessor that provides a simplified object orientated approach to css. The syntax is very similar to CSS but encourages better reuse of classes and discourages high specificity.

I think there comes a time in any front-end web developer's life when CSS stops being "the most amazing powerful design language on earth" and changes to become the skeletons in our closet that we prefer not to think about too much. This was certainly my experience.

CSS is undoubtedly powerful, but it's too powerful. It encourages you to do things that seem efficient and clever at the time but eventually turn in to absolute maintenance nightmares.

One night I couldn't sleep, I was thinking about the new redesign and how many things would start to break or have to be hacked around to do the new CSS. I realized that I would probably have to completely start again with the CSS on the page. But how should I structure it so that this wouldn't happen again?

I got reading on the internets, trying to find better ways to do it - preprocessors, frameworks, etc. I'd used SASS/SCSS in the past, and while the nesting functions were nice, it was still far too easy to make a mess. I came across Stubbornella's Object Oriented CSS project. I really liked some of the ideas and concepts. Things like writing for reuse and avoiding specificity. For me OOCSS it wasn't the answer though, it just didn't click for me, so I started to think about how I could twist CSS to be less unwieldy.

I wanted to be able to define objects, but not have to worry about where those objects were on the page. I wanted those objects to have multiple elements but not have those styles spill into other objects. I wanted to be able to add classes to objects as tags/flags - only applying if the object were a particular type. I wanted to be able to create mixins that could be applied to multiple elements, but not used on their own. CSS can do all of these things fairly easy, but it just doesn't encourage it.

So this was the point I realized I was going to have to come up with my own CSS subset that forced these things, but made them far easier to do, and much more manageable/readable. One of my design goals was to make the class attributes in the HTML very easy to understand, using the single class field for assigning object type, meta data flags, and mixins.

Here's some HTML we want to style:

<html>
  <head>
    <title>HTML5 Rules, but css is still just css...</title>
  </head>
  <body>
    <aside class="Sidebar -mini">
      <header></header>
      <section></section>
      <footer></footer>
    </aside>
    
    <article class="Page -wide -editable -post">
    
      <header>
        <h1>Post Title</h1>
        <p>Subtitle</p>
      </header>
      
      <nav></nav>
      <section>
        <header></header>
      </section>
    </article>
    
  </body>
</html>

And some MCSS to do the styling:

  Sidebar {
    header {
      font-weight: bold
      color: white
      background: #363
    }
    section {
      header {
        
      }
      footer {
        
      }
    }
    footer {
      
    }
  }
  
  Page {
    header {
      
    }
    nav {
      
    }
    section {
      
    }
    footer {
      
    }
  }
  
  Comment {
    
  }

You'll notice that MCSS provides an easy way to view an overall structure of your page. In fact I almost always write the MCSS first to figure out how the page will be laid out then write the HTML to match.

$ npm install micro-css -g

When installed globally execute:

$ mcss filepaths... -o outfile.css

Or it can be used by API in Node.js:

var microCss = require('micro-css')
var finalCss = microCss("Item { color: red } body { font: 80% sans-serif }")  // read from file or hardcoded like this 

Because semicolons always annoyed me...

The following MCSS:

Item {
  border: 1px solid gray;
  background: silver;
}

Becomes:

.Item {
  border: 1px solid gray;
  background: silver;
}

As long as it starts with a lower case letter... otherwise it'll see it as an Object class.

Item {
  h1 {
    font-weight: normal
  }
  p {
    margin: 4px 0px
  }
}

Becomes:

.Item > h1 {
  font-weight: normal
}
.Item > p {
  margin: 4px 0px
}

Makes it not so IE6 friendly, but it's so worth it (then again IE6 doesn't even support multiple classes!)

Item {
  (strong{
    font-weight: bold
    color: #333
  }
}

Becomes:

.Item strong {
  font-weight: bold;
  color: #333;
}
Item {
  color: black
  -special {
    color: red
  }
}
AnotherItem {
  color: black
}

Becomes:

.Item {
  color: black;
}
.Item.-special {
  color: red;
}
.AnotherItem {
  color: black;
}
<div class='Item'>
  back text
</div>
<div class='Item -special'>
  red text
</div>
<div class='AnotherItem -special'>
  still black text as '-special' is not defined for 'AnotherItem'
</div>

So I can use the -special flag wherever I like and not worry about stepping on another namespace.

Item {
  -unknown-disabled{
    color:gray
  }
  -disabled {
    opacity:0.5
  }
}
h1h2h3h4 {
  font-weight: normal
}

Becomes:

.Item.-unknown {
  color: gray;
}
.Item.-disabled {
  color: gray;
  opacity: 0.5;
}
h1h2h3h4 { /* this one is left unchanged - one of the few parts that work exactly like standard css */
  font-weight: normal;
}
Listing {
  -featured {
    h1 {
      color: orange
    }
  }
  -sold {
    h1 {
      color: red
    }
  }
  -featured -sold {
    h1 {
      color: green
    }
    opacity: 0.5
  }
}

Becomes:

.Listing.-featured > h1{
  color: orange;
}
.Listing.-sold > h1{
  color: red;
}
.Listing.-featured.-sold > h1{
  color: green;
}
.Listing.-featured.-sold{
  opacity: 0.5;
}
<div class='Listing -featured'>
  <h1>This text will be orange</h1>
</div>
<div class='Listing -sold'>
  <h1>This text will be red</h1>
</div>
<div class='Listing -sold -featured'>
  <h1>This text will be green</h1>
  And this div will be transparent
</div>

A way to reuse styles in multiple places.

$fancyThing {
  box-shadow: 10px 10px silver
  div {
    font-size: 90%
  }
}
 
Item {
  $fancyThing 
  
  border: solid 1px gray
  background-color: fuchsia
}

Becomes:

.Item {
  border: solid 1px gray
  background-color: fuchsia
}
.\$fancyThing, .Item {
  box-shadow: 10px 10px silver;
}
.\$fancyThing > div.Item > div {
  font-size: 90%;
}

So we can also use the $mixin directly as well if we like.

Except severely crippled so you can't hurt yourself.

Item {
  color: black
  div.main {
    font-weight:bold
  }
  div.extra {
    color: gray
  }
}

Becomes

.Item {
  color: black;
}
.Item > div.\.main {
  font-weight:bold
}
.Item > div.\.extra {
  color: gray
}

And we can use it like this in our HTML:

<div class='Item'>
  <div class='.main'>
    I am some main text
  </div>
  <div>
    I am a standard div
  </div>
  <div class='.extra'>
    I am an extra div
  </div>
</div>

They can only be used with an element selector, and never on their own. And generally should be avoided if they have a better pure element alternative.

@svg test {
  width: 20px
  height: 20px
  content: "<path d='M0,0 L20,20' />"
 
  path {
    stroke: #CCC
    stroke-width: 3
    fill: none
  }
}
 
Item {
  background-image: svg(test)
}

Becomes

Item {
  background-image: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bW...)
}

The svg is automatically inlined as a data url.

@keyframes animationName {
  from { background-color: red }
  50% { background-color: green }
  to { background-color: blue }
}

Becomes

@keyframes animationName {
  from { background-color: red; }
  50% { background-color: green; }
  to { background-color: blue; }
}