0.0.1 • Published 8 years ago

navgati v0.0.1

Weekly downloads
-
License
ISC
Repository
-
Last release
8 years ago

Navgati

The CSS and JavaScript files in this repository form the backbone of 'Navgati'– the codename given to the new-look 8.x version of our back-office application.

Getting Started

Requirements

  • A Mac running OS X 10.11 El Capitan or higher. Yeah, yeah, Linux blah Windows grumble, get over it.
  • A text editor which supports EditorConfig, such as Coda, Sublime Text, Atom.
  • CodeKit (which is why you need a Mac).
  • A Git client: GitHub Desktop is good enough, but if you want to use something else, feel free. Go wild and rock the command line if you like.

Listen, it's not strictly necessary to go the Mac route. If you have (a) a neck beard, and (b) too much time on your hands, you can recreate all of this setup with Grunt, or Gulp, or whatever trendy task-runner is currently flavor of the week at your Debian meet up.

  • We compile our SCSS files Compressed, with no debug info and 10-digit decimal precision, with a source map generated. After completion, we run Autoprefixer and Bless on the output files.
  • Plugins are managed using Bower. Have fun with that.
  • JavaScript is run through JSHint with the following flags on:
    • bitwise
    • curly
    • freeze
    • newcap
    • noarg
    • none
    • regex
    • undef
    • unused
    • notypeof
    • browser
    • level
    • jQuery
  • JSHint settings will change as we produce production-ready code.
  • JavaScript is output Minified + source map using Uglify.js

Source File Structure

  • Bower components are installed in /src/bower_components
  • JavaScript is in /src/js
  • SCSS files reside in /src/scss

Output file structure

  • Bower does not output any files
  • JavaScript outputs to /javascript/navgati
    • myFile.js will become myFile.min.js
  • CSS outputs to /skins/version/AAcss, where version is the version number, e.g. /skins/8.0.0/AAcss
    • myfile.scss becomes myfile.css
  • There is an /images folder for images

SCSS Structure

We are using Inverted Triangle CSS (ITCSS) to structure our SCSS code. The scss folder is flat, and does not use the recommended structure from The Sass Way because trying to remember if a file is a module, a partial, etc. is a pain. Instead, we use the format <section>.<file>.scss, which provides us a quick overview of every file, easily sorted, with no need to make tough decisions like 'Do I need to create a new folder?' because the answer is 'no'.

This structure and naming convention was created by Harry Roberts, and we use some parts of his inuitcss framework for Navgati. Because of this, we follow the inuitcss implementation of the ITCSS naming convention:

  • Settings: Global variables, site-wide settings, config switches, etc.
  • Tools: Site-wide mixins and functions.
  • Generic: Low-specificity, far-reaching rulesets (e.g. resets).
  • Base: Unclassed HTML elements (e.g. a {}, blockquote {}, address {}).
  • Objects: Objects, abstractions, and design patterns (e.g. .media {}).
  • Components: Discrete, complete chunks of UI (e.g. .carousel {}).
  • Trumps: High-specificity, very explicit selectors. Overrides and helper classes (e.g. .hidden {}).

We mix and match layers as necessary. At the time of writing, navgati.scss looks like this:

#!scss

/****
    * Settings
    * Global variables, site-wide settings, config switches, etc.
    */

@import "../bower_components/inuit-defaults/settings.defaults";
@import "settings.defaults";
@import "settings.colors";
@import "settings.responsive"; 

/****
    * Tools
    * Site-wide mixins and functions.
    */

@import "../bower_components/inuit-functions/tools.functions";
@import "tools.functions";
@import "../bower_components/inuit-mixins/tools.mixins";
@import "tools.mixins";

/****
    * Generic
    * Low-specificity, far-reaching rulesets (e.g. resets
    */

@import "../bower_components/inuit-normalize/generic.normalize";
@import "../bower_components/inuit-box-sizing/generic.box-sizing";

/****
    * Base / elements
    * Unclassed HTML elements (e.g. a {}, blockquote {}, address {}).
    */

@import "../bower_components/inuit-page/base.page";
@import "base.page";

/****
    * Objects
    * Objects, abstractions, and design patterns (e.g. .media {}).
    */

@import "../bower_components/inuit-list-inline/objects.list-inline";

/****
    * Components
    * Discrete, complete chunks of UI (e.g. .carousel {}). 
    */

@import "components.navgati";
@import "components.nav-bar";
@import "components.context-bar";
@import "components.header-bar"; 
@import "components.breadcrumbs"; 
@import "components.aboutWindow"; 

/****
    * Trumps
    * High-specificity, very explicit selectors. Overrides and helper classes (e.g. .hidden {}).
    */

@import "trumps.grid";

Most of our work is in the creation of Components. All files which do not output CSS are prefixed with an underscore, so "components.navgati" is actually a file named _components.navgati.scss.

ITCSS is structured so that the topmost files are the most wide-ranging (for example, defining body {} tag or a {}), and specificity increases as we progress downwards, until we hit the most specific items of all, at the Trumps level.

It is fine to create variables, etc. and to add mixins or functions in the Settings and Tools levels. On the other hand it is highly unlikely you will need to create new Objects (check the inuitcss repository– they likely have the Object you are looking for). You really need to question what you are doing and why, should you find yourself working at the Generic level. That's a red flag. You should avoid Trumps where possible, but this is the real world, and sometimes it has to be done. Better to separate out the trumps than write consulted code elsewhere.

SCSS Writing Guidelines

  • Maintainability is key. Keep code readable and use longhand CSS so it's always clear what's going on.
  • Keep specificity as low as possible. Use class names whenever you can.
  • Write CSS that takes advantage of SCSS functions, but be sure you understand what the output CSS will look like.
  • Use BEM-like notation (see below).
  • If you are working on a component and it becomes bulky, separate it into multiple components. If you have two components that are so tightly entwined they have to stay in the same file, you are probably doing it wrong.
  • If you hit 300 lines of SCSS, it's time to refactor.
  • Classes are for styling, ID's are for targeting with JavaScript. Don't mix these up.
  • Avoid nesting.
    • Avoid Nesting.
      • No seriously, avoid nesting.
      • Nesting is bad.
        • Nesting is really
          • Really
            • Bad.

BEM (Block, Element, Modifier)

  • Class names are lower case, with dashes to separate words, e.g. .my-awesome-class {}
  • This is much more readable than camelCase.
  • We don't use underscores because they are used in BEM syntax.

BEM syntax looks like this:

#!scss

.block {}
.block__element {}
.block--modifier {}

.block__element--modifier {}
  • A .block {} is a complete abstraction or component.
  • A .block__element {} is a descendant of a .block {}, which is an integral part of the whole
  • A .modifier {} is an alternate state of a .block {} or .block__element {}.

For example:

#!scss

.link {}               /* block */
.link--selected {}     /* modifier */

.navigation-list {}                           /* block */
.navigation-list__list-item {}                /* element */
.navigation-list__list-item--highlighted {}   /* modifier */

Writing CSS this way makes it easier to understand how elements relate to one another, regardless of how the HTML is structured.

A couple of gotchas:

  • No grandchildren allowed. You should never have .nav-menu__nav-item__link {}, as this is too specific. .nav-menu {}, .nav-menu__nav-item {} and .nav-menu__link {} are more appropriate.
  • Not everything needs to be an element of a block. If .link {} will be used in multiple places, define .link {} rather than .nav-menu__link {}.
  • Equally, don't BEM items just because they are inside another HTML element.

To be continued...

0.0.1

8 years ago