Stylus and General CSS Guidelines - tsgrp/HPI GitHub Wiki
Please reference the following for general CSS best practices. This is Github's official styleguide and has some good points / do's / don'ts:
https://github.com/styleguide/css
HPI employs the use of Stylus which is a CSS preprocessor (like SASS or LESS). It allows us to simplify CSS syntax, reduce file sizes, and includes functions and variables to make our stylesheets more dynamic... all while outputting plain ol' CSS in the end.
Stylus can be installed with node and works well with grunt, making it a good preprocessor candidate for HPI. Done properly, we can easily control the color scheme and other look and feel items for our clients.
There is no point in re-documenting the Stylus docs -- they'll provide most of the helpful shortcuts and conventions that make up the syntax, but we'll go over some of the more common cases in HPI here.
One of the most common CSS mistakes made by our developers is scoping. This is very important in HPI where ALL of our stylesheets are compiled into one large CSS file. If I've created a new module that has a standard <a>
element, and I want to correctly add a style to it, I should make sure the CSS declaration I create is only targeting the elements I know I want to change in that module. So the wrong way to scope it would be to add this CSS in my stylesheet:
a:link { font-weight: bold; }
The correct way in order to avoid all the other links in the app from inheriting my new style is to use something like the following:
.search-container a:link { font-weight: bold; }
Of course, this might not be new to you. But what about when things get complex? When you have a large amount of nesting in markup and you want to avoid running into CSS where you have a huge amount of nested selectors and multiple declarations on different lines? Enter Stylus & Nesting:
The following markup will be used as a sample for much of our documentation, so keep that in mind for future examples. If you're curious, this is from listview.html in the search module. It displays the list view for search results and is made up of a set of rows for each result, each containing a thumbnail and a configurable set of metadata. I've removed some of the elements and knockout bindings for clarity:
<div class="content list-view">
<div class="list-item">
<div class="list-item-overlay">
<input type="checkbox" />
</div>
<a><img class="list-item-thumb"></a>
<div class="metadata">
<div class="row">
<div class="span5">
<a><h4 data-bind="text: result.metadata().title"></h4></a>
<ul class="props" data-bind="foreach : { data: result.metadata().attrs, as: 'attr'}">
<li>
<b data-bind="text: attr.name"/><b>:</b>
<span data-bind="text: attr.value"/>
</li>
</ul>
</div>
<div class="span2">
<div class="btn-group" data-bind="visible: actions().length > 0">
<button class="btn btn-mini dropdown-toggle" data-toggle="dropdown" data-bind="click: actionTime">Actions<span class="caret"></span></button>
<ul class="dropdown-menu" data-bind="foreach: actions">
<li>
<a data-bind="text: label, click: $parent.executeAction" ></a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
To be continued...