Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CSMess to OOCSS: Refactoring CSS with Object Oriented Design

CSMess to OOCSS: Refactoring CSS with Object Oriented Design

Ask any web developer: the most neglected part of their site/app is likely its CSS. Unlike other parts of the stack, most CSS is messy, complex, and long overdue for a rewrite. But it doesn’t have to be. Break out of these bad patterns by applying an object oriented CSS framework (OOCSS).

This talk will step through the process of designing, building, and implementing a custom OOCSS framework for a mid-sized web application, outlining the basic methodology, best practices, and expected outcomes, which include significant gains in both front-end performance as well as developer productivity.

Written transcript:
http://blog.kate-travers.com/how-oo-design-saved-our-css-and-site-performance/

Kate Travers

October 17, 2016
Tweet

More Decks by Kate Travers

Other Decks in Programming

Transcript

  1. └── assets └── stylesheets ├── admissions │ ├── index.scss │

    └── show.scss ├── lessons │ ├── index.scss │ └── show.scss ├── shared │ ├── _fonts.scss │ ├── _vars.scss │ ├── _mixins.scss │ ├── footer.scss │ ├── header.scss │ └── nav.scss ├── application.scss ├── admissions.scss ├── lessons.scss ├── shared.scss etc...
  2. #lesson-show { position: fixed; width: auto; top: 10px; left: 80px;

    z-index: 10; .title { margin-top: 0; vertical-align: middle; } .btn-row { line-height: 1; padding-left: 15px; background-color: $light-gray; margin-bottom: 4px; margin-left: 8px; } /* etc... */ } └── assets └── stylesheets ├── admissions │ ├── index.scss │ └── show.scss ├── lessons │ ├── index.scss │ └── show.scss ├── shared │ ├── _fonts.scss │ ├── _vars.scss │ ├── _mixins.scss │ ├── footer.scss │ ├── header.scss │ └── nav.scss ├── application.scss ├── admissions.scss ├── lessons.scss ├── shared.scss etc...
  3. └── assets └── stylesheets ├── admissions │ ├── index.scss │

    └── show.scss ├── lessons │ ├── index.scss │ └── show.scss ├── shared │ ├── _fonts.scss │ ├── _vars.scss │ ├── _mixins.scss │ ├── footer.scss │ ├── header.scss │ └── nav.scss ├── application.scss ├── admissions.scss ├── lessons.scss ├── shared.scss etc... LEARN_V1 NATIVE 213 stylesheets 1.3 MB VENDOR 116 stylesheets 848 KB TOTAL 329 stylesheets 2.1 MB
  4. MODULAR Coupled to single view Too brittle / specific to

    re-use ENCAPSULATED Specificity wars MAINTAINABLE
  5. MODULAR Coupled to single view Too brittle / specific to

    re-use ENCAPSULATED Specificity wars Unpredictable behavior MAINTAINABLE
  6. MODULAR Coupled to single view Too brittle / specific to

    re-use ENCAPSULATED Specificity wars Unpredictable behavior MAINTAINABLE
  7. MODULAR Coupled to single view Too brittle / specific to

    re-use ENCAPSULATED Specificity wars Unpredictable behavior MAINTAINABLE Writing new CSS for every view
  8. MODULAR Coupled to single view Too brittle / specific to

    re-use ENCAPSULATED Specificity wars Unpredictable behavior MAINTAINABLE Writing new CSS for every view Difficult to onboard new team members
  9. 1. Take visual inventory of app’s UI/UX 2. Build component

    OOCSS library 3. Rewrite CSS and markup ROADMAP
  10. 1. Take visual inventory of app’s UI/UX 2. Build component

    OOCSS library 3. Rewrite CSS and markup 4. Onboard your team ROADMAP
  11. .site-header .site-sidebar .site-main LAYOUT >> CONTAINER >> OBJECT COMPONENTS .site-subheader

    .site-banner .module .media-block .media-block .media-block .media-block .image .text-block .button
  12. .site-header .site-sidebar .site-main LAYOUT >> CONTAINER >> OBJECT >> GLOBAL

    COMPONENTS .site-subheader .site-banner .module .media-block .media-block .media-block .media-block .image .text-block .button.util--pull-right
  13. Compartmentalized Limited/single responsibility Complexity through combination Portable Interchangeable from view

    to view Components don’t affect parent or relative styles MODULAR COMPONENTS
  14. /* Block component */ .list /* Child element of parent

    block */ .list__card /* Modifier that changes the style of the block */ .list--accordion .list--spacing-large
  15. └── assets └── stylesheets ├── layout │ ├── site-header.scss │

    ├── site-footer.scss │ └── site-main.scss ├── containers │ ├── list.scss │ ├── media-block.scss │ └── module.scss ├── objects │ ├── button.scss │ ├── image-frame.scss │ └── input.scss ├── global │ ├── special.scss │ ├── typography.scss │ └── vars.scss └── application.scss
  16. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; }
  17. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } .media-block .media-block__content .media-block__media
  18. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <!-- Start by outlining the basic container + objects --> <div class="media-block"> <div class="media-block__media"> <!-- circle with user’s profile picture --> </div> <div class="media-block__content"> <!-- text object: user name --> <!-- text object: time ago --> <!-- text object: action completed by user --> </div> </div>
  19. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <!-- Start by outlining the basic container + objects --> <div class="media-block"> <div class="media-block__media"> <!-- circle with user’s profile picture --> </div> <div class="media-block__content"> <!-- text object: user name --> <!-- text object: time ago --> <!-- text object: action completed by user --> </div> </div>
  20. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <div class="media-block"> <div class="media-block__media"> <!-- image container that adds circle border radius --> <div class="image-frame image-frame--border-radius-full"> <!-- image object --> <img class="image-frame__image" src="img.png"/> </div> </div> <div class="media-block__content"> <!-- text object: user name --> <!-- text object: time ago --> <!-- text object: action completed by user --> </div> </div>
  21. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <div class="media-block"> <div class="media-block__media"> <!-- image container that adds circle border radius --> <div class="image-frame image-frame--border-radius-full"> <!-- image object --> <img class="image-frame__image" src="img.png"/> </div> </div> <div class="media-block__content"> <!-- text object: user name --> <!-- text object: time ago --> <!-- text object: action completed by user --> </div> </div>
  22. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <div class="media-block"> <div class="media-block__media"> <div class="image-frame image-frame--border-radius-full"> <img class="image-frame__image" src="img.png"/> </div> </div> <div class="media-block__content"> <!-- .heading is an text object component --> <!-- can be applied to text and non-text DOM elements --> <span class="heading heading--level-5">Brent...</span> <span class="heading heading--level-6">5 min ago</span> <h5 class="heading heading--level-5">Built...</h5> </div> </div>
  23. /* * Overall Rules */ .media-block { display: table; }

    /* * Local Descendants */ .media-block__content { display: table-cell; vertical-align: middle; } .media-block__media { display: table-cell; vertical-align: middle; padding-right: $content-spacing; } <!-- End product: encapsulated, reusable block of markup --> <!-- Ready to drop into any view --> <div class="media-block"> <div class="media-block__media"> <div class="image-frame image-frame--border-radius-full"> <img class="image-frame__image" src="img.png"/> </div> </div> <div class="media-block__content"> <span class="heading heading--level-5">Brent...</span> <span class="heading heading--level-6">5 min ago</span> <h5 class="heading heading--level-5">Built...</h5> </div> </div>
  24. QA testing: feature turned on for select user groups Training

    session on rewriting existing markup PHASE 2
  25. QA testing: feature turned on for select user groups Training

    session on rewriting existing markup Identify & assign views for “hands-on learning” rewrites PHASE 2
  26. Launch: feature 100% live Ship style guide with full framework

    documentation Pair with teammates as needed on new feature builds PHASE 3
  27. Originally prototyped for 3 user-facing views Grew to cover ALL

    user-facing views Packaged with JS refactor SCOPE CREEP
  28. LEARN_V1 LEARN_V2 (OOCSS) NATIVE 213 stylesheets 31 stylesheets 1.3 MB

    193 KB VENDOR 116 stylesheets 6 stylesheets 848 KB 49 KB TOTAL 329 stylesheets 37 stylesheets 2.1 MB 242 KB
  29. LEARN_V1 LEARN_V2 (OOCSS) NATIVE 213 stylesheets 31 stylesheets 1.3 MB

    193 KB VENDOR 116 stylesheets 6 stylesheets 848 KB 49 KB TOTAL 329 stylesheets 37 stylesheets 2.1 MB 242 KB