Utility-first CSS mit
Puzzle Tech Kafi #Frontend
26.08.2020, Mathis Hofer
Context
How it works
Conclusion
Context
CSS Framework Approaches
Vanilla
CSS
Utility CSS Frameworks
Component CSS Frameworks
Full control
From scratch
Quick results
Customize
The "write from scratch" approach:
Vanilla CSS
Write custom styles and classes
Own conventions
No framework
Optional: Preprocessor (LESS, SASS)
The "works out of the box" approach:
Component CSS Frameworks
Predefined component and utility classes
Use library and add new styles reactively
Quick results
"Everything looks the same"
Heavy theme customizing/CSS overriding
User downloads huge library
Component CSS Frameworks
The "middleway" approach:
Utility CSS Frameworks
No prestyled component classes
Low-level utility classes
Build own components
Create a well thought-out library proactively
Write less (or no) CSS code
Utility CSS Frameworks
Influences
Atomic CSS/Functional CSS
TACHYONS
Atomic CSS
Atomic CSS is the approach to CSS architecture that favors small, single-purpose classes with names based on visual function.
Atomic CSS (cont. 1)
Challenging CSS Best Practices,
Thierry Koblentz (Smashing Magazine, 2013)
Atomic CSS (cont. 2)
Styling via markup
Avoid CSS redundancy
Stop CSS growing
No contextual or descendant selectors
Styles “sandboxed” to attached nodes
Move modules around without losing styles
No dead styles
CSS Bloat ➡️ HTML Bloat
Not about banning “semantic” class names
How it* works
*
The Framework
https://github.com/tailwindlabs/tailwindcss
MIT License
First alpha in 2017
First stable in 2019
Implemented as PostCSS plugin
Directives to be used in CSS files

Configuration File
Breakpoints
Fonts
Color palette
Spacings
Variants
Plugins
Purging
# Create minimal tailwind.config.js
npx tailwindcss init
# Include all defaults
npx tailwindcss init --fullGenerate with CLI:
Inject Styles
/* Injects tailwind base styles
& normalize.css */
@tailwind base;
/* Injects tailwind component classes */
@tailwind components;
/* Add custom component classes here */
/* Injects tailwind utility classes */
@tailwind utilities;
/* Add custom utility classes here */Build
npx tailwindcss build styles.css -o output.css*only necessary after CSS changes or configuration modifications
// postcss.config.js
module.exports = {
plugins: [
// ...
require('tailwindcss'),
require('autoprefixer'),
// ...
]
}*
Preprocessing
PostCSS plugins:
Autoprefixer
Build-time imports: postcss-import
Nesting: postcss-nested, postcss-nesting
Variables: postcss-custom-properties
Future CSS features: postcss-preset-env
Example

Example: Traditional CSS
<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">ChitChat</h4>
<p class="chat-notification-message">You have a new message!</p>
</div>
</div>.chat-notification {
display: flex;
max-width: 24rem;
margin: 0 auto;
padding: 1.5rem;
border-radius: 0.5rem;
background-color: #fff;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.chat-notification-logo-wrapper {
flex-shrink: 0;
}
.chat-notification-logo {
height: 3rem;
width: 3rem;
}
.chat-notification-content {
margin-left: 1.5rem;
padding-top: 0.25rem;
}
.chat-notification-title {
color: #1a202c;
font-size: 1.25rem;
line-height: 1.25;
}
.chat-notification-message {
color: #718096;
font-size: 1rem;
line-height: 1.5;
}Example: Tailwind
<div class="max-w-sm mx-auto flex p-6 bg-white rounded-lg shadow-xl">
<div class="flex-shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div class="ml-6 pt-1">
<h4 class="text-xl text-gray-900 leading-tight">ChitChat</h4>
<p class="text-base text-gray-600 leading-normal">You have a new message!</p>
</div>
</div>
Source:
https://github.com/gojutin/tailwindcss-cheatsheet

Variants
Pseudo-class variants:
Responsive variants:
hover: focus: active: group-hover: group-focus: focus-within: focus-visible: motion-safe: motion-reduce: disabled: visited: checked: first: last: odd: even:
sm: md: lg: xl:
➡️ Prefix utility classes with variant(s)
➡️ Some combinations are not generated per default!
Variants (cont.)
<button class="bg-blue-400 hover:bg-blue-300">
Pseudo-class
</button>
<button class="md:text-lg xl:text-xl">
Responsive: Font size
</button>
<button class="hidden lg:inline-block">
Responsive: Only visible on large screens
</button>
<button class="lg:hover:bg-red-300">
Combined
</button>Responsive Design
Mobile-first breakpoints (min-width)
Customizable in tailwind.config.js
sm
640px
md
768px
lg
1024px
xl
1280px
Extract Components
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Button
</button>Problem:
Utility-first != Utility-only
Extract Components (cont. 1)
Primary choice:
Don't (avoid premature abstraction)
Secondary choice:
Template partial (backend)
or JavaScript component (frontend)
Tertiary choice:
Component class with @apply directive
Extract Components (cont. 2)
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Button
</button><button class="btn-blue">
Button
</button>@tailwind base;
@tailwind components;
/* Custom components */
.btn-blue {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}
@tailwind utilities;Extracted:
Optimizing for Production
Per default the generated CSS is > 1MB
PurgeCSS strips out unused utility classes
(simple Regex based approach)
// tailwind.config.js
module.exports = {
purge: ['src/**/*.html'],
...
}
# Build without unused classes
NODE_ENV=production tailwindcss \
build styles.css \
-o output.cssEnough theory...
Conclusion
+
Focus: markup/style in one place
Super high quality documentation and screencasts
Lot of traction
?
How about more complex components (e.g. datepicker)?
Custom component's accessibility
Mental-Shifts
Choose abstractions wisely
Work with JavaScript components/partials
Work with predefined (gradual) spaces/sizes/colors
Background images ➡️ <img>
Design while you write (ideal for prototyping)
Let's change the methodology of how we write CSS!
Questions?
Slides:
References:
Challenging CSS Best Practices (Thierry Koblentz, Smashing Magazine)
Let’s Define Exactly What Atomic CSS is (John Polacek, CSS-Tricks)
In Defense of Utility-First CSS (Sarah Dayan, dotCSS 2019)
Why I Don't Like Tailwind CSS (Chris Hawkes)
This work is licensed under a
Creative Commons Attribution 4.0 International License.

Utility-first CSS mit Tailwind
By Mathis Hofer
Utility-first CSS mit Tailwind
- 545