Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Merge release-v2.8.5 into master
Browse files Browse the repository at this point in the history
  • Loading branch information
johnboxall committed May 29, 2019
2 parents bf0064f + 5e2556c commit d2aa296
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 148 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v2.8.5 (May 29, 2019)
- Remove `linebreak-style` blocks windows users from linting their code properly [#169](https://github.com/mobify/mobify-code-style/pull/169)
- Add in Responsive Best Practices section, updated references to Adaptive [#165](https://github.com/mobify/mobify-code-style/pull/165)

## v2.8.4 (October 31, 2017)
- Add support to copyright tooling for TypeScript files (.ts, .tsx) [#164](https://github.com/mobify/mobify-code-style/pull/164)

Expand Down
1 change: 1 addition & 0 deletions css/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* [When to use our selector naming scheme](class-naming-conventions#when-to-use-our-selector-naming-scheme)
* [When to use their existing selectors](class-naming-conventions#when-to-use-their-existing-selectors)
* [How to use their existing selectors in our components](class-naming-conventions#how-to-use-their-existing-selectors-in-our-components)
* [Responsive Best Practices](responsive-best-practices/readme.md)
* [Localization and Theming Best Practices](localization-and-theming-best-practices/readme.md)
* [Block Comment Documentation Guide](comments/Readme.md)
* [Hybrid Projects Best Practices](hybrid-projects/Readme.md)
Expand Down
37 changes: 17 additions & 20 deletions css/class-naming-conventions/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ Our CSS class naming convention (which we call CSM or Component, Sub-Component,
</div>
```

This example may seem confusing at first but if we break down each of the selectors that we have, it begins to make more sense.
This example may seem confusing at first, but if we break down each of the selectors that we have, it begins to make more sense.

`.c-blog` This is a high-level component. In this example, it describes a wrapper that may contain blog content.

`.c-blog__title` This is a sub-component. In this example, it is a title for a blog.
`.c-blog__title` This is a sub-component. In this example, it's a title for a blog.

`.c-blog-post` This is another high-level component. In this example, it describes the blog post itself. Notice that it is its own component instead of a sub-component of `c-blog` because a blog post does not need to be child of the blog container. This way the component is able to live anywhere.
`.c-blog-post` This is another high-level component. In this example, it describes the blog post itself. Notice that it can be its own component instead of a sub-component of `c-blog` because a blog post does not need to be child of the blog container. This way, the component is able to live anywhere.

`c-blog-post.c--featured` This is a modifier. Notice that the `c--featured` class is paired with the component or sub-component it belongs to. In this example, it describes a different way of displaying the `c-blog-post` component.

`.c-blog-post__time` Like before, this is another sub-component this time belonging to the `c-blog-post` component. It is still a sub-component even though it is not a **direct** child of the component. In other words, sub-components are not required to be direct children of its parent component.
`.c-blog-post__time` Like before, this is another sub-component this time belonging to the `c-blog-post` component. It's still a sub-component, even though it is not a **direct** child of the component. In other words, sub-components are not required to be direct children of their parent component.

### Components

Expand All @@ -70,7 +70,7 @@ Components are independent and self-contained units of UI. Styles belonging to a

### Sub-components

Sub-components are elements that are child to its parent component. The classname should be formatted as such: `c-[parent-component-name]__[sub-component-name]`. Sub-components do not, and should not, have sub-components of their own. If you find you need to write a sub-sub-component, instead just treat it as a sub-component – sub-components are only ever child to the parent component.
Sub-components are elements that are descendants of their parent component. Their classnames should be formatted as such: `c-[parent-component-name]__[sub-component-name]`. Sub-components do not, and should not, have sub-components of their own. If you find you need to write a sub-sub-component, instead just treat it as a sub-component.

Like components, these should always live at the root level of a file. Avoid nesting these within the parent component or another sub-component.

Expand Down Expand Up @@ -103,7 +103,7 @@ Like components, these should always live at the root level of a file. Avoid nes

### Modifiers

Modifiers, as their name suggests, modify components or sub-components. They are always chained to the component or sub-component they belong to.
Modifiers, as their name suggests, modify components or sub-components. They're always chained to the component or sub-component they belong to.

* Prefixed with the namespace of the affected element and two dashes (`c--`, `t--`)
* Contained to the scope of a single component
Expand Down Expand Up @@ -292,7 +292,7 @@ Prefix | Purpose | Location |
`.m-` (*) | Desktop embedded mobile markup classes: these are classes that we will use if we author Markup that is intended for clients to embed onto their desktop pages, but is for mobile content. | *n/a* |
`.js-` | Javascript classes are used exclusively by scripts and should never have CSS styles applied to them. Repeat: **Do NOT** style Javascript classes. | *n/a*

> \* The `m-` class prefix has an old, deprecated use: Mobify Modules. However, Mobify Modules have been replaced with third part plugins, and are treated as third party libraries with their own conventions.
> \* The `m-` class prefix has an old, deprecated use: Mobify Modules. However, Mobify Modules have been replaced with third party plugins, and are treated as third party libraries with their own conventions.

## Components That Style Components
Expand All @@ -308,9 +308,9 @@ Sometimes there are situations when a component makes use of other components, a
</button>
```

In situations like this it is tempting to just style the icon's class inside of the button. However, this practice is poor and creates tight coupling between the Button and Icon components that shouldn't exist. As a rule of thumb, a component should only know about what it's responsible for; it should be unaware of anything external to itself. Continuing with this example, the Icon is an external component, therefore the Button component should be completely unaware there there is even such thing as icon classes, like `c-icon`.
In situations like this it is tempting to just style the icon's class inside of the button. However, this practice is poor and creates tight coupling between the Button and Icon components that shouldn't exist. As a rule of thumb, a component should only know about what it's responsible for; it shouldn't be aware of anything external to itself. Since Icon is an external component, the Button component should be completely unaware of `c-icon`.

The solution to this challenge is to instead give the external component a new class that our new component can know about, like `c-button__icon`. By doing it in this way the external Icon component is, for all intents and purposes, being treated as a sub-component of the Button component. This method also has the benefit of being free of any (tight) coupling between the components. Both components can change, be added or removed, without really effecting the other in an unpredictable way.
The solution to this challenge is to instead give the external component a new class that our new component can know about, like `c-button__icon`. This way, the component is treated like a sub-component of Button, and eliminates any tight coupling between the components. Both components can change, be added or removed, without affecting the other in an unpredictable way.

So, to summarize...

Expand Down Expand Up @@ -349,25 +349,22 @@ So, to summarize...

## Parsing vs. Decorating

It's important to understand that we have a few different ways of authoring our CSS, and the way we do this is depends a lot on how we convert the desktop markup for mobile. Ideally, we parse the desktop markup and take full control of the final HTML. However, this isn't always possible, and sometimes we just output the desktop markup as is: untouched, or perhaps partially wrapped in order to control the appearance entirely through CSS.
Ideally, we have total control over the HTML markup of a project. However, sometimes there are engineering requirements that force us to retain client markup, or partially wrap it in a container of our own.

If you find yourself wondering "should I be adding a new class, or should I use the classes from desktop?" consider the following: If we're using their class names, we obviously can't follow our CSM syntax. But that said, sometimes we just have no choice; perhaps there are engineering requirements that force us to retain the markup structure. Under such circumstances, we must stick to the desktop classes.

Below is laid out some situational advice that should clarify when to use desktop classes and when to author our own. We also talk about ways to adjust the code style when using their class names.
If you find yourself wondering "should I be adding a new class, or should I use the classes from desktop?" consider the following: If we're using their class names, we can't follow our CSM syntax. Here's some advice:

### When to use our class naming convention

* When writing your own markup in a template
* When decorating (adding, moving, or wrapping) markup in a View, Parser, Decorator or UI-Script
* When decorating (adding, moving, or wrapping) markup in a View, Parser, Decorator or UI-Script (Adaptive.js)
* When adding custom classes to existing markup
* When you find yourself using @extend

### When to use their existing selectors
### When to use client selectors

* When it's fastest, easiest or most efficient to use their markup than it is to add our own.
* When their markup is too inconsistent, or makes parsing too difficult.
* When mobile functionality is tightly coupled to desktop's markup structure.
* When intercepting AJAXed content or content added after a page is too costly, unperformant, or inefficent.
* When functionality is tightly coupled to markup structure.

### How to use their existing selectors in our components

Expand All @@ -394,7 +391,7 @@ Always component classes should always be structured with our naming conventions

Desktop classes can be added inside their parent component, but adding our own classes should be your FIRST approach so as to avoid nesting.

Constantly evaluate your nesting in situation like this.
Constantly evaluate your nesting in situations like this.

```scss
// Okay
Expand Down Expand Up @@ -427,7 +424,7 @@ Constantly evaluate your nesting in situation like this.
}
```

Use their modifiers the same way you would use our modifiers. Chain it to the component or sub-component it directly affects.
Use their modifiers the same way you would use our modifiers. Chain them to the component or sub-component it directly affects.

```scss
// Okay
Expand Down Expand Up @@ -456,4 +453,4 @@ Use their modifiers the same way you would use our modifiers. Chain it to the co
}
```

Continue on to [Block Comment Documentation Guide ](../localization-and-theming-best-practices/readme.md)
Continue on to [Responsive Best Practices ](../responsive-best-practices/readme.md)
44 changes: 22 additions & 22 deletions css/css-best-practices/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* [A Note On Attribute Selectors](#a-note-on-attribute-selectors)
* [Class Naming Convention](#class-naming-convention)
* [Self Documenting Selectors](#self-documenting-selectors)
* [Mobile First](#mobile-first)
* [Single Direction Rule](#single-direction-rule)
* [Name Spacing](#name-spacing)
* [Size Units](#size-units)
Expand All @@ -21,9 +22,7 @@

## Code Like it's 2020

Because we use Autoprefixer, we are able to write our code as if all our properties are fully supported. When compiled, Autoprefixer will of course convert any properties that have special requirements as far as compatibility is concerned and add prefixes to them as needed.

That includes things like Flexbox, CSS3 properties, and many more! This also means that we *should not* be using mixins for prefixing. Remember that Autoprefixer uses data from caniuse.com to determine what will be output — so properties that don't have enough browser support should probably still be avoided (or at least used with extreme caution).
Because we use post-processors, we are able to write our code as if all our properties are fully supported–includeing things like Flexbox, CSS3 properties, and many more! This also means that we *should not* be using mixins for prefixing.


## Selector Specificity
Expand All @@ -32,32 +31,30 @@ We strive to write performant, portable, selectors whenever possible. In short,

To help do that, it might be helpful to know how to measure specificity which [Smashing Magazine has an article just for that](http://www.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/)!

### Dos:
### Some Notes:

* Use class names for specificity because it improves performance.
* Use the component oriented naming conventions outlined below.
* If you have no other choice and you must select an ID, use the attribute selector instead

### Do Nots:

* Avoid using IDs. They decrease portability.
* Use the component oriented naming conventions outlined below.
* Avoid using tag selectors. They both impact performance and portability.
* Never over qualify selectors because it impacts performance.
* If you have no other choice and you must select an ID, use the attribute selector instead


```scss
// NO
// Instead of:
ul.button-group li.button {
}

// Yes
// Try:
.button-group__button {
}

// NO
// Instead of:
#something {
}

// Yes (Only as a last resort!)
// Try (Only as a last resort!):
[id="something"] {
}
```
Expand All @@ -67,7 +64,7 @@ ul.button-group li.button {

A common use case is to target input types. For example `input[type="text"]`.

It's important to realize that the element selector is not necessary here. If you think about it, we are actually increasing the specificity needlessly. Attribute selectors have the same specificity as a class. The above example has the same specificity as `input.someClass`
It's important to realize that the element selector (`input`, in this case) is not necessary here. Using `input` increases the specificity needlessly. Attribute selectors have the same specificity as a class. The above example has the same specificity as `input.someClass`

All we really need is `[type="text"]`, because that is sufficient for targeting text inputs.

Expand All @@ -76,7 +73,7 @@ In summary: *attribute selectors should be used alone*, just like classes.

## Class Naming Convention

We use a modified version of BEM that we call CSM (Component, Sub-component, Modifier). At it's core, it's virtually identical to BEM, but our exact syntax is slightly different. Basically:
We use a modified version of BEM that we call CSM (Component, Sub-component, Modifier). At its core, it's virtually identical to BEM, but our syntax is slightly different. Basically:

```
.c-component
Expand All @@ -93,14 +90,18 @@ When authoring CSS, you should be always aware of the selectors that you are cre

Strive to create selectors that actually fully describe where it is authored. Put another way, any given selector should tell you which file and where in the file it is written.

This can be down by following this simple rule: the first class in a selector is the file it can be found
This can be done by following this simple rule: the first class in a selector is the file it can be found.

For example `.t-pdp .c-product` would be written in `_pdp.scss` and NOT `_product.scss`.

The exception to this rule are when a base or root class is dependant on a global state.
The exception to this rule is when a base or root class is dependent on a global state:

`.x-landscape .t-about .c-contact-form` would be found in `_about.scss` and NOT a `_landscape.scss` file (modifier classes alone don't have their own files). Using `x-` prefixes is an old convention and won't be found very often.

For example `.x-landscape .t-about .c-contact-form` would be found in `_about.scss` and NOT a `_landscape.scss` file (modifier classes alone don't have their own files).

## Mobile First

When styling responsively, we use min-width queries and build on top of them when we need to. Learn more about our other responsive best practices [here](responsive-best-practices/readme.md).

## Single Direction Rule

Expand All @@ -115,9 +116,7 @@ This principle is talked about in depth by [Harry Roberts on csswizardy.com](htt

## Name Spacing

The first thing you'll notice when going through Customer Success's CSS is that all of our class names are prefixed (aka: name-spaced) to one of two letters: `c-` or `t-`, meaning `_component_` or `_template_` respectively. See the [below table](../class-naming-conventions#class-prefix-conventions) for more details on Mobify's namespacing practices.

Because we work on top of our client's markup and javascript, we need to make sure our class names will never conflict with their class names. By prefixing/namespacing our classes with `c-` or `t-`, we can be assured that 99.9% of those situations are avoided.
The first thing you'll notice when going through our CSS is that all of our class names are prefixed (aka: name-spaced) to one of two letters: `c-` or `t-`, meaning `_component_` or `_template_` respectively. See the [below table](../class-naming-conventions#class-prefix-conventions) for more details on Mobify's namespacing practices.


## Size Units
Expand Down Expand Up @@ -230,6 +229,7 @@ And as before, we use [Sass-Lint](https://github.com/sasstools/sass-lint) to hel
1. Pseudo-elements
1. Modifier elements
1. Child elements
1. Media Queries

```scss
.c-selector {
Expand Down Expand Up @@ -309,7 +309,7 @@ And as before, we use [Sass-Lint](https://github.com/sasstools/sass-lint) to hel
Sometimes we break out of this convention to add to the readability of our stylesheets. This occurs especially often with long comma separated property values like gradients, shadows, transitions, or includes. These can be arrange across multiple lines and indentation levels to help with diffs and readability.

```scss
.x-selector {
.c-selector {
@include icon(
home,
$color: blue,
Expand Down
1 change: 1 addition & 0 deletions css/csscomb/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ Before you start, make sure you have [Package Control](https://packagecontrol.io
* [CSSComb for VIM](https://github.com/csscomb/vim-csscomb)
* [jetbrains-csscomb](https://github.com/csscomb/jetbrains-csscomb) which should work for all JetBrains IDEs, such as IDEA, PyCharm, WebStorm, PhpStorm, RubyMine, and perhaps others.
* [CSSComb for Emacs](https://github.com/channikhabra/css-comb.el), including Aquamacs
* [CSSComb for VS Code](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-csscomb)

0 comments on commit d2aa296

Please sign in to comment.