GrooCSS - code CSS in Groovy

Download

GrooCSS

GrooCSS let's you code your CSS in Groovy, using a natural Groovy DSL with optional code completion.

Like Less but without inventing a new language.

It was created by Adam L. Davis (@adamldavis) and inspired by the many other Groovy-based projects out there, like Gradle, Grails, Spock, Ratpack, and grooscript.

Principles: Stay in pure Groovy, get as close to CSS as possible, and maximize code reuse.

Getting Started

Introduction Gradle What's new? Measurement math Config Other

Examples

Static DSL Code Completion

From 1.0-M1 onwards, GrooCSS uses groovy extension modules to extend String, Integer, and Number so the following syntax can be used fully with IDE code completion.

def myColor = 'fe33ac'.color   // creates a Color object
def mySize = 100.px

'.box'.sg {             //sg or $ can be used interchangeably whichever you prefer
  color myColor          // resolves to color: #fe33ac
  borderColor whiteSmoke // borderColor becomes border-color; built-in named colors
  padding 2.em           // resolves to 2em; validated
}
table {
    color myColor background black //fluent
}
'table.my-class'.$ {
    color darken(myColor)  // tint, shade, lighten, mix, fade, and many other methods
}
input %odd {          // becomes input:nth-child(odd)
    background yellow
}
'formId'.id {       // resolves to #formId
    minWidth mySize      // resolves to 100px
    maxWidth mySize*2    // resolves to 200px
    fontSize 1.cm + 2.mm // you can add different types
    extend(table)        // ability to extend previously defined styles
}
$('.box div') {      // can use jQuery-style as well
  boxShadow '0 0 5px rgba(0, 0, 0, 0.3)'
}

Dynamic Styles DSL/More Operators

def myColor = c('#fe33ac')

_.box {           // _.box becomes .box
  color myColor
  borderColor '#fdcdea'
}
table {
    color myColor
}
table.my_class {           //can be configured to replace _ with -
    color myColor.darker()
}
input['class$="test"'] = { //becomes input[class$="test"]
    background yellow
}
sg '#formId', {     // sg useful for ID's
    minWidth 100.px // resolves to 100px
}
_.box div {
  boxShadow '0 0 5px rgba(0, 0, 0, 0.3)'
}
p + div {
    border '1px solid black'
}
p.red | a.red { color red } // | => ,
p >> a { color blue }       //>> => >
p * a { color blue }        // * => *
p - a { color blue }        // - => ~(tilde)
p ^ a { color blue }        // ^ =>  (space)

Dynamic vs. Static/XOR Not always needed

For many cases, XOR (^) is not actually needed. Keep in mind when you use dynamic method calls it will disable code completion. For example, using dynamic groovy (CSS on left, GrooCSS on right):


"div p.test a{text-decoration: none;}" => { div p.test a { textDecoration 'none' } }
"div.man p.test a{text-decoration: none;}" => { div.man p.test a { textDecoration 'none' } }
"div.man .test a{text-decoration: none;}" => { div.man _.test a { textDecoration 'none' } }
"body div p a{text-decoration: none;}" => { body div p a { textDecoration 'none' } }
"body div.test p a{text-decoration: none;}" => { body div.test p a { textDecoration 'none' } }
"body div.test p li a{text-decoration: none;}" => { body div.test p li a { textDecoration 'none' } }

If you prefer having NO dynamic code (all static) use the sg method whenever a styleClass is needed. For example:

sg 'div p.test a', { /*DSL*/ } or 'div p.test a'.sg { /*DSL*/ }