Support CSS
Using the this swizzling trick I describe in #1, you could also support CSS for the @style section. The CSS syntax is here: http://www.w3.org/TR/css3-syntax/
Basically I'm thinking that there would be only a couple functions, @rule, @media, @import etc, and the @rule would take a selector string and one or more objects with the CSS properties as key-value pairs). When property order matters (only seldomly), then multiple @rule calls for the same selector could be used.
The @rule function could automagically add vendor extensions for new properties like box-sizing or border-radius.
Some hypothetical examples inspired by lesscss.org:
@style ->
color="#4D926F"
@import "other.css"
@rule "#header", color: color;
@rule "h2", color: color
roundedCorners = (radius = "5px") ->
"border-radius": radius
@rule "#header", roundedCorners(), border: "2px solid red"
@rule "#footer", roundedCorners("10px")
would result in
<style>
@import "other.css";
#header {
color: #4D926F;
}
h2 {
color: #4D926F;
}
#header {
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border: 2px solid red;
}
#footer {
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
}
</style>
sounds useful, i'll look into this.
I've been thinking about this some more and in the mean time I found SASS which has neat features like calculation on colors and nesting. I think CoffeeMugg could do the same.
@style would take objects, arrays of objects, or a function with separate @css statements which would do the same without adding a <style> tag.
The objects would be multi-level: The main object has selectors as keys and the values are property/value objects or sub-selector objects. Some properties can get objects as well, like font.
To avoid having to quote, properties could optionally be written with _ instead of -.
Finally sass has special syntax to handle colors and lengths. That could be done with classes, maybe at a later stage.
So where sass would say
$blue: #3bbfce
$margin: 16px
.content-navigation
border-color: $blue
color: darken($blue, 9%)
.border
padding: $margin / 2
border-color: $blue
table.hl
margin: 2em 0
td.ln
text-align: right
li
font:
family: serif
weight: bold
@mixin table-base
th
text-align: center
td, th
padding: 2px
@mixin left($dist)
float: left
margin-left: $dist
#data
@include left(10px)
@include table-base
CoffeeMugg could have
blue = cm.color "3bbfce"
margin = cm.px 16
table_base =
th:
text_align: center
"td, th":
padding: "2px"
left = (dist) ->
float: "left"
margin_left: dist
@style
".content-navigation":
border_color: blue
color: blue.darken 0.09
".border":
padding: margin.div 2
border_color: blue
"table.hl":
margin: "2em 0"
"td.ln":
text_align: right
li:
font:
family: "serif"
weight: "bold"
"#data": [ table_base, left("10px") ]
The result for either should be something like
.content-navigation {
border-color: #3bbfce;
color: #2b9eab;
}
.border {
padding: 8px;
border-color: #3bbfce;
}
table.hl {
margin: 2em 0;
}
table.hl td.ln {
text-align: right;
}
li {
font-family: serif;
font-weight: bold;
}
#data {
float: left;
margin-left: 10px;
}
#data th {
text-align: center;
font-weight: bold;
}
#data td, #data th {
padding: 2px;
}
Looks nice, no? Sass also offers selector inheritance which seems a little complicated to put into CoffeeMugg (you need to parse and cache selectors), and I don't think it adds much value over writing custom functions.
A limitation with this approach is that you can't use the same selector in the same object twice, but you can work around that with an array of objects.
I think CoffeeMugg shouldn't try very hard to make the CSS concise, there are CSS minifiers if that is needed.
I already took a stab at my first proposal but now I'll try this first. Should be doable, I'll see which features won't make it ;-)
Good suggestions.
How about blue = @color '#3bbfce'? (vs cm.color)
and keeping pixels as regular numbers? That way users can manipulate pixel values easier by using +/-/*...
On Aug 18, 2012, at 4:20 AM, wmertens wrote:
I've been thinking about this some more and in the mean time I found SASS which has neat features like calculation on colors and nesting. I think CoffeeMugg could do the same.
@style would take objects, arrays of objects, or a function with separate @css statements which would do the same without adding a
The objects would be multi-level: The main object has selectors as keys and the values are property/value objects or sub-selector objects. Some properties can get objects as well, like font.
To avoid having to quote, properties could optionally be written with _ instead of -.
Finally sass has special syntax to handle colors and lengths. That could be done with classes, maybe at a later stage.
So where sass would say
$blue: #3bbfce $margin: 16px
.content-navigation border-color: $blue color: darken($blue, 9%)
.border padding: $margin / 2 border-color: $blue
table.hl margin: 2em 0 td.ln text-align: right
li font: family: serif weight: bold
@mixin table-base th text-align: center td, th padding: 2px
@mixin left($dist) float: left margin-left: $dist
#data @include left(10px) @include table-base CoffeeMugg could have
blue = cm.color "3bbfce" margin = cm.px 16 table_base = th: text_align: center "td, th": padding: "2px" left = (dist) -> float: "left" margin_left: dist
@style ".content-navigation": border_color: blue color: blue.darken 0.09
".border": padding: margin.div 2 border_color: blue
"table.hl": margin: "2em 0" "td.ln": text_align: right
li: font: family: "serif" weight: "bold"
"#data": [ table_base, left("10px") ] The result for either should be something like
.content-navigation { border-color: #3bbfce; color: #2b9eab; } .border { padding: 8px; border-color: #3bbfce; } table.hl { margin: 2em 0; } table.hl td.ln { text-align: right; } li { font-family: serif; font-weight: bold; } #data { float: left; margin-left: 10px; } #data th { text-align: center; font-weight: bold; } #data td, #data th { padding: 2px; } Looks nice, no? Sass also offers selector inheritance which seems a little complicated to put into CoffeeMugg (you need to parse and cache selectors), and I don't think it adds much value over writing custom functions.
A limitation with this approach is that you can't use the same selector in the same object twice, but you can work around that with an array of objects.
I think CoffeeMugg shouldn't try very hard to make the CSS concise, there are CSS minifiers if that is needed.
I already took a stab at my first proposal but now I'll try this first. Should be doable, I'll see which features won't make it ;-)
— Reply to this email directly or view it on GitHub.
@color works too, I didn't use it because at first I was considering using a function for each of the 290 CSS properties and it collided.
For the lengths the problem is that px and em etc aren't easily convertible. Hmm, perhaps a default unit should be settable and then when you use a number for a property they get that unit? Means parsing the values though.
A @px = (x) -> x + 'px' function and others like it could also be used — easier to type.
I think this functionality will see some iterations before we're happy :-)
I think this functionality will see some iterations before we're happy :-)
Seems to be the name of the game!
Hmm, Object key ordering is not guaranteed across JS implementations... Whereas rule ordering is important in CSS... This will probably cause headaches.
Here's a jab at it...
@style unit:'pixels', ->
blue = @color "#3bbfce"
margin = 16
# Helper functions could also be defined on this (@):
@table_base = ->
@_ "th",
text_align: center
@_ "td, th",
padding: "2px"
@left = (dist) ->
@_ "&",
float: "left"
margin_left: dist
# Object style
# (length 1 enforced, to keep things clean)
@_ ".content-navigation": # rule name
border_color: blue # css property
color: blue.darken 0.09 # css property
# Object style in a procedure
if someCondition
@_ ".border":
padding: margin.div 2
border_color: blue
# String with function style
@_ "table.hl", -> # Here we use a function block (->...) because we have multiple @_ rules.
@_ "&": # You must proxy with '&', because the argument is always a rule, never a CSS property.
margin: "2em 0"
@_ "td.ln":
text_align: right
# String with an Object style
@_ "li",
font: [
{family: "serif"}, # Objects in arrays get merged for you
{weight: "bold"}
]
# Same effect as above
@_ "li",
font:
family: "serif"
weight: "bold"
# Procedures
@_ "#data", ->
@table_base()
@left(10)
# All together without comments... hmm.
@style unit:'pixels', ->
blue = @color "#3bbfce"
margin = 16
@table_base = ->
@_ "th",
text_align: center
@_ "td, th",
padding: "2px"
@left = (dist) ->
@_ "&",
float: "left"
margin_left: dist
@_ ".content-navigation":
border_color: blue
color: blue.darken 0.09
if someCondition
@_ ".border":
padding: margin.div 2
border_color: blue
@_ "table.hl", ->
@_ "&":
margin: "2em 0"
@_ "td.ln":
text_align: right
@_ "li",
font:
family: "serif"
weight: "bold"
@_ "#data", ->
@table_base()
@left(10)
Finally, the ultimate DSL hack... the letter 'o'
@style unit:'pixels', (o) ->
blue = @color "#3bbfce"
margin = 16
table_base = ->
o "th":
text_align: center
o "td, th":
padding: "2px"
left = (dist) ->
o "&":
float: "left"
margin_left: dist
o ".content-navigation":
border_color: blue
color: blue.darken 0.09
if someCondition
o ".border":
padding: margin.div 2
border_color: blue
o "table.hl", ->
o "&":
margin: "2em 0"
o "td.ln":
text_align: right
o "li":
font:
family: "serif"
weight: "bold"
o "#data", ->
table_base()
left(10)
Indeed, that is a nice hack... I've already implemented the first syntax though :-)
Ordering in css is important, but only in certain cases (see here):
- same property of a selector getting different values
- same selector (because of the property)
Basically when you need ordering you're doing a bit of a hack and then using an array or multiple @css calls to enforce ordering and allow same keys seems fine, no?
e.g.
@style -> @css
"h3": [
display: "inline"
, display: "run-in"
]
or
@style ->
@css "h3": display: "inline"
@css "h3": display: "run-in"
would do the right thing.
I dropped the font: { weight: xxx } thing for now, because I think it confuses matters more than it helps writing CSS.
I added the code to the css branch of my repo. Needs more tests and the prefix expansion. Thoughts?
Ah, you're right about the ordering. Glad you knew that.
took a stab at the trailing empty rule problem:
https://github.com/jaekwon/CoffeeMugg/commit/209128237a2543a9f1d43814c8abaac5aa717a6c
fixed a bug.
https://github.com/jaekwon/CoffeeMugg/compare/a0a8bb9c1cdce1c8ce747830cb008b2b9b4d2bd9...WM_css
Yey, thanks!
I added prefixing, looks good I think!
Now for those color, length and animation classes... I think I'll first try to make some web pages.