Agent 5 CSS Refactor
Overview
- Current State
- Why Refactor
- OOCSS
- Practical Application
- Results
Current State
- 4 Files
- bootstrap.css
- styles.css (our stuff)
- kendo.css
- print.css (print-specific styles)
- Size of styles.css - 208kB
- # Rules - 1898
- # Selectors - 2903
Why Refactor?
Codebase was a mess
@import "form_add-cc.less";
@import "form_create-case.less";
@import "form_create-contact.less";
@import "form_modal_create-contact.less";
@import "form_create-solution.less";
@import "form_edit-case.less";
@import "form_edit-contact.less";
@import "form_edit-employee.less";
@import "form_edit-site.less";
@import "form_edit-solution.less";
.cc-listing .alert {
padding: 4px 35px 4px 14px;
}
.add-cc-form .contact-picker .contact-input-control {
margin-left: 0px;
}
form_add-cc.less
form_create-case.less
div.contact-input-control {
padding-bottom: 12px;
.pick-contact {
width: 100%;
margin-bottom: 0;
}
}
div.site-input-control {
padding-bottom: 25px;
.pick-site {
margin-bottom: -10px;
}
}
.content-row{
margin-bottom: @baseLineHeight;
padding-top: @baseLineHeight;
position: relative;
}
solution-description.less
.nav-header {
// 28 lines
&:hover {
.badge{
background-color: @grayDarker;
color: @grayLight;
//right: 14px;
}
}
.badge{
.badge-gray();
background-color: darken(@grayLight, 5%);
top:6px;
}
&.active{
// 8 lines
.badge{
background-color: @blue;
color: @grayLight;
}
}
// 12 lines
.nav-header {
a.due-soon-navbadge{
// 13 lines
.badge{
background: @grayDarker;
top: 18px;
color: @grayLight;
}
&:hover{
background-color: @blue;
color: @white;
.badge{background-color: @white; color: @blue;}
text-shadow: none;
i{text-shadow: none;}
}
}
}
// At bottom
.badge{
.badge-gray();
background-color: darken(@grayLight, 5%);
text-indent: 0;
}
.toolbar-wrapper{
line-height: 10px;
color: @grayDark;
background-color: @white;
float: right;
margin-left: 15px;
margin-bottom: 15px;
margin-top:-25px;
margin-right: -25px;
//...
}
mixins.less
.account-and-addresses{
//...
.toolbar-wrapper {
margin-top: -15px;
margin-right: -15px;
}
}
containers.less
.history {
.toolbar-wrapper{
margin-top: 0;
z-index: 1;
}
}
tab_history.less
.toolbar-wrapper{
margin-top: -10px;
margin-right: -15px;
float: right;
position: relative;
.cases-linked-badge {
float: left;
margin-right: 5px;
margin-left: 0;
margin-bottom: @baseLineHeight;
}
.icon-toolset-menu {
float: right;
margin: 0 5px;
}
}
tools-menus.less
- We used to have bootstrap and our styles build into one stylesheet. Why split them?
- IE9 is smart
Summary
- Code organization was terrible (hard to find rules you wanted to)
- Rules were all over the place (hard to find which rule you cared about in your specific situation)
- Specificity wars galore
Let's Try Something Different
(You guys are gonna hate the name)
Object Oriented CSS
OOCSS History
- Created by Nicole Sullivan in 2009
- Claim to fame was helping Facebook go on a stylesheet diet (19% less css, 44% less html, 50% gain in loading performance)
- Challenges css "best-practices"
- Use specificity
- Create modules
OOCSS Goals
- Code reuse
- Easy dev introduction
- Robust
OOCSS Principles
- Separate Structure & Skin
- Separate Content & Container
Structure vs Skin
.notification-info {
border: 1px solid black;
height: 200px;
width: 400px;
background: blue;
color: black;
}
.popup-red {
border: 1px solid black;
height: 200px;
width: 400px;
background: red;
color: white;
}
.box-narrow {
border: 1px solid black;
height: 200px;
width: 200px;
&.red {
background: red;
color: white;
}
.blue {
background: blue;
color: black;
}
}
.box {
border: 1px solid black
height: 200px;
}
.box-wide {
width: 400px;
}
.box-narrow {
width: 200px;
}
.box-red { // Bad naming
background: red;
color: white;
}
.box-info {
background: blue;
color: black;
}
<div class="box box-wide box-red"></div>
<div class="box box-narrow box-info"></div>
Content vs Container
A Heading should not be a Heading on another part of the page
h1 { ... }
#module1 h1 { ... }
#module2 h1 { ... }
/* It's impossible to have a normal h1 in #moduleX now */
.nav-header {
// 28 lines
&:hover {
.badge{
background-color: @grayDarker;
color: @grayLight;
//right: 14px;
}
}
.badge{
.badge-gray();
background-color: darken(@grayLight, 5%);
top:6px;
}
&.active{
// 8 lines
.badge{
background-color: @blue;
color: @grayLight;
}
}
// 12 lines
.nav-header {
a.due-soon-navbadge{
// 13 lines
.badge{
background: @grayDarker;
top: 18px;
color: @grayLight;
}
&:hover{
background-color: @blue;
color: @white;
.badge{background-color: @white; color: @blue;}
text-shadow: none;
i{text-shadow: none;}
}
}
}
// At bottom
.badge{
.badge-gray();
background-color: darken(@grayLight, 5%);
text-indent: 0;
}
Practical Application
- Identify common elements
- Think in terms of structure and skin, not in modules
- Don't be afraid to have many classes on an element
.a5-card {
.border-box;
display: block;
height: 190px;
max-height: 190px;
max-width: 33%;
min-height: 190px;
min-width: 32%;
}
.a5-card-small:extend(.a5-card) {
height: 120px;
max-height: 120px;
min-height: 120px;
}
.a5-card-med:extend(.a5-card) {
height: 150px;
max-height: 150px;
min-height: 150px;
}
.a5-card-full-width:extend(a5-card) {
min-height: 20px;
min-width: 95%;
}
Naming is Hard
.box {...}
.box-blue { background: blue; }
.box-red { background: red; }
.box {...}
.box-info {...}
.box-error {...}
.box {...}
.box-blue { background: teal; }
.box-red { background: orange; }
Enabling Customization
// Agent 5 Variables
// ------------------------------
// Colors
@grayLightest: #f9f9f7;
@grayBorder: #c3c3c3;
@greenDarkest: #368959;
@greenLight: #74cf9b;
@greenLightest: #b1f4ce;
// Variables
// ------------------------------
@a5-card-bg: @white;
@a5-card-border-color: @grayLight;
@a5-card-wrapper-bg: @grayLighter;
// Structure
// ------------------------------
.a5-card-default {
.border-radius(4px);
background: @a5-card-bg;
border: 1px solid @a5-card-border-color;
}
variables.less
a5-cards.less
@a5-card-bg: gray;
@grayLightest: #c9c9c9;
custom.less
Results
Red Flags
- Overwriting rules through specificity
- Re-declaring attributes often (float, margin, color, border, etc.)
- Using "!important"
- Getting deeper than 3 levels
Wrap-up
- Old way
- Code base gets bloated, unorganized over time
- Have to be an expert in css just to add simple styles
- Specificity Wars
- New way
- Easy developer ramp-up
- Easy customization
- More reuse
- Smaller code base
- Avoid specificity wars
- Possible HTML bloat
- More classes to know
Resources
- Me
- https://fronteers.nl/congres/2009/sessions/object-oriented-css
Any Questions?
Agent5 CSS
By Craig Jennings
Agent5 CSS
- 81