A fun place to compare overwatch stats between friends
Once you have installed the above dependencies:
cd
into the root of the new project folder and runnpm install
from the command line
From the root of the project, several commands can be issued from terminal:
gulp
: Runs the default Gulp task. This builds the project with source maps from theapp
folder into thebuild
folder, spawns a Node server, opens a new browser with the website at http://localhost:3000, and listens for subsequent changes. When you edit and save a new file, Gulp will recompile accordingly and refresh your browser window with the latest changes automatically.gulp dev
: Runs the above Gulp task without spawning a server.gulp build
: Builds project from theapp
folder into thebuild
, uglifies the JS, and minifies the CSS. This should generally be run prior to committing/pushing your code to the repo.gulp dist
: Runs the above task and spawns a localhost server. This is useful if you want to proof the production build before pushing it to a remote server.
app/
: All work should be done in theapp
folder. This is where your website's source code lives.build/
: When running Gulp, files fromapp
are compiled intobuild
. If you work out of thebuild
folder, your work will be overwritten and you will be sad. Don't work out of thebuild
folder.gulp/
: This contains all of the Gulp tasks that the project relies on. There is also aconfig.js
file that most of the tasks reference to make file paths and preferences more manageable.node_modules/
: The folder where node modules are installed when you runnpm install
..jshintrc
: The configuration file that dictates syntactical rules for JS linting. These should be followed closely..jsbeautifyrc
: The configuration file that can be used with Sublime Text's HTML-CSS-JS Prettify and Atom's atom-beautify plugins. Allows you to format your HTML, CSS, JavaScript, and JSON code. These plugins look for a.jsbeautifyrc
file in the same directory as the source file you're prettifying (or any directory above if it doesn't exist, or in your home folder if everything else fails) and uses those options along the default ones..scss-lint.yml
: The configuration file for "linting" Sass/SCSS files. Not currently enforced during build-time, but can be used with Sublime Text's SublimeLinter plugin along with SublimeLinter-contrib-scss-lint, or Atom's atom-lint and linter-scss-lint (among others).gulpfile.js
: This references all of the tasks ingulp/tasks/
. Tasks are broken apart for organizational purposes and referenced from this root file when you rungulp
.package.json
: Contains the project's Node dependencies. Modules specified in this files are installed intonode_modules
when you runnpm install
.README.md
: You're reading it.
To encourage organization, scalability, and code-reuse, we generally take an Atomic Design approach when structuring our HTML and Sass. Our Sass partials and HTML includes are broken apart in folders denoted by Atomic-style building blocks (atoms/pieces, molecules/components, organisms/regions, etc.).
Init utilizes twig.js for creating templates and reusable components. Twig provides the ability to:
- Write a piece of code once and reuse it in multiple places.
- Use conditional code to allow for variation in the template or component.
- Use json data to populate content of each template, which allows the use of the same component partial within one or multiple templates with different content for each instance.
Your HTML lives in the app
folder, and can contain references to reusable includes (which live in app/includes/
). For example:
{% include 'includes/3_components/media--person-card.twig' %}
Each main template in the app
folder also requires a json
file that includes any data utilized in the template. These data files live in the app/json
folder and must use the same name as the template file.
When Gulp runs, it takes the includes and data, and compiles the full HTML into the build
folder.
Note: The paths in which these includes are referenced are relative to the HTML file you are authoring. If you include an include from another include, that path will need to be prefixed with ../
accordingly.
Want to know how to get the most out of twig? Check out the documentation.
Note: Init uses twig.js which is an implementation of the Twig PHP templating language, so some features in the documentation may not be available. Check the implementation support for twig.js to verify feature support.
When developing we should be aware of how our sites preform for users with accessibility needs. Our sites should be level AA compliant, refer to Accessibility Checklist and Some best practices for accessibility for more information on level AA. We recommend using these tools to help check the accessibility of sites:
- Cythina Says allows users to test individual pages on their website and provides feedback in a reporting format that is clear and easy to understand.
- Wave Chrome Extension is a google extension that provides visual feedback about the accessibility of your web content by injecting icons and indicators into your page.
- Contrast Checker is a great tool to test the contrast of text to background within your website
- ChromeVox screenreader is an extension that is a screenreader allowing you to understand how your site will perform. Please refer to How to use ChromeVox for more information on how to use ChromeVox.
WAI-ARIA, the Accessible Rich Internet Applications Suite, defines a way to make Web content and Web applications more accessible to people with accessibility needs. For background on ARIA and extensive examples on how and where to use them, refer to the ARIA in HTML page. For practical examples of working with ARIA can be found here and information on browser support for the ARIA tags can be found here.
The following ARIA tags are the baseline accessibility tags we recommend using while writing your HTML. Each will have a markup example on its use.
role="navigation":
A collection of navigational elements (usually links) for navigating the document or related documents.
<nav role="navigation">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Landing Page</a></li>
<li><a href="#">Inner Page</a></li>
</ul>
</nav>
Note: the <nav>
element is a HTML 5 element that is not supported in all browsers, so putting the role="navigation
makes this backwards compatible
role="menu":
A type of widget that offers a list of choices to the user.role="menuitem":
An option in a group of choices contained by a menu.
<ul role="menu">
<li><a href="#" role="menuitem">Sub Menu</a></li>
<li><a href="#" role="menuitem">Sub Menu</a></li>
<li><a href="#" role="menuitem">Sub Menu</a></li>
</ul>
aria-haspopup="true":
Indicates that the element has a popup context menu or sub-level menu.aria-expanded="false:
Indicates that the element is expanded or closed.
<a aria-haspopup="true">Menu Item</a>
<ul class="sub-menu" aria-expanded="false">
<li><a>Sub Menu Item</a></li>
<li><a>Sub Menu Item</a></li>
<li><a>Sub Menu Item</a></li>
</ul>
Note: aria-expanded="false"
should be changed to true
when javascript shows the .sub-menu
Note: this aria tag should only be used for a hidden menu
Note: the role="menu"
and role="menuitem"
have been omitted from this example for clarity purposes
role="main":
The main content of a document.
<div role="main">
<h1>Page title</h1>
<p>Page description</p>
...
</div>
role="tab":
A grouping label providing a mechanism for selecting the tab content that is to be rendered to the user.role="tablist":
A list of tab elements, which are references to tabpanel elements.role="tabpanel":
A container for the resources associated with a tab, where each tab is contained in a tablist.aria-selected="true":
Sets or retrieves the selection state of this element.
<div>
<ul role="tablist">
<a role="tab" aria-selected="true">Click here to change tabs</a>
</ul>
<div role="tabpanel">
<p>This is the tab content that will show when the tab is clicked</p>
</div>
</div>
Note: aria-selected="true":
should be changed to false
when the javascript fires (the new active tab should get the new `true)
role="button":
An input that allows for user-triggered actions when clicked or pressed.
<a role="button">This Link is a Button</a>
hidden
helper class
Init launches with a hidden
helper class that will help hide the content of a linked icon (for example an arrow that moves a carousel). To makes this element accessible you will need to add text within the element. To prevent this from breaking the layout we can add the class hidden
to remove the text from the DOM visually while still allowing a screenreader to access it. The following is an example of use:
<a class="hidden icon-arrow-l">View the next slide</a>
The text "View the next slide" will be moved off screen visually but the markup will be semantically correct.
Your styles live in the app/styles/sass
folder. This folder is organized atomically:
screen.scss
: This contains globbing patterns that@include
tools and partials contained in the following folders0_utility/
: This contains font, helper, mixin, and variable declarations.1_core/
: All bare (classless) HTML is styled in thehtml-elements
folder. Icons are specified in the_icons.scss
partial and the site's grid system is specified in the_layout.scss
partial.2_pieces/
: This is where your "Atoms" live.3_components/
: This is where your "Molecules" live.4_regions/
: This is where your "Organisms" live.5_pages/
: This is where your "Layouts" live.
Init comes with a customized version of Susy grid that gives more control with responsive layouts. The Susy default object can be found in app/styles/1_core/_grid.scss
and default grid can be viewed by going to the 'Grid Structure' page on your localhost. The default Susy settings Init uses are:
$susy: (
columns: 12,
global-box-sizing: border-box,
gutters:$spacing-unit/12rem
);
_Note: Uncomment the debug{}
to apply the columns
Note: Refer to Susy Settings for information on Init's default settings
Init's grid on compile will provide a couple of helpful grid classes by default:
span-#
: This is the standard Susy classes. For examplespan-4
.span-#.center
: Thespan-#
will automatically have acenter
modifier class associated with them. For examplespan-4.center
.push-#
: This is the standard Susy Push modifier. The number value will be the amount of columns the element is pushed to the right. For examplepush-4
.pull-#
: This is the standard Susy Pull modifier. The number value will be the amount of columns the element is pushed to the left. For examplepull-4
.span-#of#
: This is another version of class syntax that the grid by default will support. For examplespan-1of2
.span-#of#.center
: Thespan-#of#
will automatically have acenter
modifier class associated with them. For examplespan-1of2.center
.
These classes and behavior are largely relatively default Susy. Init's grid system has been updated to be more robust for responsive development.
By default, Init's grid will compile with responsive modifiers that will alter the grid by targeting certain breakpoint. The breakpoints are defined at the top of the _grid.scss
file in the $breakpoint-has-widths
list. Init's default breakpoints options are ('mobile', 'tablet', 'desktop')
. Upon sass compile these list values will be used to create the grid "@" modifiers. For example, to change a column's width to span 4 columns on desktop and higher we just need to add the class span-4@desktop
.
Note: We develop mobile first, so all the breakpoints will reflect outward from mobile
Init's grid on compile will provide a couple of helpful grid classes by default:
span-#@BREAKPOINT
: This is the standard Susy classes. For examplespan-4
on sizes larger than the BREAKPOINT.span-#@BREAKPOINT.center
: Thespan-#
will automatically have acenter
modifier class associated with them. For examplespan-4.center
on sizes larger than the BREAKPOINT.push-#@BREAKPOINT
: This is the standard Susy Push modifier. The number value will be the amount of columns the element is pushed to the right. For examplepush-4
on sizes larger than the BREAKPOINT.pull-#@BREAKPOINT
: This is the standard Susy Pull modifier. The number value will be the amount of columns the element is pushed to the left. For examplepull-4
on sizes larger than the BREAKPOINT.span-#of#@BREAKPOINT
: This is another version of class syntax that the grid by default will support. For examplespan-1of2
on sizes larger than the BREAKPOINT.span-#of#@BREAKPOINT.center
: Thespan-#of#
will automatically have acenter
modifier class associated with them. For examplespan-1of2.center
on sizes larger than the BREAKPOINT.
Note: In the _grid.scss
there is a $suffix
variable that will disable the responsive modifiers on compile. By default it is set to true
that will include it in the compiled code, to remove this feature update this value to false
(or '')
Note: There is a .remove-center
class that can be added to markup or extended in CSS to overwrite the .center
To prevent render blocking, Init leverages Font Face Observer. Init comes with a font set of Roboto to demonstrate how fonts are set up using this pattern. In short, the script in app/includes/1_core/head.html
listens for the font requests coming from app/styles/sass/0_utility/_fonts.scss
. Using a promise, it will add a class of fonts-loaded
to the body once the fonts have downloaded. This class is leveraged in app/styles/sass/1_core/html-elements/_base.scss
to update the page with the custom webfonts. If you want to change or add fonts, follow these steps:
- In
app/styles/sass/0_utility/_fonts.scss
, change or add a new font making sure to include the appropriate weight. Then update your font variable(s) accordingly. - In
app/includes/1_core/head.html
, create a new variable for each weight and update the weight property with the same weight you specified in step 1.
Init comes with a generic font set of icons that includes common things like arrows and social chiclets. To add or edit the icon font, upload app/fonts/icomoon/selection.json
to the Icomoon web-app. From here, you can add and remove icons, then re-export. When you re-export, make sure you save the updated selection.json
.
Init comes with a JS module loading system. This is how the JS folder is structured:
libs/
: This is where your vendor libraries and plugins live. Alternatively, you can use Bower if you really prefer.modules/
: This is where your JS modules live.modules/index.js
: This is the "module registry". It is essentially an object that contains a key/value for each module in the project.app.js
: This is your application bootstrap. All JS kicks off from here.
You can quickly generate a new module right from the command line. Run gulp create-module --name=moduleName
, where moduleName is the name of your new module. Be sure to keep it camelCase. Running this command will generate a new module folder as well as add a require reference to the module registry file. If you use this CLI method instead of manually creating modules, you shouldn't ever have to touch the module registry file.
You can also pass an async flag to the command. For example gulp create-module --name=moduleName --async
. This will tell Webpack to bundle this file separately from the rest of the application and will asynchronously load this module in only when the module is referenced on the page.
When you generate a new module, it will have two files; the .load file and the .main file. You don't need to touch the .main file. This simply tells Webpack how to require the module in the build (depending on whether you specified it to be asynchronous or not).
The .main file is where you write your code. It exports an ES6 class:
'use strict';
var $ = require('jquery');
module.exports = class SampleModule{
constructor($el){
this.$el = $el;
this.method(this.$el);
}
method($element){
console.log($element);
}
};
If you're unfamiliar with the ES6 class syntax, you can read more about it here.
Then reference the new module from somewhere in the HTML with the data-module
attribute:
<section class="outer-wrapper" data-module="sampleModule">
<div class="inner-wrapper">
<h1>My Module</h1>
</div>
</section>
That's it! Now, when the page loads, app/scripts/app.js
kicks off the module registry, which loops through all of the data-module
attributes on the page and instantiates a new
version of that module via the reference in the module registry.
Note: The module loader passes a jQuery object of the element that contains data-module
. This allows for easy scoping if you need to load more than one instance of the module on a page.
Init comes with a reveal utility that allows for the highlighting of components on a particular page. To highlight a component simply pass in a search query at the end of the url ?r=[COMPONENT SELECTOR]
. For example to hightlight all the .example-cards components, simply pass in this query in the url, ?r=.example-card
. This query value can be any valid jQuery selector.
Some plugins might not be available via NPM. Rather than use another package manager, we can leverage Napa. Add the repo URL to the napa
object in the package.json
folder and reference it just like an NPM package.
If for whatever reason, there is no repository for the library you want to include, you can download it manually to app/scripts/libs
, include via the browser
object in package.json
, and reference it just like an NPM module.
Init leverages JS and Sass sourcemapping for easy debugging. The sourcemaps are automatically built — all you need to do is configure your browser to use them.
- Run
gulp
to get your server running. - In Chrome Inspector, go into settings and make sure sourcemaps are enabled for both JS and CSS.
- Open the "Sources" tab in the inspector, and in the side pane on the left, right-click and select "Add Folder to Workspace". Select the root folder of the project, from your file system.
- At the top of the browser, Chrome will prompt you for access. Click the "Allow" button.
- In the left side pane of the Sources tab, you should now see your project folder. Expand it and and drill down to any one of your Sass partials. Click it once. In the middle pane, an alert should come up asking if you want to map the workspace resource. Click the "more" link to expand the dialog, then click "Establish the mapping now...".
- A list of files should come up. Select the one that matches the file you just clicked on (generally the first one).
- Inspector will want to restart.
- That's it! Your local files should be tied to the sourcemaps the site loads. Now, when you inspect an element, look at the CSS pane and it should have a link to the exact partial for each rule declaration.
Make sure you've installed ALL dependencies specified above. Also, make sure you have up-to-date versions of Node.
The watch
task only picks up on changes made to files that existed when the task was started. When you edit a Gulp task, a config file, a twig json
file, or add any new file to the app
folder, you must stop and restart Gulp.