SharePoint Information Site > Technical Guides > Object-Oriented CSS

Object-Oriented CSS

Object-oriented CSS is a coding paradigm that styles "objects" or "modules" (nest-able chunks of HTML) that define a section of a web page with robust, reusable classes. The paradigm employed by front-end frameworks like Twitter Bootstrap has greatly informed how we think of front-end development at DePaul. We strive to honor best practices in efficiency and organization in order to make our CSS framework as maintainable and usable as possible.

Here are some rules we try to follow:
  • Write rulesets in specificity order  - The CSS reset, basic HTML elements, Objects (nav abstraction, media object), Components (objects abstractions, site-main-nav, user-actions-menu), Style trumps (.error classes that need to override always), skins. On the topic of skins,  we've done skins in occurrence order which is sometimes not recommended, but it works for us. So the skin selectors are ordered according to visual appearance (e.g. header, page, footer).
  • Separate structure and skin - See how we did the call to action buttons in responsive.css? We separated the structural, or always-the-same, properties into one class and for the skin we made a color class that is added to the element so that the structure and skin are independent, and it's easier to apply in alternate contexts. In other words, skin classes have visual properties and zero structural properties.
  • Separate container and content - We've created a grid system to layout content. Content is styled separately and never contextually to a container. So no ".gridUnit10 p {...}" This decoupling allows content centric elements such as paragraph to exist without needing a specific kind of container to format properly.
  • No ID's: ID's are absolute and better used for scripting for our needs. Classes can (and should) be used in a flexible manner in that your class should be able to be applied to different elements without a sensitivity to context. For example, the "warning" classes we devised can be dropped onto any element. This is incredibly flexible.
  • Extensions - Think in terms of having a basic structure first such as your grid unit stuff, or the structure for a special object like calls to action. This contains the basic dna of these objects. To give each object a unique personality or skin, an extension class is created (or re-used) that puts color, background, anything non structural that skins the object. That's an extension as far as we define things here at DePaul with regard to CSS.
  • "#Foo h3" - This kind of context selection is bad for the most part. We used context selection for the skins of sites, but this was done for ease of implementing skins. For the creation of interfaces, unique panels, tabbed things, objects, etc we should always think about how we can separate things out into a structural object and a skin that makes it look nice.
  • "#Foo h3 {color: blue;}" - This example  forces you to write more css for the same style when you want something to be blue again. Think about how this might be reused and how an extension class such as ".blue-text" could be used.
  • "#Foo h3, #Fie h3, #Fum h3" - This is unpredictable and brittle code in most cases. Why not make a single class that can be attached to headings, or more broadly for that matter?
  • Style objects without elements, i.e. the ".error" class. This way if there's an error, you just apply that class to the element, and it can be used anywhere. When you have an exception to this rule say your paragraph element needs to do something slightly different, then you can do p.error 
  • Float - Float is declared in the grid system as .unit and .unitRight. While there could be exceptions, this is a prime example of using a couple basic classes for maximum reuse.
  • In general, avoid specifying location. We avoided doing context, location based stuff like .nav-primary UL so the .nav-primary class could be leveraged in other places if ever necessary. This will probably never happen, but it's easier to do this early in a site's development history than to do it after you've built dozens of site.
  • Avoid qualifying selectors p.intro > .intro this increases specificity, extra selectors, limits reuse (can't be used on any other element) it's less efficient and more work for the browser rendering engine.
  • Avoid unnecessary nesting like .carousel .panel because this increases specificity, limits portability and is less efficient.
  • Avoid chaining selectors like .msg.error > .error-msg, same problems as above, limits portability/less efficient.
  • If you feel you need to note where best a class should be applied, use quasi-qualified selectors! /* UL */ .product-page or /* table */ .winners This way you tell others how it should be used while preserving portability.
  • If rulesets being added are undoing previous rulesets then you should either rethink your approach to adding new work or consider rewriting previous rulesets to be more flexible.
None of these should be seen as too dogmatic; you may have a great reason for contextual selection as we did in the creation of easily deployable skins for sites. The spirit of these guidelines are to help us think about how to organize and how to make our work friendly to those in the future who will use it.