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

🇨🇿 Productboard Frontend Meetup (Nov 2023)

🇨🇿 Productboard Frontend Meetup (Nov 2023)

ℹ️ It's 2023 and I Can Finally Talk About Atomic CSS

Libraries like Tailwind became quite popular and their utility-first—aka atomic classes—approach was an interesting paradigm shift in CSS. Many developers love it, and it's understandable why.

However, we tend to forget that the core of this technique isn't new. Way before Bootstrap, we all had our small CSS snippets copied from project to project with similar classes.

In this session, we'll discuss the evolution of scalable CSS, walk through the limitations and drawbacks of Atomic CSS, and figure out where this concept can be beneficial.

Matheus Albuquerque

November 22, 2023
Tweet

More Decks by Matheus Albuquerque

Other Decks in Programming

Transcript

  1. Hello, Productboard! 👋 IT'S 2023 AND I CAN FINALLY TALK

    ABOUT ATOMIC CSS • THE 22ND OF NOVEMBER, 2023.
  2. This talk presents… ↝ The Bad (takes) ↝ The Bad

    ↝ The Ugly ↝ The Good (Way) ↝ Closing Thoughts
  3. #definition 🧐 Atomic CSS is the approach to CSS architecture

    that favors small, single- purpose classes with names based on visual function.
  4. #QUESTION ✋ Who here uses — or has used —

    atomic/utility-first CSS? e.g. Tailwind, Tachyons, ACSS...
  5. #QUESTION 🤔 If you were to summarize your experience with

    atomic CSS, what would you say? e.g. easy to reuse, hard to read, love it, an anti-pattern, enforced consistency, BEM is enough…
  6. If you were to summarize your experience with atomic CSS,

    what would you say? IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS
  7. “What About… Inline Styles?” ↝ SURPRISINGLY COSTLY FOR THE BROWSER

    ↝ CAN'T HANDLE MEDIA QUERIES OR PSEUDO SELECTORS ↝ YOU DON’T HAVE TO FOLLOW ANY PRE-EXISTING DEFINITION ↝ UTILITY CLASSES EXPOSE A WELL-DEFINED API AND A SINGLE SOURCE OF TRUTH
  8. “What About… the HTML Bloat?” ↝ THE DEFLATE ALGORITHM (GZIP)

    CAN HANDLE DUPLICATE STRINGS ↝ THE MORE A SELECTOR IS REPEATED IN A STYLESHEET, THE MORE WORK THE BROWSER HAS TO DO TO RESOLVE ALL STYLES
  9. “What About… SoC?” ↝ STYLE COMPOSITION IS PERFORMED IN THE

    HTML, BUT NOT USING style OR align ATTRIBUTES ↝ PIECES ARE ASSEMBLED FROM A STYLESHEET WRITTEN IN CSS AND HTML BECOMES A CONSUMER OF A CSS ↝ EXTREME VISION OF “SEPARATION OF CONCERNS” ↝ DEEPLY IMPRACTICAL (DOGMATIC LEVEL)
  10. “What About…?” ↝ “REDESIGNING/THEMING BECOMES CHALLENGING” ↝ “IT RESULTS IN

    A LOT OF UNUSED CSS” ↝ “IT’S HARD TO KNOW WHAT’S AVAILABLE TO USE” ↝ “A WHOLE OTHER LANGUAGE TO LEARN ON TOP OF CSS” ↝ …
  11. Tailwind has the potential to alleviate some of the concerns

    outlined for atomic CSS and provides intriguing new benefits.
  12. I often see a popular belief that Tailwind is the

    future of web development, and that it represents the correct way to do things.
  13. Semantic HTML/CSS ⇢ Tailwind ↝ BREAK “COMPOUND” SEMANTIC CLASSES INTO

    “ATOMIC” UTILITY CLASSES WITH SINGLE RESPONSIBILITIES ↝ A FAIRLY EASY THING TO DO
  14. Tailwind ⇢ Semantic HTML/CSS ↝ IT’S HARD TO PICTURE A

    TOOL THAT DOES THE REVERSE ↝ YOU CAN’T REALLY BUILD MORE COMPLEX WITHOUT ASSEMBLING THOSE CLASSES BY HAND ↝ YOU COULD ONLY REALISTICALLY CONVERT TAILWIND INTO SOME OTHER UTILITY FRAMEWORK
  15. Utility CSS Lock-in ↝ MOVING TO ANY OTHER FRAMEWORK OR

    PREPROCESSOR REQUIRES A CONSIDERABLE AMOUNT OF REFACTORING ↝ MOST OF US AREN’T SWAPPING OUT CSS FRAMEWORKS ON PROJECTS ON A REGULAR BASIS ↝ BUT IT’S AN IMPORTANT CONSIDERATION FOR APPS THAT YOU’LL BE MAINTAINING IN THE FUTURE
  16. Missing Key CSS Features ↝ BACKGROUND GRADIENTS; ↝ ANIMATIONS; ↝

    NEW SELECTORS (:is AND :where) ↝ NEW FUNCTIONS (min(), max(), AND clamp()) ↝ OTHER BLEEDING-EDGE FEATURES
  17. Class Detection ↝ TAILWIND DOESN'T PARSE OR EXECUTE ANY OF

    THE CODE ↝ IT USES REGULAR EXPRESSIONS TO EXTRACT EVERY STRING THAT COULD POSSIBLY BE A CLASS NAME ↝ IT WILL ONLY FIND CLASSES THAT EXIST AS COMPLETE UNBROKEN STRINGS ↝ YOU CAN'T CONSTRUCT CLASS NAMES DYNAMICALLY
  18. Hard to Scan <div className="w-16 h-16 rounded text-white bg-black py-1

    px-2 m-1 text-sm md:w-32 md:h-32 md:rounded-md md:text-base lg:w-48 lg:h-48 lg:rounded-lg lg:text-lg"/>
  19. Hard to Scan .class { width: 16px; height: 16px; color:

    white; background-color: black; padding: 0.25rem 0.5rem; margin: 0.25rem; border-radius: 0.25rem; font-size: 0.875rem; line-height: 1.25rem; } @media screen and (min-width: 768px) { .class { width: 32px; height: 32px; border-radius: 0.375rem; font-size: 1rem; line-height: 1.5rem; } } @media screen and (min-width: 1024px) { .class { width: 48px; height: 48px; border-radius: 0.5rem; font-size: 1.125rem; line-height: 1.75rem; } }
  20. Hard to Scan .class { width: 16px; height: 16px; color:

    white; background-color: black; padding: 0.25rem 0.5rem; margin: 0.25rem; border-radius: 0.25rem; font-size: 0.875rem; line-height: 1.25rem; } @media screen and (min-width: 768px) { .class { width: 32px; height: 32px; border-radius: 0.375rem; font-size: 1rem; line-height: 1.5rem; } } @media screen and (min-width: 1024px) { .class { width: 48px; height: 48px; border-radius: 0.5rem; font-size: 1.125rem; line-height: 1.75rem; } }
  21. Hard to Scan ↝ IT'S SIMPLER TO SCAN IF YOU

    ONLY NEED TO READ YOUR CODE FROM TOP TO BOTTOM ↝ IT'S EASIER TO FIND SPECIFIC PROPERTY-VALUE PAIRS ↝ PROPER SYNTAX HIGHLIGHTING SEPARATES PROPERTIES FROM VALUES AND ENHANCES READABILITY
  22. Encouraged Tag Soup ↝ THE FOCUS IS ON THE CLASSES,

    NOT THE MARKUP ↝ TAILWINDCSS DOESN’T PROMOTE “UGLY HTML” AT ALL ↝ BUT YOU CAN THROW IN AS MANY <div> AS YOU WANT WITHOUT CARING ABOUT MEANING ↝ YOU CAN DO IT THE RIGHT WAY, BUT ERGONOMICS LEAN DEEP DOM
  23. #hotTake 🌶 The problem lies in thinking in CSS classes

    first, rather than starting with markup and working the CSS from there.
  24. #hotTake 🌶 Tools can make it easy to do certain

    things the wrong way. Their approach makes poor semantics the easiest path.
  25. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #3 DEVELOPER (TOOLS) EXPERIENCE
  26. Hard To Find Components ↝ WHEN TROUBLESHOOTING IN A LARGE

    CODE BASE, NARROWING DOWN THE AFFECTED COMPONENT IS IMPORTANT ↝ HAVING A CLOSE MAPPING BETWEEN A COMPONENT’S NAME AND ITS CLASS NAMES MAKES IT EASIER TO FIND THE RELEVANT CODE QUICKLY ↝ HERE, WE HAVE TWO OPTIONS: KNOWLEDGE OF THE PARTICULAR AREA OF THE APP AND STRINGS
  27. Hard To Find Components ↝ NOT EVERYONE ON A TEAM

    MAY BE FAMILIAR WITH EVERY COMPONENT IN THE CODE BASE (ENTERPRISE-SCALE MONOREPOS, NEW HIRES, ETC.) ↝ STRINGS MAY GET REUSED ACROSS MULTIPLE COMPONENTS = SEARCHING MAY YIELD MULTIPLE RESULTS ↝ IT’S HARD TO DETERMINE WHERE A MODULE STARTS AND ENDS
  28. Hard to Tweak CSS ↝ MAKING STYLE TWEAKS THROUGH DEV

    TOOLS IN THE BROWSER IS A COMMON PRACTICE ↝ HERE, YOU NEED TO GIVE EACH COMPONENT A NEW CLASS NAME AND USE THAT AS THE SELECTOR ↝ …OR USE INLINE STYLES, BUT SOMETIMES IT'S HELPFUL TO SEE HOW CHANGES ARE REFLECTED THROUGHOUT THE UI
  29. @for $i from 1 through 10 { .m-#{$i} { margin:

    $i / 4 rem; } } On-Demand Generation [BEFORE]
  30. @for $i from 1 through 10 { .m-#{$i} { margin:

    $i / 4 rem; } } .m-1 { margin: 0.25 rem; } .m-2 { margin: 0.5 rem; } / * . . . * / .m-10 { margin: 2.5 rem; } On-Demand Generation [BEFORE]
  31. On-Demand Generation [AFTER] CSS YOU ARE USING CSS SHIPPED (PROD

    / DEV) CSS GENERATED ON DEMAND SCAN GENERATE SHIP
  32. Beware of @apply NEGATES BENEFITS GAINED OVER TRADITIONAL COMPONENT- DRIVEN

    CSS: ↝ THE EXPLICITNESS OF THE CLASS NAME ↝ THE TIME SAVED BY NOT HAVING TO WRITE YOUR OWN CSS ↝ THE SINGLE SOURCE OF TRUTH
  33. Beware of @apply ↝ EXTREMELY DESTRUCTIVE POTENTIAL ↝ E.G. USE

    FUNCTIONAL CLASSES AS AN ESCAPE HATCH TO UNDO COMPONENT RULES ↝ STRIVE TO BE EXTREMELY STRICT WITH THE APPLICATION OF BOTH SO THAT THEY DO NOT INTERSECT OR SHARE CONCERNS
  34. StyleSheet Composition [SIMPLE] import { clsx, type ClassValue } from

    "clsx" import { twMerge } from "tailwind-merge" export function classnames(…inputs: ClassValue[]) { return twMerge(clsx(inputs)) }
  35. const Input = ({ className, . . . props })

    = > { return <input className={classnames(' . . . ', className)} { . . . props} />; }; import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function classnames(…inputs: ClassValue[]) { return twMerge(clsx(inputs)) } StyleSheet Composition [SIMPLE]
  36. const buttonVariants = cva( ' . . . ', {

    variants: { intent: { primary: 'bg-green-500 hover:bg-green-600', secondary: 'bg-red-500 hover:bg-red-600', default: 'bg-gray-500 hover:bg-gray-600', }, size: { small: ['text-sm', 'py-1', 'px-2'], medium: ['text-base', 'py-2', 'px-4'], large: ['text-lg', 'py-4', 'px-8'], }, roundness: { square: 'rounded-none', round: 'rounded-md', pill: 'rounded-full', }, }, defaultVariants: { intent: 'default', size: 'medium', roundness: 'round', }, } ); StyleSheet Composition [COMPLEX]
  37. intent: { primary: 'bg-green-500 hover:bg-green-600', secondary: 'bg-red-500 hover:bg-red-600', default: 'bg-gray-500

    hover:bg-gray-600', } size: { small: ['text-sm', 'py-1', 'px-2'], medium: ['text-base', 'py-2', 'px-4'], large: ['text-lg', 'py-4', 'px-8'], } roundness: { square: 'rounded-none', round: 'rounded-md', pill: 'rounded-full', } StyleSheet Composition [COMPLEX]
  38. StyleSheet Composition [COMPLEX] export default function Button({ intent, size, roundness,

    children }) { return ( <button className={buttonVariants({ intent, size, roundness })}>{children}</button> ) }
  39. Accessibility ↝ BUILD PROCESS: CATCH ERRORS AS YOU BUILD OUT

    THE APP (AXE-CORE, JSX-A11Y, LIGHTHOUSE AUDITS, ACCESSLINT.JS) ↝ CONTINUOUS INTEGRATION: FIND ISSUES IN YOUR PULL REQUESTS (AXE-LINTER OR ACCESSLINT)
  40. #hotTake 🌶 It allows us to write our styles in

    a familiar “monolithic” way, but get Atomic CSS out. — THE SHORTHAND-LONGHAND PROBLEM IN ATOMIC CSS, BY ROBIN WESER
  41. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #1 IT’S JUST A TOOL BUT THE RIGHT TOOL™ CAN MAKE A HUGE DIFFERENCE
  42. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #2 THE SOLUTION TO THE PROBLEM ONLY CHANGES THE PROBLEM
  43. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #2 THE SOLUTION TO THE PROBLEM ONLY CHANGES THE PROBLEM TRADE-OFFS TRADE-OFFS TRADE-OFFS
  44. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #3 UTILITY CLASSES CAN COEXIST WITH OTHER APPROACHES THE SWEET SPOT FOR YOU MIGHT BE A HYBRID OF DIFFERENT CONVENTIONS
  45. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #4 TAILWIND SUFFERS FROM THINKING IT APPLIES TO ALL PROJECTS
  46. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #5 JSX CREATED A SIMILAR FEELING AMONG DEVELOPERS WORLDWIDE …IT WAS GOING AGAINST SO MANY BEST PRACTICES THAT IT COULDN'T BE CONSIDERED A GOOD IDEA
  47. If you were to summarize your experience with atomic CSS,

    what would you say? IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS
  48. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    #6 THERE’S AN EMOTIONAL FACET TO DEVELOPERS’ TECH CHOICES THIS SCORCHING PASSION IS USUALLY WHAT’S CALLED TEAM IDENTIFICATION IN PSYCHOLOGY
  49. IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS

    ↑ ALL THE LINKS! 🧑🏫 TECHLABS 🐦 @ythecombinator 👨💻 MEDALLIA ⚡ GDE
  50. THAT’S ALL, FOLKS! THANKS! 👋 QUESTIONS? MATHEUS ALBUQUERQUE • @ythecombinator

    ↑ ALL THE LINKS! IT'S 2023 AND I CAN FINALLY TALK ABOUT ATOMIC CSS