The CSS codebase is a Sass solution (we use the SCSS syntax) with BEM as naming convention. For a quick intro to BEM, please read this excellent article by Harry Roberts: MindBEMding – getting your head ’round BEM syntax.
We use stylelint to test for possible errors and formatting issues. You can install tools like stylelint for Visual Studio Code to give you instant feedback on your code. You may also run the gulp task “stylelint” to test your scss code for errors.
We encourage you to follow these guidelines. If you fail to do so your code will probably;
There are exceptions where we want to commit code that “break” the rules — this is possible but requires that comments are inserted into the code. For example /* stylelint-disable-line name-of-rule */
.
Don’t mess with cursor
-property unless you’ve invented a completely new (and un-native) interactive element.
Never remove the :focus
style completely. If you remove the default outline
, please replace it with something that is either as noticeable or more noticeable.
ys-
. This is to avoid naming conflicts and inheritance issues.ys-
-classes may never be overwritten or modified.All ys-
selectors are also preceded by html:not(#ys-specificity)
which is added to heighten specificity on the selector. This is done to avoid other CSS from “bleeding” into the DNA components — ie. some projects who include DNA might not be using strict BEM (or similar), and if they have styling on elements there is no way to prevent those styles from being inherited by DNA components, so we have to do our best to have a higher specificity than those rules.
Explain code as needed, where possible. (They will be removed in production anyway).
//Use this for short comments
/* Use this for long comments that needs more explanation.
What does it cover, what purpose does it serve, why is
respective solution used or preferred */
Use lowercase for everything. This applies to CSS selectors, properties, variables and property values etc. You can use a hyphen instead of camelCasing.
Bad example
.Example {
//
}
.contentBox {
//
}
Good example
.example {
//
}
.content-box {
//
}
Class names should always follow BEM.
Never use ID as selectors, they are way too specific. Make heavy use of classes because they are the ideal selector
Blocks have NO prefixes
Elements are always prefixed with two underscores
modifiers are prefixed with tow hyphens
long names are separated by one hyphen
avoid underscores in class names besides for elements
Bad examples
#some-class
.class_name
.longnotwellnamedclassname
.block__withsomeelememt
Good examples
.classname
.class-name
.long-wellnamed-classname
.block__with-some-elememt
.block__with-some-elememt--modifier
Naming selectors should always be sematic. Don’t name it based on its looks. That will quickly get redundant.
Bad examples
.blue-button-with-space
.blue-button-with-space--withyellowborder
Good examples
.button--primary
.button--primary--highlighted
Don’t nest selectors if it’s not necessary. As a good practice maximum nest up to three layers. Also, before every nested class or selector there should be a linebreak for readability reasons.
Not allowed
.feedback {
//
.feedback__header {
//
.feedback__subheader {
//
.feedback__subheader--special {
//
}
}
}
&__content {
&--modifier {
//
}
}
}
Good example
.feedback {
//
&__header {
//
}
&__subheader {
//
&--special {
//
}
}
&__content {
//
&--modifier {
//
}
}
}
Indent by 2 spaces at all time. Don’t use tabs or mix tabs and spaces for indentation.
Bad example
.example {
color: $color-white;
}
Good example
.example {
color: $color-white;
}
Always use single quotes
Bad example
content: "Hello";
background: url("/img/image.jpg");
Good example
content: 'Hello';
background: url('/img/image.jpg');
Remove trailing white spaces. Trailing white spaces are unnecessary and can complicate diffs.
Bad example
.example {
font-size: rem(16);_
}__
Good example
.example {
font-size: rem(16);
}
End every declaration with a semicolon for consistency and extensibility reasons.
Bad example
.class {
display: block
}
Good example
.class {
display: block;
}
Use a space after a property name’s colon. Always use a single space between property and value (but no space between property and colon) for consistency reasons.
Bad example
.class {
font-weight:bold;
}
Good example
.class {
font-weight: bold;
}
Use a space between the last selector and the declaration block. Always use a single space between the last selector and the opening brace that begins the declaration block.
The opening brace should be on the same line as the last selector in a given rule and the closing brace should be immediately after the last rule.
Bad example
/* Not recommended: missing space and there is a unnecessary line break */
.class{
margin-top: rem(16);
}
/* Not recommended: unnecessary line break */
.class
{
margin-top: rem(16);
}
Good example
.class {
margin-top: rem(16);
}
Separate selectors and declarations by new lines. Always start a new line for each selector and declaration.
Bad example
&:hover, &:active, &:focus {
background: $color-white;
color: $color-white;
}
Good example
&:hover,
&:active,
&:focus {
background: $color-white;
color: $color-white;
}
Separate rules by new lines. Always put a blank line (two line breaks) between rules. Also if the class is nested
Bad example
.class {
margin: rem(16);
min-width: rem(80);
}
.another-class {
margin: rem(16);
min-width: rem(80);
.nested-class {
margin: rem(16);
min-width: rem(80);
}
}
Good example
.class {
margin: rem(16);
min-width: rem(80);
}
.another-class {
margin: rem(16);
min-width: rem(80);
.nested-class {
margin: rem(16);
min-width: rem(80);
}
}
Use shorthand properties where possible. CSS offers a variety of shorthand properties (like font) that should be used whenever possible. Using shorthand properties is useful for code efficiency and understand-ability.
Bad example
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: rem(16);
font-weight: bold;
line-height: 1.6;
padding-bottom: rem(32);
padding-left: rem(16);
padding-right: rem(16);
padding-top: 0;
Good example
border-top: 0;
font: bold rem(16)/1.6 palatino, georgia, serif;
padding: 0 rem(16) rem(32);
Don’t use qualified selectors with type selectors.
Bad example
a.classname
ul.someclass
body div ul li.myclass
Good example
.classname
.someclass
.myclass
Please nest all media queries directly in to the class it affects. Make sure there is an empty line above the media-query to improve readability.
Bad example
.classname {
margin: rem(16);
min-width: rem(80);
}
@media (min-width: 768px)
.classname {
min-width: rem(128);
}
}
Good example
.classname {
margin: rem(16);
min-width: rem(80);
@media (min-width: 768px) {
min-width: rem(128);
}
}
Always declare your CSS rules for smallest screen possible. Then use breakpoints to change layout for bigger screens.
Bad example
.classname {
display: flex;
@media (max-width: 768px) {
display: block;
}
}
Good example
.classname {
display: block;
@media (min-width: 768px) {
display: flex;
}
}
YouSee DNA and Bootstrap use the same media queries. This is because the grid in YouSee DNA is build on top of Bootstrap.
Breakpoints
xs = Extra small <576px (default)
sm = Small ≥ 576px
md = Medium ≥ 768px
lg = Large ≥ 992px
xl = Extra large ≥ 1200px
If you have installed YouSee DNA you can/should write your media queries like this:
@media (min-width: $ys-breakpoint-sm) { ... }
@media (min-width: $ys-breakpoint-md) { ... }
@media (min-width: $ys-breakpoint-lg) { ... }
@media (min-width: $ys-breakpoint-xl) { ... }
Don’t use them. We add them automatically when compiling SCSS code to CSS . In some rare cases you still need to add them though.
Bad example
-webkit-border-radius: 12px;
-moz-border-radius: 12px;
border-radius: 12px;
Good example
border-radius: 12px;
Using !important is bad practice and should be avoided. It makes it difficult to override if necessary and breaks the natural cascading in your stylesheets. Always look for a way to use specificity before even considering !important.
By indicating one or more elements before the element you’re selecting, the rule becomes more specific and gets higher priority. If you HAVE to use !important please remember to disable the linter for that particular line: /* stylelint-disable-line declaration-no-important */
.
Bad example
.element {
display: none !important;
}
Good example
.class .element {
display: none;
}
// or if you have to
.element {
display: none; /* stylelint-disable-line declaration-no-important */
}
Always declare pseudo-elements with double colon notation. The double colon replaced the single-colon notation for pseudo-elements in CSS3.
Also, for pseudo-classes the specs says one single colon.
Bad example
.element:before {
content: 'This is bad';
&:hover {
//
}
}
Good example
.element::before {
content: 'This is good';
&:hover {
//
}
}
Rem vs pixels Because our design files is normally made in pixels it makes good sense for us to use pixels too. In that way we are talking the same “language”. But because pixels doesn’t scale are we using a small REM mixin. If you need to write 10px you should use rem(10) instead. Our rem function will then take the pixel value and divide it with 16px (our base font-size). That will return it in rem which is a proportional CSS unit. So, 10px = rem(10) = 0.625rem.
Values below one should never have a leading zero and if it’s a comma-seperated list, there should be a space after each comma.
Borders: You can use px for borders because it doesn’t make sense to scale a border. Also, px-based values are allowed for box-shadows too.
Bad example
.element {
width: 20px;
height: 80px;
animation-duration: 0.5s;
border: .975em solid black;
padding-top: 10px;
}
Good example
.element {
width: rem(20);
height: rem(80);
animation-duration: .5s;
border: 1px solid $color-black;
padding-top: rem(10)
}
The ampersand “&” is a nice Sass feature. But please use it for pseudo classes and for elements and modifiers only. If we use it elsewhere the code will become difficult to read.
Bad example
.time {
//
&__timestamp {
//
&-title {
//
&-date {
//
}
}
}
Good example
.time {
//
&__timestamp {
//
}
&__timestamp-title {
//
}
&__timestamp-title-date {
//
}
}