How to Deal with Technical Debt of CSS

How to Deal with Technical Debt of CSS

0814cba621ab9aeabcf91b4095d9dd50?s=128

Takuya Matsumoto

March 22, 2019
Tweet

Transcript

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

    @upinetree Rails Developer Meetup 2019 Day 1 2019.03.22
  2. Takuya Matsumoto @upinetree Everyleaf corp. גࣜձࣾ ສ༿ Programmer Hometown: Nagaoka,

    Niigata, Japan Love: Sake, Guitar, Game
  3. #ݱ৔Rails ͕Μ͹Γ·ͨ͠

  4. TODAY'S Theme Technical Debt of CSS

  5. Consider the problem in a point of view of a

    programmer based on my experiences
  6. Why does CSS technical debt happen

  7. 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
  8. 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
  9. This structure seems same with the (Ruby) programming from the

    point of view of a technical debt
  10. Unlike some programming language, I think there are many teams

    lacking discussion about a technical debt of CSS
  11. Why?

  12. Examine a background of CSS

  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. CSS The valley outside of concerns

  23. "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
  24. How to over the valley of concerns

  25. 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)
  26. 3 kind of bridges in this session • CSS Methodologies

    • Constraints • Choi-tashi class
  27. CSS Methodologies

  28. 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
  29. 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
  30. 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
  31. Constraints

  32. 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
  33. 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
  34. 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
  35. 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 --
  36. 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"
  37. 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>
  38. 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
  39. 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)
  40. 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
  41. 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
  42. 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; }
  43. 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
  44. 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; }
  45. 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
  46. Choi-tashi class

  47. 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>
  48. 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
  49. 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
  50. 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>
  51. 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
  52. Limitation of the bridge

  53. 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
  54. 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
  55. 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
  56. Feature comparison 4PMWBCMFQSPCMFNT 'FBTJCJMJUZBOE TVTUBJOBCJMJUZ #VJMEB CSJEHF -JNJUFE &BTZ
 4UBSUTNBMM

    'JMMBWBMMFZ 'VOEBNFOUBMMZ )BSE 6ONFBTVSBCMF
  57. • 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
  58. In what order should deal with them

  59. A development team • Low productivity due to debts of

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

    works, become a bottleneck Adjustment is required! Code them!
  61. 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…
  62. 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
  63. • Stop the negative cycle first, and stop incurring debts

    without a plan • Next, create a structure repayable debts How to address such a team
  64. 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
  65. 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
  66. Astrum http://astrum.nodividestudio.com/

  67. What contents should be listed • Defined Utilities, examples, notices

    • How to update the style guide itself
  68. 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
  69. In a new page, it is safely implemented with "Utilities

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

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

    and even be overwritten • Difficult to check unintended effects due to refactoring
  72. 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
  73. BackstopJS My post for explaining how to use BackstopJS on

    Rails (ja) http://upinetree.hatenablog.com/entry/2018/05/13/231951
  74. 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
  75. Discovery in the refactoring • Common structures should be found

    • ex. Layout like a grid system • Classify them and make it reusable
  76. 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
  77. 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
  78. 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
  79. Summary

  80. 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!
  81. Appendix

  82. 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>