#Starting Point
We've all been there. You're coding something when an inner voice suddenly announces, "This should be its own thing. Don't forget to pull this code out and make it its own thing." But you're busy and you don't do it.
Six months later, you're working on a new project and can't find that useful utility you once wrote. So you write it again. And again. Can we please stop recreating our greatest hits ad infinitum?
When beginning a web project, I need these things:
- A small, vanila
JavaScript
library using the module pattern - Auto minification/concatenation/
JavaScript
linting - Reusable sass mixins and placeholders
- A no-bullshit
SVG
workflow JavaScript
unit testing with Jasmine- An easy way to catch accessibility issues before going live
##Browser Support## IE9+, Chrome, Firefox, Opera, Safari, iOS Safari, and Android 4+.
##What's In Here?
###Typographical Vertical Rhythm###
Establishing a typographical vertical rhythm at the outset of a web project makes your content much easier to read and understand. Compass
makes this pretty easy to set up and you can read more about vertical rhythm here.
###Responsive Videos and Images###
I like having a padded main content area with 100% wide images that extend beyond the padding to the viewport edges.
<main>
<!-- A paragraph within the padded walls -->
<p>Some text here. Some text here. Some text here. Some text here. Some text here. Some text here. Some text here. Some text here. Some text here. </p>
<!-- This image will hug the viewport walls -->
<div class="img-container">
<img src="assets/sample.jpg" alt="">
</div>
<!-- Other stuff -->
</main>
###JavaScript Utilities###
Have you ever wanted something to happen after your CSS
transition or animation ended? Yes, you can fire that second transition or animation with a delay containing the same value as the first even duration—but that's a risky venture. This is where you would use animationend
and transitionend
, both stored in utilities.js
.
whichTransitionEvent /* returns correct vendor prefix for desired event */
You might use it like this:
var transitionend = utilities.whichTransitionEvent();
if (transitionend) { // browser supports transitionend
container.addEventListener(transitionend, handler, false);
}
Sometimes you want to know when a user is on a touch-supported device.
isTouchDevice
A useful place for this would be to determine the type of event listener to attach to an element.
var click_touch = utilities.isTouchDevice() ? "touchstart" : "click",
toggle_menu = document.querySelector("#toggle-menu");
toggle_menu.addEventListener(click_touch, handler, false);
###Useful Mixins###
@mixin animation($animate...)
@mixin keyframes($animationName)
@mixin remove-tap-highlight
@mixin input-placeholder
@mixin box-size-all
@mixin mobile-smooth-scroll
@mixin respond-to($breakpoint)
@mixin form($custom_args: "")
@mixin form-label($font-size: 0.75rem)
@mixin transitions-off
###Modular CSS Approach###
This just means all the CSS
is broken down into partials (footer, animations, common, forms, etc.). These partials tend to make your code much easier to manage as your project grows. Footer changes go in the footer partial; new animations go in the animations partial. CSS
turns out okay if you are consistent and practical.
##Grunt Tasks## Starting Point uses Grunt to handle some common, yet tedious, tasks.
###SVG Management###
svgstore is a lifesaver when it comes to managing SVG
icons you wish to include in a sprite sheet. All you have to do is start grunt watch from the command line and drag an SVG
icon into the svg directory. svgstore will build the SVG
into a sprite sheet which you can reference in an external file. Say we add an icon to the SVG
folder with the filename of ribbon.svg
.
Immediately, Grunt builds the file into our SVG
sprite sheet, making it available within our HTML
.
<a href="http://somelink.com">
<span class="hide-text">Click the ribbon</span>
<svg class="icon" aria-hidden="true">
<use xlink:href="dist/dist.svg#shape-ribbon" />
</svg>
</a>
You can then adjust the CSS
styles for your SVG
. It's dead simple.
###Linting###
All JavaScript
in Starting Point is strict and should stay that way. While Grunt is watching, it will yell at you if you break the linter rules in some way. Missing a semi-colon? Sorry—fix it. Declared a variable at the bottom of a function? Sorry—fix it. I like having the linter around to keep my code from getting ugly.
###Minification###
Ruby
users are likely familiar with config.rb
, a file which is created for us by Compass
. There, we can set a value for the variable output_style
, which determines what happens each time we save a watched sass
file. I always set this variable to :compressed
to make my CSS
file size as light as possible.
But what of our JavaScript
? That should certainly be minified, too. With a few Grunt tasks, concat
and uglify
, this is no longer a problem—well, almost. If we instruct concat
to join all files with a .js extension before uglify
does the actual minification, we could have an dependency ordering problem. We need the code in utilities.js
to load first, so that the its functions are available to any other code loaded after. This is why we organize our concat
task in the following way:
Gruntfile.js
concat: {
options: {
separator: ';'
},
dist: {
src: [['js/vendor/*.js'], 'js/utilities.js', 'js/main.js', 'js/demo.js'],
dest: 'dist/<%= pkg.name %>.js'
}
}
###Automatic Prefixing###
For a long time I have used Compass
to handle all my prefixing needs. If you are a Compass
user, you have probably written something like this before:
@include opacity(0.8);
@include transform(translateY(0.1em) scaleX(1.1) scaleY(.9));
And, of course, this is fine, and we can trust Compass
to reliably deliver us CSS
. Using autoprefixer
, though, we can get right to the CSS
and skip the middleman.
opacity: 0.8;
transform: translateY(0.1em), scaleX(1.1), scaleY(.9);
The resulting CSS
will be the same, with the necessary prefixes included for us.
##Installation##
$ git clone https://github.com/antibland/starting_point.git
$ npm install
This is an optional step. However, if you unit test your JavaScript
(or want to start), definitely proceed with this step.
$ bower install jquery jasmine-jquery --save-dev
After these files are downloaded, you'll need to include them in your Gruntfile.js
jasmine: {
src: 'dist/starting-point.js',
options: {
vendor: [
'bower_components/jquery/dist/jquery.js',
'bower_components/jasmine-jquery/lib/jasmine-jquery.js'
],
specs: 'spec/**/*.js'
}
}
You'll then be able to run tests headlessly with the following command:
$ grunt jasmine
If you're running the tests in the demo, you should see something like this:
$ grunt watch
$ compass watch
After you have the necessary modules, you'll need to run Starting Point on a server. It will work serving a local HTML
index file, but accessing the SVGs in an external file cause Chrome to throw security permission errors and serve no icons. From a Mac, the easiest way to work around this is to start a simple web server:
$ python -m SimpleHTTPServer 8000
Then just go to http://localhost:8000
and you should be in business.
##Contributing##
This is a barebones thing I've cobbled together in my spare time and is by no means complete. If you have any ideas to make Starting Point better, I'd love to work with you.
##Notes##
You're cloning the entire demo, which is probably more than you need. If you look in the sass folder, you can remove the files beginning with _custom for a cleaner start and the call to demo.init()
at the bottom of index.html
.
##License##