## Principles

Styling is done through [SASS](https://sass-guidelin.es/) and gets compiled to
CSS. CSS is very hard to manage and can get dirty very fast if not properly
maintained. To keep this language clear and readable we try to follow certain
principles.

### BEM

[BEM](https://css-tricks.com/bem-101/), short for Block Element Modifier, is a
naming convention to describe and define classes in HTML and CSS. It improves
the readability and helps unfamiliar developers understand what a component
does.

* **Block**: The root or the top-level abstraction of a component. For example:
.button, .header, .footer
* **Element**: The child elements that are placed inside the Block and are
denoted by **`__`** (underscore, underscore) following the name of the child.
These children cannot be used outside of the Block element. For example:
.button__icon, .header__title, .footer__nav
* **Modifier**: Classes that modify or adjust the Block and its children. This
is shown by appending `--` (dash, dash) to the name of the block or child. For
example: .button--dark, .header__title--dark, .footer__nav--inverted

Here is an example of an article component using the BEM principle.

```html
<article class="c-article c-article--inverted">
	<div class="c-article__container">
		<header class="c-article__header">
			<h1 class="c-article__title c-article__title--dark"></h1>

			<h3 class="c-article__subtitle"></h3>
		</header>

		<p class="c-article__text"></p>

		<img class="c-article__image c-article__image--fluid" src="" alt="" title="" />

		<p class="c-article__text c-article__text--secondary"></p>

		<footer class="c-article__footer">
			<a class="c-article__link c-article__link--fill-space" href=""></a>
		</footer>
	</div>
</article>
```

### Namespaces

[Expanding on the BEM principle](https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/)
we add another principle to the mix to give components more context and to split
them up more in proper groups. Namespaces give us the possibility to show how
things behave and we tell developers what kind of a job a component has. Like,
seriously, prefixing a component tells a developer so much more!

* **c-**: Indicate that the element is a component. This is a standalone block
which has its own slicing, has its own modifiers, states or JavaScript. For
example: button, header, footer, collapse, input, select, ... . Try to keep
these as reusable as possible.
* **l-**: Indicate a structure, which is a collection of components to form a
layout and give an interface the proper look. These can either be reusable or
contextual For example: container, grid, section, form, ...
* **s-**: Indicate a scoped class which has its own styling context or scope.
This can for example be used to overwrite libraries, third party styling,
WYSIWYG/RTE editor, ...
* **u-**: Indicate a utility class which contains very limited styling and
usually only does one thing and cannot be overwriten. (here the use of
!important is allowed). For example: u-padding, u-center, ...
* **is-** / **has-**: Indicate a state or condition, show that a DOM structure
has a temporary or optional style applied. For example: is-open, is-active,
has-nav-open, ...
* **js-**: Indicate that the DOM has JavaScript applied to it, removing this
class should not initialise the JavaScript. For example: js-hamburger,
js-header, ...

### Responsive suffix (@)

A responsive suffix is added at the end of a class with the **`@`** sign. This
indicates that the style is only applied below or above a certain prefix.
Indicating below or above a breakpoint is done by adding the **above** or
**below** after the `@` and after that mentioning the breakpoint. When no
above or below is mentioned, by default the above indicator is used in the
styling.

**Small reminder**: CSS does not know what **@** is, so you have to escape it
within CSS. Write it as **\@** to make it readable.

#### I don't get it

Now I hear what you are thinking: What does this mean? What, that's so dirty?
Why would you do that? Why don't you just quit your job? ...

Alright, calm down! It's really useful and makes responsive classes very
readable and consistent. But let me clarify with an example:

Imagine you are in the situation where you defined a container layout and it
has a max-width and centered in the middle. Suddenly after 720 pixels the
container should no longer have this max-width. The problem here is that you
already defined container to always have a maximum width. A way to overcome this
would be to define a modifier like: l-container--special-one (🤮) or
l-container--not-below-tablet (🤮) or any other name you can come up with to
describe the behaviour. Now that's really dirty and unusable. In order to fix
this we can make use of responsive suffixes and we can call the class:
l-container@above-tablet. This defines that the container properties are only
applied the element when the viewport is above tablet.

There are 2 types of responsive suffixes:

* **@-** or **@above-**: apply slicing above the breakpoint
* **@below**: apply slicing below the breakpoint

When using these classes, only apply them on layouts or utilities to keep it as
simplistic as possible. Do not use them for components. If a component behaves
completetly different, it is a new component.

When defining these classes, always use the same names as defined within the
breakpoints map in the settings/_breakpointscss file. Keep it consistent and
clear.

#### Examples

* **c-button--secondary@above-medium**: The styling which creates a secondary
button will only be applied when the viewport is above the medium breakpoint.
* **c-header--inverted@below-medium**: The styling which creates and inverted
header will only be applied when the viewport is below the medium breakpoint.
* **l-container@medium**: The styling which creates the container will only
be applied when the viewport is above the medium breakpoint.
* **l-grid__col-6@large**: The styling which make sure that the grid column
consists out of 6 columns is only applied when above the large breakpoint.

### Specificity

[Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) is
a certain weight that is applied to a CSS decleration. This is mainly determined
by the amount of selectors within a declaration. When you want to overwrite
something the last declaration, if the specificty is equal or higher, will make
sure the styling is applied to the element.

In CSS you should always try to keep the specificity as low as possible. Always
select elements with classes. Do no use #ID's to select something. If you use
this principle it will be easy to overwrite styles and keep you CSS as clean as
humanly possible.

Exceptions:
* When defining a component state: is-open

	```sass
	.c-button {

		.is-disabled {
			pointer-events: none;
		}
	}
	```

* When applying modifiers within modifiers

	```sass
	.c-button--outline {
		border: 1px solid $primary-color-base;
	}

	.c-button--secondary {

		.c-button--outline {
			border: 1px solid $secondary-color-base;
		}
	}
	```

* Using scopes
	```sass
	.s-wysiwyg-default {

		h1 {
			color: $primary-color-base;
		}

		.heading {
			font-size: $font-size-1x-large !important;
		}
	}
	```

## Structure

A clear scss structure is quite important. This can, by default, be found in the
`src/scss` directory. If you want this in a different folder, this can be done
by updating the configuration of the project.

* **_brandplatform**: styles defined specifically for styling the
brandplatform. More information on how this works can be found in the
**overwriting the brandplatform** section below.
* **base**: The most basic styling of the project. These files do not contain
any classes and are used to style HTML-tags **ONLY** or load in fonts. When
starting the slicing, everything starts here. For example: button, heading,
text, ...
* **components**: Components form the basis of everything on a project. They
can be either used as a standalone block or contextual to a certain degree. For
example: button, header, footer, ...
* **layouts**: Layouts are used in giving the structure to the pages and are
a combination of a large collection of components. These are more focused on
creating the interface and combining the components instead of defining a
standalone block. They should be very reusable, but there layouts is not fixed
in stone and can vary.
* **scopes**: Scopes are used to overwrite third party styling or style tags
or classes within a different context like styling a WYSIWYG/RTE editor tags
without influecing any other elements that use these tags.
* **settings**: Contain **ONLY** variables and maps used to define the basis
like colors, layout, typography, breakpoints, dimensions, ...
* **tools**:
	* **extends**: These ar extendable classes/components used to create more
	consistency and link the styling of comonents that are the same but not
	related to each other. These are not SASS extends, but SASS mixins that
	apply styling when included.
	* **functions**: Functions used to pass values to and return a different
	value, which has gone through some modifications. This **ALWAYS** returns
	a value.
	* **mixins**: Mixins are handy functions that can be included to apply
	slicing based on certain conditions, they are very similar to functions
	but do not return a value. They make our lives in the wonderfull world of
	CSS so much nicer and enjoyable.
* **utils**: Apply one type of styling to an element. It only does what the name
of the class indicates. The use of !important here is allowed because these
styling don't need to get overwritten en should always win over any other
property.
* **vendors**: styles from third parties or other libraries that should not get
compiled.
* **brandplatform.scss**: A file containing **ONLY** imports to overwrite
the and add some styles to the brandplatform system. This file is not passed
towards clients or any other project but is only used in this system.
* **main.scss**: This is a standalone CSS file containing only the slicing of
the items that were imported. This is the main CSS file where everything comes
together.

## Creating a component

When adding a component to the **components** folder you should always try to
keep the structure readable and not use selectors inside each other to keep the
specificity as low as possible when selecting blocks, elements or modifiers.

### SCSS file structure

The order the file is structured is very important to create a consistent
structure throughout the CSS files:

* Private variables / calculations
* Block or component root
* Elements
* Modifiers
* States
* Animations (@keyframes)

### Ruleset

#### Private variables

Define the private variables above the file, these can be anything to create
context and avoid the use of magic numbers. Private variables can contain magic
numbers or reusable units or other calculations.

#### Root element

Define the root element of the component, for example: **c-button**. Very
important to know is that you should never ever, ever, ever, ... ever (x1000)
place margins around your component. The component should be self contained and
the spacing around it is variabele in any type of context. If a margin is placed
on the component, it should be standard and not be overwritten by any type of
modifier on the component like c-button--with-margin-large (🤮). Utilities and
layouts should be used to control the spacing within a structure. Only on
layouts modifiers it is allowed to define margins and spacing around it.

#### Component to component

Root, elements and modifiers of a component should no modify or change the
styling of a different component. This is because components should be self
contained and adjustments should happen in the component folder itself. In some
cases this is allowed, if there is no other choice or the way to solve the issue
is hacky.

#### Tags within components

In these component files we do not select any tags, these should be selected
within the base folder. They should not be selected within classes themselves,
unless the tags are generated without classes. ALWAYS place a class on a HTML
element, even if there is no styling. It gives context and shows the next
developer or your lovely colleague what the element is supposed to be. You just
saved your colleague some time and confusion, you are a true hero.

#### Elements / children

Elements should only contain styling for the components children like
c-button__icon or c-button__text. These should not contain tags and should be
the most simplistic selector that has ever existed. This means just ONE
selector. If there is no choice, pseudo selectors like :last-child, :first-child
are allowed but should be used with an after thought.

#### Modifiers and naming them

Modifiers are to be placed on the components root or the components children.
The selectors are allowed to adjust multiple children. So the specificity is
allowed to be increased in this context. Modifiers can only be used on and
within the root of the component. It is bad practice to use these modifiers
outside their respective context.

#### States specificty

States are classes that indicate a temporary or changable styling when executing
an action or identifying a component state. These are meant to have a higher
specificty so that they cannot be overwritten. They are prefixed with is-/has-
to indicate a boolean. States can be placed on root, children and modifiers.
But we never use !important in any type of situation within the declaration of a
component or its state.

```sass
// =============================================================================
// :: Settings
// =============================================================================
$button-spacing: 2rem;

// =============================================================================
// :: Button
// =============================================================================
.c-button {}

// =============================================================================
// :: Elements
// =============================================================================
.c-button__text {}

// =============================================================================
// :: Modifiers
// =============================================================================
.c-button--secondary {}

// =============================================================================
// :: States
// =============================================================================
.c-button {

	&.is-disabled {}
}

// =============================================================================
// :: Animations
// =============================================================================
@keyframes button-fade-in {

}
```

## Breakpoints map

Within the settings folder of the scss structure there is a file called
**_breakpoints.scss**. This file only contains a map or better known as a type
of object containing the different breakpoints defined into the system. These
are extremely, like you cannot imagine, important. These work well together
with layouts like grid or container to create layouts that are quite common in
visual design.

Each key within the mapped variable represents a breakpoint. This is based on
the mobile-first principle, meaning that these values are applied when the
viewport is above the defined width. More breakpoints can be added and
responsive classes should be linked to these names. Keep this system consistent
or you will get a very messy structure.

Defining these breakpoint names can be linked to the viewport width. This way
you create a readable, non-contextual structure. The number added to the
breakpoint name is the first number of the defined width.

* viewport-0
* viewport-4
* viewport-7
* viewport-9
* viewport-12

The properties in each object:

* **width**: the width of the breakpoint, the properties and values are all
applied when the viewport width is above this value.
* **viewport-spacing**: the spacing on the sides of the viewport, which
separates the content from the sides of the viewport.
* **spacing**: the default spacing that should be used when above this
breakpoint. This does not mean that it should be used in every component. But it
is used in the grid to create spacing between the columns.
* **header-height**: the height of the header on top of the page.
* **grid-suffixicate**: the grid in every brandplatform is auto-generated. This
means that a lot of classes are generated based on the breakpoints map in order
to create custom and responsive layouts. When this value is false, the grid
classes for that breakpoint are not generated and you minified CSS file has
decreased in size. Only define this property as true if you need to use grid
with the breakpoint naming convention.

```scss
$breakpoints: (
	"viewport-0": (
		width: 0,
		viewport-spacing: 1.5rem,
		spacing: 1.5rem,
		header-height: 6rem,
		grid-suffixicate: false
	),
	"viewport-4": (
		width: 48rem,
		viewport-spacing: 2rem,
		spacing: 2rem,
		header-height: 6rem,
		grid-suffixicate: true
	),
	"viewport-7": (
		width: 72rem,
		viewport-spacing: 3rem,
		spacing: 2.5rem,
		header-height: 6rem,
		grid-suffixicate: true
	),
	"viewport-9": (
		width: 96rem,
		viewport-spacing: 4rem,
		spacing: 3rem,
		header-height: 8rem,
		grid-suffixicate: true
	),
	"viewport-12": (
		width: 128rem,
		viewport-spacing: 6rem,
		spacing: 4rem,
		header-height: 8rem,
		grid-suffixicate: true
	)
);
```

## Overwriting the brandplatform

When first installing the lmr-brandplatform npm package. You will probably see
all the colors and typography in the default styling. There is a way to
overwrite this and use custom colors and typography.

Within the config file you can link a CSS file to overwrite the brandplatform
slicing. This is slicing that will only be applied on the brandplatform and will
not and should not affect any type of component. Adjust the config file by
adding a new key **overwrite** and link the minified file.

```js
	styles: {
		overwrite: "/css/overwrite.min.css"
	},
```

Create the file with the same name on the root of the scss folder and start
adding imports or any css rule that should overwrite the styling of the
brandplatform. By default we have given you variables that can overwrite colors
and typography so that you don't have to write any selectors or !importants.

### Colors

Replace the value of the variables to change them in the brandplatform. **DO NOT
CHANGE THE NAME OF THE VARIABLE** or it will not be applied within the
brandplatform slicing.

```scss
// =============================================================================
// :: Primary
// =============================================================================
$bp-primary-color: hsla(216, 98%, 48%, 1);

// =============================================================================
// :: Secondary
// =============================================================================
$brandplatform-secondary-color: hsla(219, 59%, 17%, 1);

// =============================================================================
// :: Text
// =============================================================================
$bp-text-color-base: hsla(219, 59%, 17%, 1);
$bp-text-color-white: hsla(0, 0%, 100%, 1);
$bp-text-color-medium: hsla(219, 59%, 17%, 0.8);

// =============================================================================
// :: Border
// =============================================================================
$bp-border-color-base: hsla(219, 59%, 17%, 0.15);
$bp-border-color-light: hsla(220, 16%, 96%, 1);

// =============================================================================
// :: Background
// =============================================================================
$bp-background-color-base: hsla(0, 0%, 100%, 1);
$bp-background-color-white: hsla(0, 0%, 100%, 1);
$bp-background-color-light: hsla(220, 16%, 96%, 1);
$bp-background-color-medium: hsla(219, 59%, 17%, 0.15);
$bp-background-color-black: hsla(0, 0%, 0%, 1);
$bp-background-color-dark: hsla(219, 59%, 17%, 1);

// =============================================================================
// :: UI
// =============================================================================
$bp-ui-color-feature: hsla(82, 86, 44, 1);
$bp-ui-color-update: hsla(48, 100, 46, 1);
$bp-ui-color-bug: hsla(354, 81, 49, 1);
```

### Typography

Replace the value of the variables to change them in the brandplatform. **DO NOT
CHANGE THE NAME OF THE VARIABLE** or it will not be applied within the
brandplatform slicing.

```scss
// =============================================================================
// :: Font family
// =============================================================================
$bp-font-family-primary: ("Helvetica", "Arial", sans-serif);
$bp-font-family-secondary: ("Helvetica", "Arial", sans-serif);
```

### Other

If you want to overwrite any other slicing you have to select the items in the
brandplatform yourself. Do not change too much, the system is designed with
these changes in mind but has its own standards.

The brandplatform is only sliced with classes and does not contain any sort of
slicing on tag so that it will not conflict with your styleguide/component
library styling. Every class in the brandplatform is prefixed with **bp-**.
