Styling your Ember app

Now that the functionality of your app is finished, you'll no doubt want to style it to make it look more appealing to use. As with most things in Ember (and other frameworks), there are strict rules for doing this. In this article we'll explore how to use CSS, images, and fonts in your Ember app.

Including assets in your app

The app structure created by Ember CLI when you first generated your app contains a public directory. The contents of this directory are copied over unchanged to the root of the dist folder when you serve your app with ember serve, so this is where you should put assets to be used in your app, like images and fonts. You should use the usual good practices for storing these, such as having separate images and fonts directories.

Create these directories inside public now, and include some sample fonts/images to use in styling your app.

Note: I found my timezone icon at softicons.com, and my fonts at fontsquirrel.com. Both offer a good selection of free to use (with CC restrictions) resources.

Including CSS in your app

The app directory inside your app's root contains a styles directory, which is where the CSS for your app goes. It contains an app.css file already, so you can put the CSS in there. When the app is served, the CSS is put inside dist/assets/ — you'll see world-clock.css in there after running ember serve. To use your assets, you'll want to reference them with relative paths, like so — ../images/my-image.png.

Add the following sample CSS into app.css, replacing the font and image references with your own (or write your own CSS completely!):

@font-face {
    font-family: 'antoniolight';
    src: url('../fonts/antonio/antonio-light-webfont.eot');
    src: url('../fonts/antonio/antonio-light-webfont.eot?#iefix') format('embedded-opentype'),
         url('../fonts/antonio/antonio-light-webfont.woff2') format('woff2'),
         url('../fonts/antonio/antonio-light-webfont.woff') format('woff'),
         url('../fonts/antonio/antonio-light-webfont.ttf') format('truetype'),
         url('../fonts/antonio/antonio-light-webfont.svg#antoniolight') format('svg');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'ds-digitalnormal';
    src: url('../fonts/ds_digital/ds-digi-webfont.eot');
    src: url('../fonts/ds_digital/ds-digi-webfont.eot?#iefix') format('embedded-opentype'),
         url('../fonts/ds_digital/ds-digi-webfont.woff2') format('woff2'),
         url('../fonts/ds_digital/ds-digi-webfont.woff') format('woff'),
         url('../fonts/ds_digital/ds-digi-webfont.ttf') format('truetype'),
         url('../fonts/ds_digital/ds-digi-webfont.svg#ds-digitalnormal') format('svg');
    font-weight: normal;
    font-style: normal;
}
html, body {
  margin: 0px;
}
html {
  font-family: 'antoniolight', sans-serif;
  background: white;
}
body {
    width: 50%;
    max-width: 800px;
    min-width: 480px;
    margin: 0 auto;
    padding: 0px;
    border: 2px solid #888;
    border-radius: 12px;
    background-color: #999;
}
li > strong, h2 > strong {
  font-family: 'ds-digitalnormal', monospace;
  font-size: 130%;
  letter-spacing: 0;
}
h1,h2 {
  text-align: center;
  background-color: black;
  color: lime;
  margin: 0px;
  padding: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  text-shadow: 1px 1px 1px black,
               2px 2px 1px lime;
}
h1 {
  border-radius: 8px 8px 0 0;
  padding-top: 20px;
  background-image: url(../images/time-zone.png);
}
h2 {
  clear: both;
  text-align: center;
  padding-top: 15px;
}
ul {
  padding: 0;
  margin: 0;
}
ul:first-of-type li {
  float: left;
  width: 50%;
  text-align: center;
}
ul:first-of-type li a {
  display: block;
  text-decoration: none;
  font-size: 1.3em;
  letter-spacing: 0.1em;
  line-height: 2.5;
  background-image: rgba(0,0,0,0.25);
  border: 2px solid #888;
  background-image: linear-gradient(to bottom, #ccc,#999);
  box-shadow: inset 4px 4px 5px rgba(255,255,255,0.4),
              inset -4px -4px 5px rgba(0,0,0,0.4);
  color: #666;
  text-shadow: 1px 1px 1px black;
}
ul:first-of-type li a:first-of-type {
  border-left: 0;
}
ul:first-of-type li a:last-of-type {
  border-right: 0;
}
ul:first-of-type li a:hover {
  color: white;
}
ul:first-of-type li a:active {
  box-shadow: inset 4px 4px 5px rgba(0,0,0,0.8),
              inset -4px -4px 5px rgba(0,0,0,0.8);
}
ul:last-of-type {
    text-align: center;
    margin-top: 20px;
}
ul:last-of-type li {
    padding-bottom: 20px;
}
li {
  list-style-type: none;
}
h2 + div {
    padding: 20px 0 10px;
}
h2 + div select {
  display: block;
  width: 49%;
  margin: 0 auto;
  line-height: 1.3;
}
h2 + div + button {
  display: block;
  width: 50%;
  margin: 0 auto;
}
h2:nth-of-type(2) {
  margin-top: 20px;
}

Note: If you are currently serving your app through localhost:4200, you'll see the app's styling update every time you save your CSS or assets. Again, this is a really useful feature!

Finish

You should now have a nice looking and perfectly functional Ember app. My app looked like this when finished:

Next

As a final step in the series, the next article will show how to get your Ember app ready for publication by creating a production build, and how to upload it to Github Pages as an easy testing/sharing mechanism.

Document Tags and Contributors

 Contributors to this page: chrisdavidmills, brittanystoroz, kscarfone
 Last updated by: chrisdavidmills,