topaxi.codes

Using CSS Custom Properties With Ember.js

Recently there was some hype around CSS Custom Properties landing in Google Chrome. I was using them before in some Firefox only projects and with support from Google Chrome, I'm sure I will be using them even more as there are a lot of customers who are fine with Firefox + Chrome only browser support for company internal applications.

In this post, I won't go into deep detail why custom properties are awesome and very powerful. If you never heard of custom properties or css variables before, I highly recommend reading Philipp Waltons post about CSS Custom Properties. Besides the powerful feature like cascading the properties, custom properties also enables us to specify some kind of "public API" for our CSS components.

With Ember.js there are easy ways to bind a component property to a element attribute or element class, but no easy way to bind to a custom CSS property. One possibility is to bind the style attribute, but as more properties get involved the component gets bigger and more complicated. This is where my Ember.js addon ember-custom-css-properties comes in handy, it allows you to bind custom CSS properties just like attributes or classes.

Lets build a small progress-bar component using ember-custom-css-properties.

$ ember new example-app
$ ember install ember-custom-css-properties
$ ember generate component progress-bar

Open up app/components/progress-bar.js:

import Component from 'ember-component'

export default Component.extend({  
  classNames: [ 'progress-bar' ],
  cssPropertyBindings: [ 'progress' ]
})

This is all we need, when we assign something to the progress property on our component, it will be available as --progress in our CSS definitions for .progress-bar and all its descendant elements.

app/styles/app.css:

.progress-bar {
  border: 1px solid black;
  height: 24px;
}

.progress-bar::before {
  content: '';
  display: block;
  background: black;
  height: 100%;
  /* Multiply by 1% to cast to a percentage value, this way,
   * we only have to provide a numeric value for `--progress`. */
  width: calc(var(--progress, 0) * 1%);
}

app/templates/application.hbs:

{{progress-bar progress=75}}

And done! We now have a very simple progress-bar, which accepts a numeric progress property and displays the current progress.

By default, ember-custom-css-properties will wrap any JavaScript number, CSS numeric value, the string none and hex colors like #ff000 in a Handlebars.SafeString as they can't introduce any CSS XSS vulnerabilities.

As an exercise, try to add a width and height property to the progress-bar component, similar to how the <img> element works.

I think there are many use-cases and possibilities with this addon from quite static components like my example to complex animated components. I'm really curious what you can build with this! :)