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

How to Deal with Technical Debt of CSS

How to Deal with Technical Debt of CSS

Takuya Matsumoto

March 22, 2019
Tweet

More Decks by Takuya Matsumoto

Other Decks in Programming

Transcript

  1. How to Deal with Technical Debt of CSS Takuya Matsumoto

    @upinetree Rails Developer Meetup 2019 Day 1 2019.03.22
  2. Consider the problem in a point of view of a

    programmer based on my experiences
  3. Have you seen problems like below? • Changing CSS occurs

    unintended effects • Styles broken when some HTML structures are changed • Don't know how CSS affects so no one want to touch them • No styles applied for some unknown reasons • Leave to stand unused CSS because removing them is terrible
  4. Accumulated debts cause development bottlenecks • Hard to touch CSS

    by physically and psychologically reasons • Spend much more time for a small change of styles • A teammate great on CSS has heavy workloads and becomes a SPOF • Even shrink entire business
  5. Unlike some programming language, I think there are many teams

    lacking discussion about a technical debt of CSS
  6. CSS works simple • It has some rules like a

    Specificity but basically styles applied just as written • Clear and straightforward in the earliest stage • Looks superficially fine regardless of the quality • Tend to incur an unpayable debt at high interest without thinking
  7. Any language has simplicity at first • Problems underlying CSS

    are: • Difficulty in structuration • Difficulty in recognizing a fact that the code has a debt • Debt will grow below water and suddenly found without increasing concerns in CSS in a team
  8. Development team have to take concerns in too many things

    DB OS Rails Ruby Business Logic Network JavaScript CSS Device Markup Interaction UI UX Design Illustration Concept * Circle sizes have no meaning
  9. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A A certain teammate have concerns in
  10. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A teammate B A certain teammate have concerns in
  11. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A teammate B teammate C A certain teammate have concerns in
  12. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A teammate B teammate C teammate D A certain teammate have concerns in
  13. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A teammate B teammate C teammate D A certain teammate have concerns in Programmers in this team... - want to deliver values to users - think can not touch CSS properly - think designers will make CSS good
  14. DB OS Rails Ruby Business Logic Network JavaScript CSS Device

    Markup Interaction UI UX Design Illustration Concept teammate A teammate B teammate C teammate D A certain teammate have concerns in Designers in this team... - think CSS is a one of a expression methods - are difficult to be motivated to design a code
  15. "Valley of concerns" ؔ৺ͷ୩ • Valleys are easily eroded between

    concerns • Tend to think "Someone will do it better than me", if the valley is recognized • There is probably a mass psychology such as "Bystander effect" https://flic.kr/p/f7yxnc
  16. Bridge the valley • Introduce some structures (= bridge) that

    avoid creating technical debt unconsciously, even if team has intimate knowledge • Note that its effects are limited (because it is just a bridge)
  17. 3 kind of bridges in this session • CSS Methodologies

    • Constraints • Choi-tashi class
  18. CSS Methodologies • Some best practices proposed by forerunners •

    OOCSS, BEM, SUIT CSS, SMACSS, MCSS, RSCSS, ECSS, ITCSS, FLOCSS, FLOU, ... • Outsource documents and background philosophies • Easy to reach to knowledges and many introduction examples
  19. Cons. of CSS Methodologies • Sometimes it is unmatchable for

    your product • If rules are complicated it is hard to understand and allow other interpretations • Can't remember, can't permeate • Tend to just follow methodologies and lose a original purpose
  20. How to decide introducing a CSS methodology • It might

    be a best when minds and solutions of a methodology is matched to the project and satisfy a team • Otherwise, there is a way that introducing a customized one or only some essences • "Constraints" and "Choi-tashi" are recommended essences in my experience, showing the next
  21. Reasons for Constraints • CSS specifications are simple. Thus CSS

    codes could be simple or also could be complicated according to how to write it • Create failure-robast structures by introducing constraints • Explain 3 constraints in this session
  22. Constraint 1: Class naming convention • Class naming is very

    important because CSS is explicitly applied by specified selectors • Many competitions due to no scopes • Should be unique and understandable • Methodologies: BEM, SUIT CSS, ECSS
  23. BEM https://en.bem.info/ • Component based design approach. It composes a

    class name by 3 parts: Block, Element, Modifier • BEM itself do not restrict naming convention and "MindBEMding" is often used as a defacto standard .search-form__button--disabled Block Element Modifier
  24. Naming using BEM • Using BEM can emulate scopes •

    Class name should be unique, understandable and less collisions, same with whoever wrote • Accept trade-off: verbose class name, weird symbols such as __ and --
  25. Constraint 2: Keep specificity same • Unintended competitions occurred when

    there are needless differences of specificities • Specified styles are not applied for some unknown reasons • !important will be appeared • Differences of specificities should be designed by intention, but is hard for a team has "Valley of concenrs"
  26. Specificity wars .links { font-size: 1.2rem; .pickup { color: #933;

    } } * Written in Sass style <nav> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </nav>
  27. Specificity wars .links { font-size: 1.2rem; .pickup { color: #933;

    } } <nav> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </nav> <div id="menu"> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </div> Could be used for the menu too
  28. Specificity wars .links { font-size: 1.2rem; .pickup { color: #933;

    } } #menu { .links { font-size: 1rem; color: #333; } } <nav> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </nav> <div id="menu"> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </div> The menu should have different looks (high specificity)
  29. Specificity wars .links { font-size: 1.2rem; .pickup { color: #933

    !important; } } #menu { .links { font-size: 1rem; color: #333; } } <nav> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </nav> <div id="menu"> <ul class="links"> <li></li> <li></li> <li class="pickup"></li> </ul> </div> Oh, the color style does not appear. !important must be useful
  30. Constraints for preventing unintended specificity changes • No descendant selectors

    (prevent increase) • No ID selectors (prevent increase) • No type selectors (prevent decrease) • Of course, expression ability of CSS is restricted for constraints
  31. example: No descendant selectors Could define exceptions for allowable conditions

    because it is a strong constraint /* Bad */ #menu { .links { font-size: 1rem; color: #333; .sub-links { font-size: 0.8rem; } } } /* Good */ .menu-links { color: #333; } .menu-links-main { font-size: 1rem; } .menu-links-sub { font-size: 0.8rem; }
  32. Constraint 3: Separate layout from style • Specifying layouts and

    looks in a same class sometimes causes overwrite and duplication because it is hard to reuse • Layout-separated classes are reusable and flexible
  33. example: Separation of layout and looks Child selectors increase specificity,

    but it is useful to limit a range (refs. RSCSS) /* Layout (prefix: -l) */ .l-comments { > .comment { margin-top: 8px; } > .comment + .comment { margin-left: 4px; } } /* Looks */ .comment { display: block; border: 1px solid #aaa; }
  34. Cons. of separation of layout and looks • Trade-off of

    a cohesion for a component • Over separated classes increase dependency from HTML and it is difficult to use • Introducing a layout layer and not requiring separation could be a good way • refs: SMACSS, MCSS, ITCSS, FLOCSS, FLOU
  35. Choi-tashi class • "Choi-tashi" == "Small addition" in Japanese •

    Generally it is called "Utility" • Some CSS frameworks have this kind of classes
 (Bootstrap 4, UIKit, Tailwind CSS, Foundation 6, ...) <div class="margin-bottom-3 text-right">Hello</span> <div class="margin-bottom-3 text-center">World</span>
  36. Pros. of choi-tashi • Help separation of layout from style

    • Just focus to core styles of a component • Could handle styles equally without any CSS knowledge • Decrease frequency of designer reviews whether CSS satisfies design basis
  37. What should be choi-tashi Classes for design basis • Spacing

    (margin, padding) • Typography (font-size, line- height) • Color variations Classes for layout separation • Flexbox • Float • Display
  38. Avoid over choi-tashi • Increasing dependency from HTML to CSS

    causes tight coupling and larger effects from changes • Creating class is a recommended way in such cases • Defining max choi-tashi count is effective • a joke: https://github.com/marmelab/universal.css <span class="display-block background-blue font-arial font- color-white solid-blue-border padding-20"></span>
  39. Keep simple choi-tashi class • Specify stable styles because it's

    used in broad range • It is desired that effects of changes are always intended • Avoid overwrite them using kind of descendant selectors. Effects become hard to predict
  40. Big bridge • Complicated rules • Diversified choi-tashi classes •

    Checking appropriate usage of a bridge puts a strain • Confusion by unintended usages • Maintenance costs of a bridge is increasing
  41. Valley of concerns is still exists • Not resolved basically

    yet • A bridge is effective but it essentially means that high-interest debt is just transferred to low-interest debt • Valley itself should be addressed to keep a bridge size as necessary and sufficient
  42. Filling a valley • Expand concerns of a team and

    build a culture for dealing CSS with a whole team • Embracing learning costs is needed. Then, a team could be design and review without any individualization • Action of a team
  43. • Filling a valley is ideal but hard for a

    team that has bigger valley • Start from a bridge, then fill a valley gradually in parallel Solvable problems Feasibility and sustainability Build a bridge Limited Easy
 Start small Fill a valley Fundamentally Hard Unmeasurable Feature comparison
  44. A development team • Low productivity due to debts of

    CSS • Depends on a teammate who is great on CSS
  45. Please review it! A development team • A lot of

    works, become a bottleneck Adjustment is required! Code them!
  46. Merge it once before a deadline A development team •

    If they can not handle tasks, then a debt grows, and more works are coming...it is a negative cycle Well, here goes nothing Wait for a while…
  47. How to address such a team • Hire a front-end

    engineer? • Could be resolved temporary • In the long term, the bottleneck will move to the new member and the negative cycle will continue
  48. • Stop the negative cycle first, and stop incurring debts

    without a plan • Next, create a structure repayable debts How to address such a team
  49. A first small bridge • Introduce choi-tashi class, named "Utility"

    • Easily start using and affect a debt • Slow down growing debts • Reduce works of a teammate great on CSS • Useful for refactoring
  50. Have everyone use the bridge • A bridge no one

    knows is meaningless • Create a style guide and make it known • Use a generator for the style guide • Astrum, Hologram, Fractal, SC5, and so on
  51. Create rules • Policies for new classes • Create an

    agreement for what kind of methodologies and constraints should be adopted • It should be shown in the style guide and be easy to access
  52. In a new page, it is safely implemented with "Utilities

    could be used without hesitation" and "Rules preventing failures"
  53. Negative cycle now stopped • CSS in existing pages are

    still fragile • It blocks instilling new rules • Refactor existing codes to good structures
  54. Before start refactoring • Classes have debts are used widely

    and even be overwritten • Difficult to check unintended effects due to refactoring
  55. Visual regression testing • Automating the testing of how software

    looks • Detect differences of screenshots and test there are no unintended change • Some tools are established • BackstopJS, REG-SUIT
  56. BackstopJS My post for explaining how to use BackstopJS on

    Rails (ja) http://upinetree.hatenablog.com/entry/2018/05/13/231951
  57. Start of steady refactoring work • High priority on a

    high effectiveness or big issue • Reduce repeated but different classes have same styles and same purpose • Separate over reused classes for different purposes • Tweaking code is tempting but it makes refactoring to feel far
  58. Discovery in the refactoring • Common structures should be found

    • ex. Layout like a grid system • Classify them and make it reusable
  59. Do not make code over DRYed • Problem of duplication

    is small rather than code reuse if class is used for different purpose • Mix-in is the same. Abstraction should be duly considered
  60. Taking a break is always important ☕ • Refactoring CSS

    is nothing special, but not a mindless work • It requires a careful work while figuring out the whole structures of the application • Move things forward steadily because a negative cycle is already stopped now
  61. Steady and crude way, but continue • Code is gradually

    getting clear • Yield insight about system-wide knowledge • Better to collaborate with all members of a team • It is opportunities of expanding concerns and filling a valley
  62. Summary • The root of technical debts of CSS is

    a "Valley of concerns" • Bridge to a valley with "CSS Methodologies", "Constraints", "Choi-tashi classes" • Bridge has a limitation so filling a valley is also needed • A road of repaying debs is too long but starting small is easy!
  63. example of allowable descendant selectors: Block closed definition /* Good

    */ .carousel { font-size: 1rem; .home & { font-size: 2rem; } } Specificity changes of .carousel is closed in the block {} so the effects is easily forecastable /* Bad */ .carousel { font-size: 1rem; } .home { .carousel { font-size: 2rem; } } <div class="home"> <div class="carousel"></div> </div>