Skip to content

Working with Styles

Ste Allan edited this page Feb 9, 2016 · 5 revisions

We use the SCSS syntax of Sass to build our CSS.

###Watching for changes Providing you have run ember serve from your terminal or command prompt, changes to any .scss files will be detected automatically and the CSS compiled for you.

###Styling Solomon Our aim is to keep our styles as generic and reusable as possible. Wherever we can, we take parts of Solomon and create components whose styles can easily be reused. So instead of writing the same styles for something that already exists, simply applying the correct markup will utilise the existing styles. Of course, this isn’t applicable in every situation and so there will be some areas where it doesn’t make sense to have a generic component. In this case, we style our elements using more specific hooks.

For most instances, we use custom HTML attributes to style Solomon, instead of classes. This has the benefit of reducing specificity and preventing style clashes through name-spacing. Solomon is currently being refactored and so there will be some areas where styles are still applied through classes until they have been updated. Also, SVGs generated and applied through Grunticon utilise classes.

###Styling with attributes Our custom attributes are named using the basic principles of BEM. For those unfamiliar with BEM (which stands for Block Element Modifier), the aim is to make the relationship between the different elements of a component obvious, along with any variations thereof. This gives the attributes the following structure:

[scope]-[block][_element]=“[modifier]”

Here, [scope] is a required prefix which determines the scope of the attribute: whether it’s a generic component or a specific instance. If the attribute is for a generic component, then the prefix would be cpn; and if it’s a specific instance, the prefix would be spc. For example, we might have a component which applies margin to an element, cpn-margin="bottom" which can be reused by other elements and then another component which contains specific styles for a unique component, spc-unique-component. When using both types of attributes on an element, put the specific attribute first as this makes it easier to identify your components:

<div spc-unique-component cpn-margin="bottom">...</div>

Using these prefixes helps prevent potential conflicts with other HTML attributes.

The name of the component - [block] - is where we start to use the principles of BEM. So, say we have a reusable search component:

<div cpn-search>
  <input cpn-search_input />
  <button cpn-search_button>Search</button>
</div>

The div would be the ‘Block’ in this instance (or parent, if you like) and the input and button would be the 'Elements' (or children) - [_element] - here denoted by the text following the underscore in the attribute. An underscore must only be used in this way, to define elements of a component.

The ‘M’ part of BEM stands for ‘Modifier’. This is where variations of a component are defined. So, looking back at our search example, let’s say we wanted the input to be larger than the base (unmodified) component:

<div cpn-search>
  <input cpn-search_input=“large” />
  <button cpn-search_button>Search</button>
</div>

What we’re doing here is applying a modifier to the input by passing the value large into the cpn-search_input attribute.

###CSS attribute selectors To use these attributes to apply our styles, all we do is use regular CSS attribute selectors:

[cpn-search] {…}
[cpn-search_input] {…}
[cpn-seach_button] {…}

Those selectors will target our base components. So, what about our modified elements? They are still styled using the attribute selector, but this time we pass in the value we are using as a modifier:

[cpn-search_input~=“large”] {…}

Notice the ~ before the value is passed in. This changes the selector to target elements which have the specified value set on the attribute but - and this is crucial - not necessarily just that value. This allows us to pass in multiple modifiers so, for example:

<input cpn-search_input=“large dark”>

Would take styles from:

[cpn-search_input~=“large”] {…}

and

[cpn-search_input~=“dark”] {…}

If we didn’t use ~ and our selector was just:

[cpn-search_input=“large’] {…}

this would not target the element <input cpn-search_input=“large dark”> because large isn't the only value of the targeted attribute.

This method applies in the majority of cases, however there are some instances where you would want to target only a certain value. Take a float component, which applies either left, right or none. You would never have more than one modifier value so here we can construct our selector without ~:

[cpn-float=“left”] {…}

###Ready-made styles Before making your own component and styles, check first if what you want doesn’t already exist. There are lots of prewritten components available. Similarly, Solomon utilises a Sass library called Bourbon. This comes with a myriad of Sass mixins, functions and more which you can use to apply styles without having to write them yourself.

###File structure Just like with the styles, we like to keep our Sass file structure as organised as possible. You’ll find the Sass files inside ‘app/styles’. Styles are split into their own partials so that each Sass file generally holds the styles for only one thing. Generic components have their own partials and can be found inside the ‘cpn’ folder. And specific styles go in more specific partials. For example, when a story is generated it gets its own partial, inside ‘components/stories’. There are other partials for certain parts of Solomon and others still for app-wide styles. Should you need to add your own partial, make sure you import it into 'app.scss' in the relevant section.

Return to Documentation

#Quick Links

###Help for users

###Help for developers

Clone this wiki locally