Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support CSS #2

Open
wmertens opened this issue Aug 15, 2012 · 12 comments
Open

Support CSS #2

wmertens opened this issue Aug 15, 2012 · 12 comments

Comments

@wmertens
Copy link
Contributor

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>
@jaekwon
Copy link
Owner

jaekwon commented Aug 16, 2012

sounds useful, i'll look into this.

@wmertens
Copy link
Contributor Author

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 ;-)

@jaekwon
Copy link
Owner

jaekwon commented Aug 18, 2012

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 <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 ;-)


Reply to this email directly or view it on GitHub.

@wmertens
Copy link
Contributor Author

@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 :-)

@jaekwon
Copy link
Owner

jaekwon commented Aug 18, 2012

I think this functionality will see some iterations before we're happy :-)

Seems to be the name of the game!

@jaekwon
Copy link
Owner

jaekwon commented Aug 18, 2012

Hmm, Object key ordering is not guaranteed across JS implementations... Whereas rule ordering is important in CSS... This will probably cause headaches.

@jaekwon
Copy link
Owner

jaekwon commented Aug 18, 2012

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)

@jaekwon
Copy link
Owner

jaekwon commented Aug 18, 2012

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)

@wmertens
Copy link
Contributor Author

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?

@jaekwon
Copy link
Owner

jaekwon commented Aug 19, 2012

Ah, you're right about the ordering. Glad you knew that.

took a stab at the trailing empty rule problem:

2091282

@jaekwon
Copy link
Owner

jaekwon commented Aug 19, 2012

fixed a bug.

a0a8bb9...WM_css

@wmertens
Copy link
Contributor Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants