A framework for front (frob) enders (tenders) everywhere
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Frob Core

Build Status Code Climate

Because you're not hardcore.

P.S. The inline code documentation in this pup is rock solid.


  1. Copy source/javascripts/frob_core_helpers.js and source/javascripts/frob_core.js to your project.
  2. Apply the structure of source/javascripts/application.js to your project.
  3. Start Frob Core (usually in application.js): ;(function() { window.FCH = new FrobCoreHelpers(FC); })();

Initialization and Options

The core holder must be passed in as the first argument for initialization, i.e. new FrobCoreHelpers(FC), but all other options are, fittingly, optional. These are passed in via object as the second argument, i.e. new FrobCoreHelpers(FC, { ... }).

Option Type Default Description
mobile_fps boolean true Attach the scroll listener for u-disable-hover
breakpoints function null To set custom breakpoint, pass a function with two args and return a string: boolean object (example below)
preserve_breakpoints boolean true Merge custom breakpoints with default breakpoints. If false, value of breakpoints removes all default breakpoints
window.FCH = new FrobCoreHelpers({}, {
  breakpoints: function(ww) {
    return {
      boot_size: ww < 12
  preserve_breakpoints: false

// FCH.bp => { boot_size: <true|false> }


Direct descendants of the core holder can access hooks using reserved property names. These are called automagically, avoiding declaring multiple event listeners on the document or window.

FC.ui = {
  ready: {
    if(FCH.exists('.js-slider')) {

  mySuperSliderInitialization: function() {

For example, use the resize function to change the width of .mydiv to match the window's width.

FC._ui = {
  resize: function() {

Hooks can also be added by adding a function to the appropriate FCH array.

var sticky = function($el) {
  $el.css('position', 'fixed');
Hook Called on
scroll window scroll
resize window resize
ready DOMContentLoaded
load window onload

Special Note: Using this in a hook function will refer to the parent namespace, not FrobCoreHelper.

FC._ui = {
  boo: function() {

  resize: function() {
// a scary alert is triggered every time the window is resized

Debounced Events

Sometimes, a callback function on rapid-firing window events can be resource-intensive. Thanks to pioneering efforts from John Hann, Paul Irish, and Underscore.js, these events can be tricked to fire only once or twice instead of continuously.

Wrap your function in FCH.debounce when adding it to a hook.

FC.nav_listeners = {
  ready: function() {
    FCH.resize.push( FCH.debounce( this.resourceConsumingFunction.bind(this) ) );

  resourceConsumingFunction: function() {

  destroy: function() { ... }
Param Description
func Callback function
threshold Milliseconds to check between fires (defaults to 250)


These defaults are available from FCH.bp. Returns boolean. They can be appended, overwritten, or removed entirely when declaring options.

Accessor Description
small window width less than or equal to 767
small_up window width greater than or equal to 768
medium_portrait window width between 768 and 960
medium window width between 768 and 1024
large_down window width less than 1024
large window width greater than 1024
if(FCH.bp.small) {


Available from FCH.dimensions

Accessor Description
ww window width
wh window height

Cached jQuery Objects

Only available if jQuery is included.

Accessor Description
FCH.$body equivalent to $('body')
FCH.$window equivalent to $(window)

Default Values

Add default values for missing values in functions, similar to Ruby's variable ||= value

function(required_value, missing_value) {
  missing_value = FCH.setDefault(missing_value, 10);


addClass adds a class to an element with vanilla JS.

Param Description
element JS Object
class String of class to be added
var el = document.createElement('div');
FCH.addClass(el, 'foo'); // el.className is now "foo"


removeClass removes a class to an element with vanilla JS if the element already has that class.

Param Description
element JS Object
class String of class to be removed
var el = document.createElement('div');
el.className = 'foo';
FCH.removeClass(el, 'foo'); // el.className is now ""


toggleClass adds a class to an element with vanilla JS if the element does not already have the class, removes the class if it does.

Param Description
element JS Object
class String of class to be toggled
var el = document.createElement('div');
FCH.toggleClass(el, 'foo'); // el.className is now "foo"
FCH.toggleClass(el, 'foo'); // el.className is now ""


loop saves characters on for loops.

Param Description
selector Array, NodeList or DOM selector
callback requires one argument - the current looped item in callback
var titles = '';
FCH.loop('.posts', function(post) {
  titles += post.querySelector('h2').textContent;

Local Storage

Read, Update, and Destroy localStorage objects.

Function Description
FCH.localGet(key) retrieve value (returns false if key is not defined)
FCH.localSet(key, value) create or update key
FCH.localClear({optional} key) if key is provided, destroy just that key; otherwise destroy all keys


Check to see if an element exists on the page

// <div class="henry"></div>

FCH.exists('.henry') // => true


Test for IE versions. Returns boolean. Only use in the most trying of times. Agent strings are unreliable.

Accessor Description
FCH.IE10 true if browser is IE10
FCH.IE9 true if browser is IE9
FCH.anyIE true if browser is Internet Explorer


  1. Copy source/stylesheets to your project (usually replacing app/assets/stylesheets)


Variable Description
$em-base font-size (must be in pixels) used for emCalc and remCalc.
$f-sans font stack for sans-serif fonts
$f-serif font stack for serif fonts
$f-script font stack for script fonts
$f-monospace font stack for monospaced fonts
$f-international font fallback stack for multilingual fonts
$c-white vanilla palette for #fff
$c-black vanilla palette for #000

Font-stack variables are designed to be applied after custom font names.

$f-opensans: 'Open Sans', $f-sans;
$f-content: $f-opensans;



Quick shortcut for &:hover { ... }. Accepts color value or block.

@include hover($c-white)

@include hover {
  background: $c-white;


Make z-indexing easy. Create an ordered list of your classes and call it inside your class.

$lightbox: (

.lightbox {
  &-bg {
    @include stack($lightbox); // z-index: 1
  &-content {
    @include stack($lightbox); // z-index: 2

If you want to name your ordered list different from your classes, pass a key as the second argument.

.lightbox {
  &-bg {
    @include stack($lightbox, 'lightbox-content'); // z-index: 2
  &-content {
    @include stack($lightbox, 'lightbox-bg'); // z-index: 1


Param Accepts Default
$name string required
$breakpoint_list map $breakpoints
$additional_breakpoints arglist null

Put a block of content within a media breakpoint using the $breakpoints list defined in _variables.scss.

.show--mobile {
  display: none;
  @include bp(small) {
    display: block;

To use a custom set of breakpoints, pass the list in the second argument (default is $breakpoints).

$tweakpoints: (
  'really-specific-nav-size': ( min-width: 438px )
@include bp(really-specific-nav-size, $tweakpoints) { ... }

Multiple breakpoints can be combined with an arglist starting at the third argument. Note that proper order should be obeyed and will not be automatically corrected (i.e. including print or screen as the third argument).

.narrow-print {
  // Prints `@media only print and (min-width: 421px) and (max-width: 767px)`
  @include bp(print, $breakpoints, small, medium-down) { ... }


Apply a CSS triangle to an element.

Param Accepts Default
$direction top, bottom, left, right top
$color hex $c-black
$size px 30px
$shadow boolean false
.nav-dropdown {
  @include triangle(bottom, $c-white);


Pass a block to apply properties to input placeholder styles. Strongly recommended to be used only at root-level. Accepts block.

@include placeholder {
  color: $c-gray;
  text-shadow: 1px 1px 0 $c-black;


Target specific Internet Explorer versions, and optionally pass in a version number. Only use this mixin as a last resort. Feature detection is strongly preferred. Accepts block.

.animated-element {
  @include ie { ... } // .ie .animated-element
  @include ie(9) { ... } // .ie9 .animated-element


Target touch devices using Modernizr. Accepts block.

.nav {
  @include touch { ... } // .touch .nav


Use a Nicolas Gallagher clearfix. A .clearfix class is available in _utilities.scss

.cf {
  @include clearfix;


Vertically align an object without vertical-align.

.center-between {
  @include vertical-center;



Convert px to em. Relies on $em-base in _fine_variables.scss, but this can be overwritten in your own _variables.scss

body {
  font-size: emCalc(16px);


Convert px to rem. Relies on $em-base in _fine_variables.scss, but this can be overwritten in your own _variables.scss

body {
  font-size: remCalc(16px);


Find pair of value or key in map. If value/key cannot be found, returns false

$descriptions: (
  'big' : 'blue',
  'wet' : 'wide'

.whats-the-sea-like {
  &:before {
    background: match($descriptions, 'big'); // 'blue'
    content: match($descriptions, 'wet'); // 'wide'


Invert a number.

.upside-down {
  top: negate(10px);


Use a gray color from the $grays map.

$grays: (
  30: #777

a {
  color: gray(30); // #777

File Structure and Naming Conventions


Child files should have declarations in the following order:

  1. Scoped variables
  2. FCH hooks
  3. Public functions
  4. Protected functions


FC.ui = {
  logo_height: 100,

  ready: function() {

  load: function() {

  resize: function() {

  setLogoHeight: function() {
    var logo = this._getLogo();
    this.logo_height = logo.innerHeight;

  _getLogo: function() {
    return document.querySelector('.logo');

Functions should be lowerCamelCase; variables should be lower_underscore. All functions must include a short description and should be documented using JSDoc standards.

 * Update value of scoped `logo_height` var
 * @fires _getLogo
setLogoHeight: function() { ... },

 * Find the logo element
 * @protected
 * @return {Node}
_getLogo: function() { ... }


Install all dependencies:

npm install --save-dev