Roux & Sass Standards – Vocabulary – General



Roux & Sass Standards – Vocabulary – General

0 0


tech-talk-roux-sass


On Github elyseholladay / tech-talk-roux-sass

Roux & Sass Standards

Arrow left/right between sections

Arrow up/down inside sections

CSS Basics

CSS Vocabulary Cascade & Inheritance Specificity Using Inheritance Composition

Vocabulary

nimbupani.com/css-vocabulary.html

First, a little vocab lesson. It’s easier to talk about CSS when we know all the names of what we are discussing.

Selectors

What element(s) the styles should apply to; an element, class, ID, etc.

A selector is what you declare which elements
 the styles should apply to.

Elements h1, p, div

Classes .page-header


IDs #login


Attributes input[type=“text”]


Pseudo-classes :last-child


Pseudo-elements :after

Property The style that you are applying to a selector, e.g. color.

Value The value that the property can have,
 e.g. blue.

Therefore you have a property: value; pair,

Declaration The combination of a property: value; pair.

Rulesets A selector followed by some number of declarations:

.classname {
   color: blue;
   font-size: 18px;
}

Cascade & Inheritance

nicolasgallagher.com/css-cascade-specificity-inheritance

Let's talk a little bit about the cascade and inheritance. This is the part of CSS that really trips everybody up when it gets complex.

The cascade is a mechanism for determining which styles should be applied to a given element, based on the rules that have cascaded down from various sources.

The cascade takes importance, origin, specificity, and source order of style rules into account. It assigns a weight to each rule. When multiple rules apply to a given element, the rule with the greatest weight takes precedence. The result is an unambiguous way to determine the value of a given element/property combination.

http://nicolasgallagher.com/css-cascade-specificity-inheritance/

importance + origin + specificity + source order = cascade

See Nicholas Gallagher notes

Inheritance

header {
    color: red;
}

.header h1 {}

what color will the h1 be? (red)

Some properties, e.g. color, are automatically inherited by the children of the element to which they are applied.

Source Order

.header {
    color: red;
}

.header {
    color: blue;
}

.header h1 {}

what color will the h1 be? (blue)

Some properties, e.g. color, are automatically inherited by the children of the element to which they are applied.

.header {
    color: red;
}

.header {
    color: blue;
}

.header h1 {
    color: green;
}

what color will the h1 be? (green)

.header {
    color: red;
}

.header h1 {
    color: green;
}

.header {
    color: blue;
}

what color will the h1 be? (green) ... why? (specificity)

Specificity

Specificity is a method of conflict resolution within the cascade.

Specificity calculates whether or not a value will
apply (and override inheritance) based on the weight
of the selector.

inline styles are 1000

IDs are 100

classes are 10

elements are 1

specificity.keegan.st/

codepen.io/elyseholladay/pen/LpgHc

Using Inheritance

How would you expect to use inheritance to your advantage in a complex website? (expecting an answer about "all headers in the sidebar are blue")

“I want every h2 in the sidebar to look the same, and I don’t want to have to write CSS every time we create a new sidebar widget.”

h2 {
    color: #fd7900;
    font-size: 1.8em;
    line-height: 1.1;
    margin-bottom: .3em;
}
						

It all starts because someone says “I don’t want to have to write CSS every time I add an h2″. So we write:

.sidebar h2 {
    color: #8cc5e6;
    font-size: 2.2em;
    padding-bottom: .2em;
    border-bottom: 1px solid black;
}
                        

This works great at first, but then it happens: A story owner wants to change the look of all of the .sidebar h2.

We don’t need to change everything, just the color, size and border. So we take advantage of the CSS cascade and tweak the values that need to be updated.

.block
    border: 1px solid #8cc5e6;
    padding: 0 15px;
}

.block h2 {
    /* Color was changed by .sidebar h2, set it back */
    color: #fd7900;
    /* remove border added by .sidebar h2 */
    border: none;
    /* remove the margin set by h2 */
    margin: 0;
    padding: .3em;
    background: #8cc5e6;
}
                        

We are trying to be smart by breaking small pieces of functionality into reusable sidebar blocks, so we decide to create some default block styles. This way all of the blocks we create today, and in the future, can inherit the same styles. Each block has a h2, so let’s look at how that will be styled.

/* The Markup: 
...
*/ .alt-block h2 { /* Need to set color set by .block h2 */ color: #8cc5e6; /* Need to set the padding-bottom back to .sidebar h2 styles */ padding-bottom: .2em; /* Need to set the border back to .sidebar h2 styles */ border-bottom: 1px solid black; /* Set bottom margin again from root h2 */ margin: 0 0 .3em; /* remove background from .sidebar h2 */ background: none; }

Now we’ve been asked to create an alternate block style that uses the original sidebar header, but has full grey background.

our title is now inheriting styles from 4 different selectors, our code is bloated, our site’s performance is taking a hit, and our style system is incredibly fragile. Any change to h2 , .sidebar h2 , .block h2 will have an effect on .alt-block h2 whether we intended for it to or not

element inheritance

location inheritance

class inheritance

In the above example we experienced 3 different types of CSS inheritance: element inheritance, location inheritance, and class inheritance. Let’s take a look at how each one of them works, why they cause problems, and solutions to fixing them.

Element Inheritance

ties presentation to HTML elements and markup

We use HTML elements to add semantic meaning to our sites. When we apply styles to these elements we end up mixing semantics and presentation. I don’t mind applying a very basic set of default styles to our elements, but we ran into problems in our example when we tied our finished, presentational styles to the h2 element. This not only muddied up the water for all of our other h2 elements, but it also made those base styles impossible to reuse once overridden. Instead of relying on element inheritance to propagate our base style, we should move those styles into a reusable class or extend. You can even call it .h1 or %h1 if you want to! But the key is to avoid tying presentation to your base elements

Location Inheritance

means your styles are dependent on their location in the DOM and parents

Using location inheritance means that your header styles are dependent on being in the sidebar (not standalone or reusable), and that you’re required have intimate knowledge of your parent container before writing styles.

Someone is going to ask you to create a new header style for the sidebar and the last thing you want to have to do is try out all 6 of the header elements ( h1 – h6) to see which one has the least number of styles to override.

You will eventually be asked to move a component from the main content region over to the sidebar. How much do you want to bet that the .sidebar h2 styles won’t have ANY effect on the .widget h2 you are moving over.

You might think that using a decendant selector (like .sidebar > h2) will solve all of your problems, but now your styles are dependent on markup order, and there is no way to reuse those h2 styles elsewhere in your site.

Class Inheritance

creates relationships & dependencies where none should exist

Class inheritance is the practice of applying an entire system of styles on a collection of markup via a single class. In our example we have a .block class that is a complete component, then we add on another set of styles with .alt-block . this means that .alt-block “modifies or relies on the internal workings of another module”. This isn’t always a bad thing, but it is something that can quickly become complex and fragile.

My Calendar Title

...

Imagine that you wrote the .block code, and then someone else on the team decided to create .my-calendar-widget using .block as a set of base styles, i.e. a “relied upon module”.

what happens when we get a new story to change block to have a different background?

Unless you have a well established system for documenting these relationships, this becomes what I like to call “hijacked inheritance”. We have no indication in our CSS that .block has another component tightly coupled to it, so we’ll be dealing with random bugs on our calendar page every time we update .block.

.block
    border: 1px solid #8cc5e6;
    padding: 0 15px;
}

.block h2 {
    /* Color was changed by .sidebar h2, set it back */
    color: #fd7900;
    /* remove border added by .sidebar h2 */
    border: none;
    /* remove the margin set by h2 */
    margin: 0;
    padding: .3em;
    background: #8cc5e6;
}
                        

Even with single inheritance our .block element is still completely dependent on the cascade. Move a .block out of the sidebar and it will break. Change the header to H3 and it will break. The problem is that each element inside of .block inherits styles from the parent class, the block’s location and the HTML tag itself. No styles are prescribed to it due its semantic purpose, which is to be a “title”.

how do we do it better?

composition

is the idea that an html component might “contain” other styles, rather than “inheriting” those styles.

My Calendar Title

...

My Blog Title

...

My News Title

...

Note how each title has its own unique class. This allows us to target the title regardless of the element used.

%primary-header {
  font-size: 1.8em;
  line-height: 1.1;
  color: #fd7900;
  margin: .3em;
}

%secondary-header {
  font-size: 2.2em;
  line-height: 1.1;
  color: #8cc5e6;
  margin: 0 0 .3em;
  padding-bottom: .2em;
  border-bottom: 1px solid black;
}

%block-header {
  font-size: 2.2em;
  line-height: 1.1;
  color: #fd7900;
  margin: 0;
  padding: .3em;
  background: #8cc5e6;
  margin: 0 -15px;
}

%block {
  border: 1px solid #8cc5e6;
  padding: 0 15px;
}

%alt-block {
  padding: 15px;
  background: #eee;
}
                       
.calendar-widget {
  @extend %block;
}
.calendar-widget-title {
  @extend %block-header;
}

/*...*/

.latest-blogs {
  @extend %alt-block;
}
.latest-blogs-title {
  @extend %secondary-header;
}

/*...*/

.latest-news {
  @extend %alt-block;
}
.latest-news-title {
  @extend %secondary-header;
}

                        

Notice how each semantic selector is composed of styles rather than inheriting them from its tag, location or parent class. This allows us to “package up our code and reuse it in many different unrelated places and situations”.

The placeholder extends create a relationship between the style and the module name, but not between different modules.

Roux

CSS in Roux vs RMN New Pages Commenting

A single source of truth for the way ingredients look, their HTML and Sass/CSS code, and how to implement them;

Refactored Sass code to improve developer ergonomics, making it easier to find what you need than to write something similar from scratch;

An accessible view into the common ingredients available to build out an RMN page, how they work, the code, and how they can be extended or modified;

An ability for developers to quickly code new features without frustrating and untraceable CSS bugs;

Improved developer and designer ergonomics, so you can work on the stuff you are best at without worrying about the rest.

Our CSS should be 80% Roux, 20% RMN.

Roux is 80% of our CSS — globals and shared styles. making one-off unique CSS is _okay_! roux does not mean we dont have to ever write css again

Do I write it in Roux or RMN?

  • Is some or all of it unique to that page?
  • Could the code be reused in the future?
  • Or the design pattern?
  • Is it for a test?
  • Is it just plain hacky?

Making a New Page

1. Create templates/markup

2. Create example.scss manifest file in www/gui/libsass

3. Create partial templates in libsass/pages/example/

4. Import Roux and partials into example.scss

- roux // (symlink folder)
  example.scss
    // (imports roux, example/partial1, example/partial2)
  - pages
    - example
      partial1.scss
      partial2.scss
                

example.scss

  • comment header with name of page & what it is
  • import roux
  • import any partials
  • any extra CSS that doesn’t belong in a partial

show store

partial1.scss

  • comment header with name of module, what it does, where/what pages you’ll find it on
  • comment subheaders between sections
  • explanations/instructions for any mixins or variables
  • any TODOs or notes with name & date

show store subpages

show typography, favorite, mobile dropdown

Commenting Rules

Use /* */ comments for page headers only; they are visible in output Use non-output // comments for explanations, usage, edge cases, individual line comments, and TODOs. For TODOs, leave your handle and date:
// TODO eholladay 101415 comment goes here

Sass Standards

General Naming Conventions Spacing & Formatting Media Queries

anyone who says CSS is easy isn’t doing it right. Sass is a Turing-complete language and it deserves to be treated with the same amount of respect and care we treat other languages. perhaps even more, because it is responsible for what our users see, and very easy to break.

General

Keep functional Sass separate from presentational styles

Keeping functional Sass separate from presentational Sass is important in order to maintain readability, search-ability and scaleability of your code. Patterns like placing mixins in the same file as presentational Sass leads to overly complex files to scan and opportunities for accidental pollution of your processed CSS. http://gist.io/4436524

example: transitions/spinner

Write for composition, not inheritance.

This mainly means not to create relationships where none exist, like creating alt-block from block. Namespace your modules and make them standalone.

Extends/Placeholders, Mixins, & Maps

sassmeister.com/gist/a787869d74248f5d4ea2

Use extends to reuse code with no output, create a relationship

http://sassmeister.com/gist/18c47aadd302b8bd9566

button placeholders

use mixins to alter variables, give options

http://sassmeister.com/gist/elyseholladay/878b591ee969db0026b4 and http://sassmeister.com/gist/elyseholladay/1adb96cae0a363086916

square-image and spinner

use maps for exponential code with
 a relationship

https://stash.rmn.com/projects/UI/repos/roux-ingredients/browse/sass/_molecules/_coupon_anchor.scss

coupon anchors

Namespace (nest) modules one level to eliminate conflicts… but use minimal nesting to eliminate specificity hell.

.survey-module {
    .survey-module-header {}
}
                        

This is OK

.survey-module {
    .survey-module-header {
        .survey-module-header-close {
            .icon-close {}
        }
    }
}
                        

This is NOT OK

Always use classes over elements or IDs.

even when it means making more classnames!!

elements are bad b/c: location inheritance and tightly-coupled DOM;IDs are bad: unique, only for JS. use js- prefix classes for js functionality

// Incorrect
.survey-module {
    h2 {}
    .icon {}
}

// Correct
.survey-module {
    .survey-module-header {} // h2
    .icon-close {} // specific icon
}
                        

Check the existing codebase before adding
 a new var, mixin, or extend.

can you reuse something that is there? do you need to overwrite an existing function? if so, do you know where it will affect?

places to check: roux-ingredients, typography, colors, utils/helper folders (show these)

Variabilize numbers that have a relationship locally

$square-image-size: 25px;

.square-image {
    height: $square-image-size;
    width: $square-image-size;
}
                        

these have a relationship

$square-image-size: 25px;

.square-image {
    height: $square-image-size;
    width: $square-image-size;
    padding: 10px; // creates 10px of white border/empty space around the image
}
                        

padding doesn’t have a relationship. could we say $square-image-size*.4 ? yes. but why? not related. also.... we added a comment as to WHY

Add inline documentation. Always.

if your CSS is not obvious at first glance, PUT A COMMENT.

li.ds-dfp-banner-container {
    padding: 0;
    margin: -1px;

    .ds-dfp-banner {
        padding: 20px 0;
        margin: 0 -16px;
        text-align: center;
    }
}
                        

why the negative one margin? why the li? what is dfp?

// li required to add specificity to override some of the styling
li.ds-dfp-banner-container {
    padding: 0;
    margin: -1px;

    .ds-dfp-banner {
        padding: 20px 0;
        margin: 0 -16px;
        text-align: center;
    }
}
                        

ok... this is an improvement.. but what styling? what is dfp?

// Double Click for Publishers (DFP) banner ads
// ---------------------------------------------------------------------- //

// li required to add specificity over .coupon-horizontal
li.ds-dfp-banner-container {
    // when banner ad child is hidden (DFP doesn't serve ad), li needs to seem hidden
    padding: 0;
    margin: -1px; // hide double border from .coupon-horizontal top borders

    .ds-dfp-banner {
        padding: 20px 0;
        margin: 0 -16px; // align with sides when screen is small
        text-align: center;
    }
}

                        

muuuuch better

Naming Conventions

Choose human readable names over acronyms

.btn-lg-s {} // ???
                        

button… large? login? logo? save? submit?

.button-login-submit {}
                        

much easier. computers don’t really care if things are long/short/acronyms/etc. we do.

if you have to use an acronym, like our DFP doubleclick for publishers example (because that would be annoyingly long), PUT A COMMENT!

Shared or global name, then specific name

.blue-button      …   .button-blue
.red-button       …   .button-red
.submit-button    …   .button-submit

                        

easier to scan visually, easier to remember

Use dashes, not underscores or camelcase.

We don't specifically use BEM, although I see some people doing it, which is fine, we use a BEM-like syntax. But don't camelcase. Please.

// Incorrect
.buttonPrimary

// Trying to deprecate (BEM)
.button--primary

// Correct
.button-primary
.button-submit-offer
                        

Never use display/functionality in names

.orange-box {}
.form-float-left {}

                        

why is this bad?

.orange-box {
   background: green;
}

.form-float-left {
   float: right;
}

                        

lulz

Be descriptive.

Yes, naming is hard. You can always ask me for help. But try to explain what is in the element you are naming.

.csat-survey
.csat-survey-content
  .csat-survey-header
  .csat-survey-question-wrapper
  .csat-survey-questions
  .csat-survey-question
    .csat-question-prompt
    .button-csat-response
                        

what's better... this...

.csat-survey
.surveyContent
  .header-survey
  .surveywrapper
  div
  .question-survey-item
    p
    .button
                        

or this?

Spacing & Formatting

Use four-space tabs with an editor config.

Put spaces after the colon in property declarations.

// Correct
display: block;

// Incorrect
display:block;

                        

Put spaces before brackets in declarations.

// Correct
.class {}

// Incorrect
.class{}

                        

Place closing braces of declaration blocks on a new line.

// Correct
.class {
    styles: go-here;
}

// Incorrect
.class {
    styles: go-here; }

                        

Put one property per line.

// Correct
.class {
    display: block;
    color: red;
}

// Incorrect
.class {
    display: block; color: red;
}
                        

When grouping selectors, keep individual
selectors to a single line.

// Correct
.class,
.box {
    styles: go-here;
}

// Incorrect
.class, .box {
    styles: go-here;
}

                        

Avoid specifying units for zero values and
using zeros before decimals.

// Correct
.class {
    margin: 0;
    font-size: .5em;
}

// Incorrect
.class {
    margin: 0px;
    font-size: 0.5em;
}

                        

why do we do this?

Use non-outputting // for comments

One line between rulesets; two lines between sections

.coupon-anchor {
    ...
    text-align: center;

    // size and color of SVG icons inside the coupon anchor amount div
    .icon {
        width: 30px;
        height: 45px;
        fill: $white;
    }
}


// COUPON ANCHOR COLOR MAP ---------------------------------------------- //
// ---------------------------------------------------------------------- //

                        

Media Queries

Write media queries inside rulesets.

Media queries go first before all other CSS in a block.

Write responsive code small to large (mobile first)

.page-callout-content {
  @include media(grid-med) {
    float: left;
    width: 75%;
    padding-left: 1em;
  }

  padding-top: 0.75em;
  padding-right: 2em;
}
                        

inside, FIRST before other CSS; small to large (anything else

@include media(grid-med) {
  .page-callout-content {
    float: left;
    width: 75%;
    padding-left: 1em;
  }
}

.page-callout-content {
  padding-top: 0.75em;
  padding-right: 2em;
}
                        

NOT separately. inside the selector is easier to parse, and you avoid writing the selector twice

Roux & Sass Standards