by Guyllaume Doyer / @gudoy
I like things:
...basic syntax checking as well as applying a set of rules to the code that look for problematic patterns or signs of inefficiency...
CSS is a visual language.
No "magic" tool can tell if your code is appropriate or not.
Most of the the rules are
Chances are very high you’ll do yourself more harm than good, ending up with harder to maintain, bloated codeMatt Willcox
Page contextualisation:
/* Login page specific */
#login form {}
#login label {}
#login input {}
/* and so on */
.foo { }
#foo { } /* Faster than above */
#bar.foo { }
.foo#bar { } /* Faster than above */
#bar.foo { }
.foo#bar { } /* Faster than above */
/* Using classnames: for generic rules */
.productsList .title { color:blue; }
aside .productsList { color:grey; }
/* Using IDs: tells us it's really a specific case */
#profilePage #someProductsList .title { color:green; }
good for prototyping, but...
With 1 markup + css (media queries) + a bit of js:
<!-- BAD: do not do this -->
<a id="foo" href="#" onclick="alert('Yo!')">click me<a>
// Better: put this in a .js file
var el = document.getElementById('foo');
el.addEventListener('click', function(){ alert('Yo!') }, false)
<!-- BAD: do not do this -->
<a id="foo" href="#" style="color:blue; font-size:32px; text-align:right;">click me<a>
/* Better: put this in a .css file */
#foo { color:blue; font-size:12px; text-align:right; }
<!-- BAD: Markup still contains styling information -->
<a class="color1 right inline big" id="foo" href="#">click me<a>
<!-- BAD: markup tied to particular representation (desktop) -->
<div class="foobar grid16">
<div class="foo grid10">foo<div>
<div class="bar grid6">bar<div>
<div>
what's in bootstrap-responsive.css:
.container,
.navbar-static-top .container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 724px;
}
.span12 {
width: 724px;
}
.span11 {
width: 662px;
}
.span10 {
width: 600px;
}
.span9 {
width: 538px;
}
.span8 {
width: 476px;
}
.span7 {
width: 414px;
}
.span6 {
width: 352px;
}
.span5 {
width: 290px;
}
.span4 {
width: 228px;
}
.span3 {
width: 166px;
}
.span2 {
width: 104px;
}
.span1 {
width: 42px;
}
.offset12 {
margin-left: 764px;
}
.offset11 {
margin-left: 702px;
}
.offset10 {
margin-left: 640px;
}
.offset9 {
margin-left: 578px;
}
.offset8 {
margin-left: 516px;
}
.offset7 {
margin-left: 454px;
}
.offset6 {
margin-left: 392px;
}
.offset5 {
margin-left: 330px;
}
.offset4 {
margin-left: 268px;
}
.offset3 {
margin-left: 206px;
}
.offset2 {
margin-left: 144px;
}
.offset1 {
margin-left: 82px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
line-height: 0;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 30px;
margin-left: 2.7624309392265194%;
*margin-left: 2.709239449864817%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .controls-row [class*="span"] + [class*="span"] {
margin-left: 2.7624309392265194%;
}
.row-fluid .span12 {
width: 100%;
*width: 99.94680851063829%;
}
.row-fluid .span11 {
width: 91.43646408839778%;
*width: 91.38327259903608%;
}
.row-fluid .span10 {
width: 82.87292817679558%;
*width: 82.81973668743387%;
}
.row-fluid .span9 {
width: 74.30939226519337%;
*width: 74.25620077583166%;
}
.row-fluid .span8 {
width: 65.74585635359117%;
*width: 65.69266486422946%;
}
.row-fluid .span7 {
width: 57.18232044198895%;
*width: 57.12912895262725%;
}
.row-fluid .span6 {
width: 48.61878453038674%;
*width: 48.56559304102504%;
}
.row-fluid .span5 {
width: 40.05524861878453%;
*width: 40.00205712942283%;
}
.row-fluid .span4 {
width: 31.491712707182323%;
*width: 31.43852121782062%;
}
.row-fluid .span3 {
width: 22.92817679558011%;
*width: 22.87498530621841%;
}
.row-fluid .span2 {
width: 14.3646408839779%;
*width: 14.311449394616199%;
}
.row-fluid .span1 {
width: 5.801104972375691%;
*width: 5.747913483013988%;
}
.row-fluid .offset12 {
margin-left: 105.52486187845304%;
*margin-left: 105.41847889972962%;
}
.row-fluid .offset12:first-child {
margin-left: 102.76243093922652%;
*margin-left: 102.6560479605031%;
}
.row-fluid .offset11 {
margin-left: 96.96132596685082%;
*margin-left: 96.8549429881274%;
}
.row-fluid .offset11:first-child {
margin-left: 94.1988950276243%;
*margin-left: 94.09251204890089%;
}
.row-fluid .offset10 {
margin-left: 88.39779005524862%;
*margin-left: 88.2914070765252%;
}
.row-fluid .offset10:first-child {
margin-left: 85.6353591160221%;
*margin-left: 85.52897613729868%;
}
.row-fluid .offset9 {
margin-left: 79.8342541436464%;
*margin-left: 79.72787116492299%;
}
.row-fluid .offset9:first-child {
margin-left: 77.07182320441989%;
*margin-left: 76.96544022569647%;
}
.row-fluid .offset8 {
margin-left: 71.2707182320442%;
*margin-left: 71.16433525332079%;
}
.row-fluid .offset8:first-child {
margin-left: 68.50828729281768%;
*margin-left: 68.40190431409427%;
}
.row-fluid .offset7 {
margin-left: 62.70718232044199%;
*margin-left: 62.600799341718584%;
}
.row-fluid .offset7:first-child {
margin-left: 59.94475138121547%;
*margin-left: 59.838368402492065%;
}
.row-fluid .offset6 {
margin-left: 54.14364640883978%;
*margin-left: 54.037263430116376%;
}
.row-fluid .offset6:first-child {
margin-left: 51.38121546961326%;
*margin-left: 51.27483249088986%;
}
.row-fluid .offset5 {
margin-left: 45.58011049723757%;
*margin-left: 45.47372751851417%;
}
.row-fluid .offset5:first-child {
margin-left: 42.81767955801105%;
*margin-left: 42.71129657928765%;
}
.row-fluid .offset4 {
margin-left: 37.01657458563536%;
*margin-left: 36.91019160691196%;
}
.row-fluid .offset4:first-child {
margin-left: 34.25414364640884%;
*margin-left: 34.14776066768544%;
}
.row-fluid .offset3 {
margin-left: 28.45303867403315%;
*margin-left: 28.346655695309746%;
}
.row-fluid .offset3:first-child {
margin-left: 25.69060773480663%;
*margin-left: 25.584224756083227%;
}
.row-fluid .offset2 {
margin-left: 19.88950276243094%;
*margin-left: 19.783119783707537%;
}
.row-fluid .offset2:first-child {
margin-left: 17.12707182320442%;
*margin-left: 17.02068884448102%;
}
.row-fluid .offset1 {
margin-left: 11.32596685082873%;
*margin-left: 11.219583872105325%;
}
.row-fluid .offset1:first-child {
margin-left: 8.56353591160221%;
*margin-left: 8.457152932878806%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
.controls-row [class*="span"] + [class*="span"] {
margin-left: 20px;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 710px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 648px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 586px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 524px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 462px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 400px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 338px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 276px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 214px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 152px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 90px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 28px;
}
Basically, a CSS “object” is a repeating visual pattern, which can be abstracted into an independent snippet of HTML, CSS, and possibly JavaScript. Once created, an object can then be reused throughout a site.
No magic tool/method,
learn CSS!
... but here are some usefull tips
#mainNav {}
#products {}
#products .product {}
.accounts {}
.blogPost .comments {}
#loginForm {}
section#demo {}
table.sampleData {}
...
one is everywhere:
When 1 thing is cut in 3 zones: intro, content, conclusion
very important for small screen design
<div class="foo">
<header class="header fooHeader" id="fooHeader">...</header>
<div class="content fooContent" id="fooContent">...</div>
<footer class="actions fooActions" id="fooActions">...</footer>
</div>
* { -webkit-box-sizing:border-box; -moz-box-sizing:border-box; box-sizing:border-box; }
(and use letter-spacing:-4px fix if needed)
app.css (default)
/* no media query, everything fluid, avoid fixed sizes */
320up.css
@media screen and (min-width:320px)
{
}
480up.css
@media screen and (min-width:480px)
{
}
and so on (640, 800, 960, 1280, ...)
.someElement,
#another,
.and > #another.one,
#oneMore + .with.anotherSelector,
.foo > .action,
.bar header
{
background:#f2f2f2;
background:-webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#c9c9c9));
background:-webkit-linear-gradient(#f2f2f2, #c9c9c9 100%);
background: -moz-linear-gradient(#f2f2f2, #c9c9c9 100%);
background: -ms-linear-gradient(#f2f2f2, #c9c9c9 100%);
background: -o-linear-gradient(#f2f2f2, #c9c9c9 100%);
background: linear-gradient(#f2f2f2, #c9c9c9 100%);
}
// This is bad: you are selecting the element 3 times
$('#elemId').addClass('someClass');
$('#elemId').attr('some attribute', 'some value');
$('#elemId').on('click', function(){ /* ... */ })
// Using caching
var $el = $('#elemId');
$el.addClass('someClass');
$el.attr('some attribute', 'some value');
$el.on('click', function(){ /* ... */ })
// and/or using chaining
var $el = $('#elemId');
$el
.addClass('someClass');
.attr('some attribute', 'some value');
.on('click', function(){ /* ... */ })
<ul id="myList">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
</ul>
// Instead of binding 5 events:
$('li', '#myList').on('click', function(){ });
// Bind only 1 on the parent
$('#myList').on('click', 'li' function(){ });
// Or event better: onto the document
$(document).on('click', '#myList li', function(){ });
// Bad: will get all .level1 elements (using getElementsByClassname),
// test if is a LI
// and go up through the DOM looking for a NAV
$('nav li.level1')
// Better: will use getElementsByTagName to find NAV
// test if contains LI
// and test for classname
$('nav').find('li').filter('.level1')
// Even better: will use getELementById on a hook
// look this DOM chunk for LI
// and test for classname
$('#mainNav').find('li').filter('.level1')