Restructure, tidy up
Before Width: | Height: | Size: 267 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 441 KiB |
Before Width: | Height: | Size: 281 KiB |
Before Width: | Height: | Size: 432 KiB |
Before Width: | Height: | Size: 2 MiB |
|
@ -1,667 +0,0 @@
|
|||
theme: poster, 8
|
||||
autoscale: true
|
||||
build-lists: true
|
||||
header-emphasis: #53B0EB
|
||||
header: alignment(left)
|
||||
text: alignment(left)
|
||||
text-emphasis: #53B0EB
|
||||
code: line-height(1.2)
|
||||
|
||||
[.hide-footer]
|
||||
[.header: alignment(center)]
|
||||
|
||||
## [fit] _Taking Flight with_
|
||||
## [fit] Tailwind CSS
|
||||
|
||||
With Oliver Davies
|
||||
|
||||
---
|
||||
|
||||
[.background-color: #FFFFFF]
|
||||
[.build-lists: false]
|
||||
[.header: #111111]
|
||||
[.text: #111111, alignment(left)]
|
||||
|
||||

|
||||
|
||||
- Full Stack Web Developer & System Administrator
|
||||
- Senior Developer at Microserve
|
||||
- Part-time freelancer
|
||||
- Acquia certified Drupal 8 Grand Master
|
||||
- Drupal 7 & 8 core contributor
|
||||
- Symfony, Laravel, ~~Silex,~~ Sculpin
|
||||
- @opdavies
|
||||
- www.oliverdavies.uk
|
||||
|
||||
^ Work at Microserve.
|
||||
Maintain Drupal modules, PHP CLI tools and libraries
|
||||
Blog on my website
|
||||
|
||||
---
|
||||
|
||||
[.background-color: #FFFFFF]
|
||||
[.build-lists: false]
|
||||
[.text: #111111, alignment(left)]
|
||||
|
||||

|
||||
|
||||
- https://microserve.io
|
||||
- https://www.drupal.org/microserve
|
||||
- https://github.com/microserve-io
|
||||
- https://twitter.com/microserveltd
|
||||
- https://www.linkedin.com/company/microserve-ltd
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
## A _Utility-First CSS Framework_ for Rapid UI Development
|
||||
|
||||
^ What is Tailwind?
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
|
||||
## A CSS framework <br>_with no CSS_
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
|
||||
## _A different way_ <br>to write CSS
|
||||
|
||||
---
|
||||
|
||||
[.build-lists: false]
|
||||
|
||||
- Developed by Adam Wathan and others
|
||||
- Utility CSS class generator
|
||||
- PostCSS
|
||||
- Configured with JavaScript
|
||||
- Some preprocessor features
|
||||
- Can be used in addition to preprocessors
|
||||
- Open source
|
||||
|
||||
^ Works with plain CSS or any preprocessor
|
||||
Can be configured to enable/disable modules, configure colours etc.
|
||||
Can use features like variables if using plain CSS.
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.title {
|
||||
background-color: #3490DC;
|
||||
color: #FFF;
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
padding: 2rem;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.text-2xl {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.bg-red {
|
||||
background-color: #93140B;
|
||||
}
|
||||
|
||||
.text-white {
|
||||
color: #FFF;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<div class="text-2xl bg-red text-white p-8">
|
||||
<p>Hello, PHP South Wales!</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# Installation
|
||||
|
||||
---
|
||||
|
||||
[.header: #53B0EB]
|
||||
|
||||
# Option 1
|
||||
|
||||
```
|
||||
https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[.header: #53B0EB]
|
||||
|
||||
# Option 2
|
||||
|
||||
```bash
|
||||
npm install tailwindcss --save-dev
|
||||
|
||||
yarn add tailwindcss --dev
|
||||
|
||||
./node_modules/.bin/tailwind init [filename]
|
||||
```
|
||||
|
||||
^ Install with npm or Yarn
|
||||
Run "tailwind init" to generate a default tailwind.js file
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// tailwind.js
|
||||
|
||||
var colors = {
|
||||
'transparent': 'transparent',
|
||||
|
||||
'black': '#222b2f',
|
||||
'grey-darkest': '#364349',
|
||||
'grey-darker': '#596a73',
|
||||
'grey-dark': '#70818a',
|
||||
'grey': '#9babb4',
|
||||
'grey-light': '#dae4e9',
|
||||
'grey-lighter': '#f2f2f2',
|
||||
'grey-lightest': '#fafcfc',
|
||||
'white': '#ffffff',
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```less
|
||||
// app.css
|
||||
|
||||
@tailwind preflight;
|
||||
|
||||
@tailwind components;
|
||||
|
||||
@tailwind utilities;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// webpack.mix.js
|
||||
|
||||
let mix = require('laravel-mix');
|
||||
|
||||
|
||||
mix.postCss('build', 'assets/css/app.css', [
|
||||
require('laravel-mix-tailwind')()
|
||||
])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// webpack.mix.js
|
||||
|
||||
let mix = require('laravel-mix');
|
||||
|
||||
|
||||
mix.postCss('build', 'assets/css/app.css', [
|
||||
require('laravel-mix-tailwind')('./tailwind.config.js')
|
||||
])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// webpack.config.js
|
||||
|
||||
Encore
|
||||
.setOutputPath('public/build/')
|
||||
.setPublicPath('/build')
|
||||
.addStyleEntry('app', './assets/css/app.css')
|
||||
.enablePostCssLoader()
|
||||
;
|
||||
```
|
||||
|
||||
^ Using Webpack Encore
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// postcss.config.js
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('tailwindcss')('./tailwind.js'),
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<head>
|
||||
<title>Hello, World!</title>
|
||||
<link rel="stylesheet" href="/build/app.css">
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<div class="text-2xl bg-red text-white p-8">
|
||||
<p>Hello, PHP South Wales!</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# Configuration
|
||||
|
||||
---
|
||||
|
||||
```javascript
|
||||
// tailwind.js
|
||||
|
||||
var colors = {
|
||||
...
|
||||
|
||||
'blue-darkest': '#05233b',
|
||||
'blue-darker': '#103d60',
|
||||
'blue-dark': '#2779bd',
|
||||
'blue': '#0678be',
|
||||
'blue-light': '#6cb2eb',
|
||||
'blue-lighter': '#bcdefa',
|
||||
'blue-lightest': '#eff8ff',
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
^ Add, change, remove values as needed
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
screens: {
|
||||
'sm': '576px',
|
||||
'md': '768px',
|
||||
'lg': '992px',
|
||||
'xl': '1200px',
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
textSizes: {
|
||||
'xs': '.75rem', // 12px
|
||||
'sm': '.875rem', // 14px
|
||||
'base': '1rem', // 16px
|
||||
'lg': '1.125rem', // 18px
|
||||
'xl': '1.25rem', // 20px
|
||||
'2xl': '1.5rem', // 24px
|
||||
'3xl': '1.875rem', // 30px
|
||||
'4xl': '2.25rem', // 36px
|
||||
'5xl': '3rem', // 48px
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
width: {
|
||||
'auto': 'auto',
|
||||
'px': '1px',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'10': '2.5rem',
|
||||
'12': '3rem',
|
||||
'16': '4rem',
|
||||
'24': '6rem',
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
padding: {
|
||||
'px': '1px',
|
||||
'0': '0',
|
||||
'1': '0.25rem',
|
||||
'2': '0.5rem',
|
||||
'3': '0.75rem',
|
||||
'4': '1rem',
|
||||
'5': '1.25rem',
|
||||
'6': '1.5rem',
|
||||
'8': '2rem',
|
||||
'16': '4rem',
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```javascript
|
||||
options: {
|
||||
prefix: '',
|
||||
important: false,
|
||||
separator: ':',
|
||||
}
|
||||
```
|
||||
|
||||
^ - Drupal important config
|
||||
- By adding a prefix, we don't clash with Drupal's core styles - e.g. ".block"
|
||||
|
||||
---
|
||||
|
||||
[.build-lists: false]
|
||||
|
||||
- Colours (text and background)
|
||||
- Font family, size, weight
|
||||
- Leading (line height), tracking (letter spacing)
|
||||
- Border widths, colours, radius
|
||||
- Width, height, min/max width/height
|
||||
|
||||
---
|
||||
|
||||
[.build-lists: false]
|
||||
|
||||
- Padding, margin (positive and negative)
|
||||
- Shadows
|
||||
- Z-index
|
||||
- Opacity
|
||||
- SVG fill, stroke
|
||||
- Screen sizes (breakpoints)
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# States
|
||||
### _Hover, Focus, Active, Group hover_
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.{state}{separator}{class}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
<a class="bg-grey hover:bg-grey-dark focus:bg-grey-dark" href="/">
|
||||
Home
|
||||
</a>
|
||||
```
|
||||
|
||||
^ Hover, focus
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
<a class="group">
|
||||
<img
|
||||
class="border-white group-hover:border-grey"
|
||||
src="{{ speaker.photoUrl }}"
|
||||
>
|
||||
|
||||
<div class="no-underline group-hover:underline">
|
||||
{{ speaker.name }}
|
||||
</div>
|
||||
</a>
|
||||
```
|
||||
|
||||
^ Group hover
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# Responsive
|
||||
|
||||
---
|
||||
|
||||
```less
|
||||
.{screen}{separator}{class}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<div class="w-full md:w-1/2 lg:w-1/4">
|
||||
<p>Hello, World!</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# Extracting <br>Components
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
|
||||
## _Do you need to_ extract <br>a component?
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
{% for item in items %}
|
||||
<a class="block py-3 px-4 text-sm text-grey" href="{{ item.url }}">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
^ Use a loop
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
<h2>Adults</h2>
|
||||
|
||||
{% include 'class-list' with {
|
||||
classes: page.classes,
|
||||
type: 'adults',
|
||||
} %}
|
||||
|
||||
<h2>Kids</h2>
|
||||
|
||||
{% include 'class-list' with {
|
||||
classes: page.classes,
|
||||
type: 'kids',
|
||||
} %}
|
||||
```
|
||||
|
||||
^ Move the duplicate markup into a partial, so there's only one version
|
||||
Pass data in.
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<a href="inline-block rounded text-sm py-2 px-3 text-white bg-red">
|
||||
Click me!
|
||||
</a>
|
||||
|
||||
<a href="inline-block rounded text-sm py-2 px-3 text-white bg-green">
|
||||
Click me too!
|
||||
</a>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
# main.css
|
||||
|
||||
.button {
|
||||
@apply .inline-block;
|
||||
@apply .rounded;
|
||||
@apply .text-sm;
|
||||
@apply .py-2;
|
||||
@apply .px-3;
|
||||
@apply .text-white;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<a href="button bg-red">
|
||||
Click me!
|
||||
</a>
|
||||
|
||||
<a href="button bg-green">
|
||||
Click me too!
|
||||
</a>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```less
|
||||
// table.less
|
||||
|
||||
.table-responsive {
|
||||
@apply .mb-4 .border .w-full;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.table-responsive table {
|
||||
@apply .mb-0 .border-0 .whitespace-no-wrap;
|
||||
}
|
||||
|
||||
.table {
|
||||
@apply .w-full .table-collapse;
|
||||
}
|
||||
|
||||
.table tr:nth-child(odd) {
|
||||
@apply .bg-grey-lightest;
|
||||
}
|
||||
|
||||
.table tr th {
|
||||
@apply .text-left .p-3 .bg-white;
|
||||
}
|
||||
|
||||
.table td {
|
||||
@apply .px-3 .py-3 .border-t;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[.header: #53B0EB]
|
||||
|
||||
# Advantages
|
||||
|
||||
- Quick to prototype and make changes
|
||||
- Write less CSS
|
||||
- More consistency
|
||||
- Easy to customise, promote to components
|
||||
- Mix and match with normal CSS
|
||||
- Easy to write reusable plugins
|
||||
- Use PurgeCSS to remove unused classes
|
||||
|
||||
^ Do more with browser dev tools
|
||||
Only picking from pre-defined colours, widths. No magic numbers.
|
||||
Less ramp-up time as using the same framework on different sites.
|
||||
Same classes, but no visual similarities like with other frameworks like Bootstrap
|
||||
|
||||
---
|
||||
|
||||
[.header: #53B0EB]
|
||||
|
||||
# Disadvantages
|
||||
|
||||
- Extra build tools and steps
|
||||
- Lots of classes in markup
|
||||
- Large file size by default
|
||||
|
||||
^ - Need a build tool (Gulp, Grunt, Webpack) to build CSS
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
[.build-lists: false]
|
||||
[.header: #53B0EB]
|
||||
|
||||
# Resources
|
||||
|
||||
- tailwindcss.com
|
||||
- tailwindcomponents.com
|
||||
- github.com/merchedhq/awesome-tailwindcss
|
||||
- youtube.com/adamwathan
|
||||
- github.com/opdavies/oliverdavies.uk
|
||||
- github.com/phpsw/phpsw-ng
|
||||
|
||||
---
|
||||
|
||||
[.header: alignment(center)]
|
||||
|
||||
# Thanks!
|
||||
### _@opdavies_
|
||||
### _oliverdavies.uk_
|
||||
|
Before Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 201 KiB |
Before Width: | Height: | Size: 129 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 172 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 621 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 226 KiB |
Before Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 154 KiB |
Before Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 163 KiB |
Before Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 118 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 110 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 138 KiB |
Before Width: | Height: | Size: 165 KiB |
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 192 KiB |
Before Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 467 KiB |
Before Width: | Height: | Size: 434 KiB |
Before Width: | Height: | Size: 306 KiB |
Before Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 139 KiB |
Before Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 160 KiB |
|
@ -1,10 +0,0 @@
|
|||
<svg class="w-10 h-10 lg:w-12 lg:h-12 block" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Tailwind CSS</title>
|
||||
<path d="M13.5 11.1C15.3 3.9 19.8.3 27 .3c10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05zM0 27.3c1.8-7.2 6.3-10.8 13.5-10.8 10.8 0 12.15 8.1 17.55 9.45 3.6.9 6.75-.45 9.45-4.05-1.8 7.2-6.3 10.8-13.5 10.8-10.8 0-12.15-8.1-17.55-9.45-3.6-.9-6.75.45-9.45 4.05z" transform="translate(5 16)" fill="url(#logoMarkGradient)" fill-rule="evenodd"></path>
|
||||
<defs>
|
||||
<linearGradient x1="0%" y1="0%" y2="100%" id="logoMarkGradient">
|
||||
<stop stop-color="#2298BD"></stop>
|
||||
<stop offset="1" stop-color="#0ED7B5"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 918 B |
Before Width: | Height: | Size: 86 KiB |
|
@ -1,883 +0,0 @@
|
|||
autoscale: true
|
||||
theme: Plain Jane, 1
|
||||
|
||||
# **Taking Flight with <br>Tailwind CSS**
|
||||
|
||||

|
||||
|
||||
^ Tailwind CSS is a framework that I've been using for the last year and a half
|
||||
Going to be using Tailwind 1.0 which was released recently (May 13th)
|
||||
|
||||
---
|
||||
|
||||
- PHP and Front End Developer
|
||||
- System Administrator
|
||||
- Senior Engineer at Inviqa
|
||||
- Part-time freelancer
|
||||
- Open sourcer
|
||||
- @opdavies
|
||||
- oliverdavies.uk
|
||||
|
||||

|
||||
|
||||
^ Co-organiser of PHP South Wales and DrupalCamp Bristol
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
# **What is Tailwind CSS?**
|
||||
|
||||
---
|
||||
|
||||
[.footer: tailwindcss.com]
|
||||
|
||||
# A **utility-first** CSS framework for rapidly building **custom designs**.
|
||||
|
||||
^ CSS utility class generator
|
||||
PostCSS
|
||||
Make different looking sites using the same class names
|
||||
No "Tailwind looking site" like there is with Bootstrap
|
||||
|
||||
---
|
||||
|
||||
[.footer: tailwindcss.com]
|
||||
|
||||
# Tailwind CSS is a **highly customizable**, **low-level** CSS framework
|
||||
|
||||
^ No components like Bootstrap or Bulma
|
||||
Configure it per project
|
||||
Extendable if needed via additional plugins
|
||||
Avoids the need to name things prematurely
|
||||
Can extract components if needed (reusability)
|
||||
|
||||
---
|
||||
|
||||
[.footer: tailwindcss.com/docs/what-is-tailwind/#designed-to-be-customized]
|
||||
|
||||
# Tailwind is more than a CSS framework, it's an engine for <br>**creating design systems**.
|
||||
|
||||
^ Good default values provided - colours, fonts, padding, widths
|
||||
Designing with constraints. Using inline styles, every value is a magic number. With utilities, you're choosing styles from a predefined design system, which makes it much easier to build visually consistent UIs.
|
||||
|
||||
---
|
||||
|
||||
- Text/border/background colours
|
||||
- Font size/family/weight
|
||||
- Alignment
|
||||
- Padding/margin/negative margin
|
||||
- Flexbox
|
||||
- Positioning
|
||||
- Lists
|
||||
- z-index
|
||||
- Opacity
|
||||
- ...
|
||||
|
||||
^ All generated from a single, customisable configuration file.
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
# **How do I use Tailwind?**
|
||||
|
||||
^ From the new tailwindcss.com website
|
||||
|
||||
---
|
||||
|
||||
# With Tailwind, you style elements <br>by **applying pre-existing classes** directly in your HTML.
|
||||
|
||||
---
|
||||
|
||||
# Using **utility classes** to build custom designs **without writing CSS**
|
||||
|
||||
---
|
||||
|
||||
## **Benefits**
|
||||
- You aren't wasting time and energy inventing class names
|
||||
- Your CSS stops growing
|
||||
- Making changes feels safer
|
||||
|
||||
^ No more adding silly class names like sidebar-inner-wrapper just to be able to style something, and no more agonizing over the perfect abstract name for something that's really just a flex container.
|
||||
|
||||
^ Using a traditional approach, your CSS files get bigger every time you add a new feature. With utilities, everything is reusable so you rarely need to write new CSS.
|
||||
|
||||
^ CSS is global and you never know what you're breaking when you make a change. Classes in your HTML are local, so you can change them without worrying about something else breaking.
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Add padding with p-6
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Rounded image - rounded-full
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Centre image using mx-auto
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Larger text - text-lg
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Purple text - text-purple-500
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Grey text - text-gray-600
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Centre text - text-center
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Responsive: enable flexbox on medium screens - md:flex
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Remove margin around image - md:mx-0
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Re-align text on medium screens - md:text-left
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ md:mr-6 - add margin to the side of the image on medium screens
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Increase image size - md:h-24 md:w-24
|
||||
|
||||
---
|
||||
|
||||

|
||||
|
||||
^ Smaller view
|
||||
|
||||
---
|
||||
|
||||
# **How do I install Tailwind?**
|
||||
|
||||
---
|
||||
|
||||
# **1. Use the CDN**
|
||||
|
||||
---
|
||||
|
||||
[.footer: https://next.tailwindcss.com/docs/installation]
|
||||
|
||||
## **https://unpkg.com/tailwindcss/dist/tailwind.min.css**
|
||||
|
||||
---
|
||||
|
||||
[.footer: https://next.tailwindcss.com/docs/installation]
|
||||
|
||||
## **To get the most out of Tailwind, <br>you really should install it via npm.**
|
||||
|
||||
^ - You can't customize Tailwind's default theme
|
||||
- You can't use any directives like *@apply*, *@variants*, etc.
|
||||
- You can't enable features like *group-hover*
|
||||
- You can't install third-party plugins
|
||||
|
||||
---
|
||||
|
||||
## **2. Installing Tailwind via NPM**
|
||||
|
||||
---
|
||||
|
||||
## `npm install --save-dev` <br>`tailwindcss`
|
||||
|
||||
## `yarn add -D tailwindcss`
|
||||
|
||||
^ Adds it as a dependency to your package.json file
|
||||
|
||||
---
|
||||
|
||||
## **Adding Tailwind to your CSS**
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 2-7]
|
||||
|
||||
```css
|
||||
# src/css/style.css
|
||||
|
||||
@tailwind base;
|
||||
|
||||
@tailwind components;
|
||||
|
||||
@tailwind utilities;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 5,9,13]
|
||||
|
||||
```
|
||||
# app.css
|
||||
|
||||
@tailwind base;
|
||||
|
||||
# Custom base styles
|
||||
|
||||
@tailwind components;
|
||||
|
||||
# Custom components
|
||||
|
||||
@tailwind utilities;
|
||||
|
||||
# Custom utilities
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Processing your CSS with Tailwind <br>with the build command**
|
||||
|
||||
^ Compile the generated CSS
|
||||
Pass through PostCSS and Tailwind
|
||||
|
||||
---
|
||||
|
||||
# `npx tailwind build` <br>`src/css/app.css` <br>`-o dist/css/app.css`
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Processing your CSS with Tailwind <br>with Laravel Mix**
|
||||
|
||||
---
|
||||
|
||||
# `npm install --save-dev laravel-mix`
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
const mix = require('laravel-mix')
|
||||
|
||||
mix.postCss('src/css/app.css', 'dist/css', [
|
||||
require('tailwindcss')()
|
||||
])
|
||||
```
|
||||
|
||||
^ PostCSS - useful if you're including other PostCSS plugins like PostCSS Nested
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
const mix = require('laravel-mix')
|
||||
|
||||
require('laravel-mix-tailwind')
|
||||
|
||||
mix.postCss('src/css/app.css', 'dist/css')
|
||||
.tailwind()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>My new website</title>
|
||||
<link rel="stylesheet" href="/dist/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# `npm run dev`
|
||||
|
||||
# `npm run watch`
|
||||
|
||||
# `npm run prod`
|
||||
|
||||
|
||||
---
|
||||
|
||||
# **Interaction states**
|
||||
## hover, focus, group-hover, focus-within
|
||||
|
||||
^ Start to differ from inline styles
|
||||
|
||||
---
|
||||
|
||||
# `.[state][separator][class]`
|
||||
|
||||
^ State = hover, focus, group focus, focus within
|
||||
Separator = configurable, colon by default
|
||||
Class = the same utility class that you would have used normally
|
||||
|
||||
---
|
||||
|
||||
# `.hover:text-red-500`
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<a href="#" class="text-red-500 hover:text-red-800">
|
||||
Read more
|
||||
</a>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.text-red-500 {
|
||||
color: #f56565;
|
||||
}
|
||||
|
||||
.hover\:text-red-500:hover {
|
||||
color: #f56565;
|
||||
}
|
||||
|
||||
.focus\:text-red-500:focus {
|
||||
color: #f56565;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// defaultConfig.stub.js
|
||||
|
||||
variants: {
|
||||
alignContent: ['responsive'],
|
||||
alignItems: ['responsive'],
|
||||
alignSelf: ['responsive'],
|
||||
appearance: ['responsive'],
|
||||
backgroundAttachment: ['responsive'],
|
||||
backgroundColor: ['responsive', 'hover', 'focus'],
|
||||
backgroundPosition: ['responsive'],
|
||||
backgroundRepeat: ['responsive'],
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# **Responsive**
|
||||
|
||||
^ Mobile first
|
||||
|
||||
---
|
||||
|
||||
# [fit] `.[screen][separator][class]`
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// defaultConfig.stub.js
|
||||
|
||||
screens: {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px',
|
||||
xl: '1280px',
|
||||
},
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# `md:flex`
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<div class="block md:flex">
|
||||
<div class="w-full md:w-1/2">
|
||||
Column 1
|
||||
</div>
|
||||
|
||||
<div class="w-full md:w-1/2">
|
||||
Column 2
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sm\:block {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.md\:block {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# **Keeping Things Small: <br>Controlling the File Size**
|
||||
|
||||
---
|
||||
|
||||
# Disabling unused variants <br>and core plugins
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
variants: {
|
||||
alignContent: ['responsive'],
|
||||
alignItems: ['responsive'],
|
||||
alignSelf: ['responsive'],
|
||||
appearance: ['responsive'],
|
||||
backgroundAttachment: ['responsive'],
|
||||
backgroundColor: ['responsive', 'hover', 'focus'],
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```diff
|
||||
// tailwind.config.js
|
||||
|
||||
variants: {
|
||||
alignContent: ['responsive'],
|
||||
alignItems: ['responsive'],
|
||||
- alignSelf: ['responsive'],
|
||||
+ alignSelf: false,
|
||||
appearance: ['responsive'],
|
||||
backgroundAttachment: ['responsive'],
|
||||
- backgroundColor: ['responsive', 'hover', 'focus'],
|
||||
+ backgroundColor: ['responsive'],
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Manually removing unused or unwanted classes
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
screens: {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px',
|
||||
xl: '1280px',
|
||||
},
|
||||
colors: {
|
||||
transparent: 'transparent',
|
||||
|
||||
black: '#000',
|
||||
white: '#fff',
|
||||
|
||||
gray: {
|
||||
100: '#f7fafc',
|
||||
200: '#edf2f7',
|
||||
300: '#e2e8f0',
|
||||
400: '#cbd5e0',
|
||||
500: '#a0aec0',
|
||||
600: '#718096',
|
||||
700: '#4a5568',
|
||||
800: '#2d3748',
|
||||
900: '#1a202c',
|
||||
},
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```diff
|
||||
screens: {
|
||||
sm: '640px',
|
||||
md: '768px',
|
||||
lg: '1024px',
|
||||
- xl: '1280px',
|
||||
},
|
||||
colors: {
|
||||
transparent: 'transparent',
|
||||
|
||||
black: '#000',
|
||||
white: '#fff',
|
||||
|
||||
gray: {
|
||||
100: '#f7fafc',
|
||||
- 200: '#edf2f7',
|
||||
300: '#e2e8f0',
|
||||
- 400: '#cbd5e0',
|
||||
- 500: '#a0aec0',
|
||||
600: '#718096',
|
||||
700: '#4a5568',
|
||||
- 800: '#2d3748',
|
||||
900: '#1a202c',
|
||||
},
|
||||
```
|
||||
|
||||
^ Needs to be done manually
|
||||
|
||||
---
|
||||
|
||||
# Automatically removing <br>unused classes
|
||||
|
||||
---
|
||||
|
||||
# `npm install --save-dev laravel-mix-purgecss`
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
const mix = require('laravel-mix')
|
||||
|
||||
mix.postCss('src/css/site.css', 'dist/css')
|
||||
.purgeCss({
|
||||
folders: ['templates'],
|
||||
extensions: ['html', 'php', 'twig']
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 1,3,6-9]
|
||||
|
||||
```js
|
||||
const mix = require('laravel-mix')
|
||||
|
||||
require('laravel-mix-purgecss')
|
||||
|
||||
mix.postCss('src/css/site.css', 'dist/css')
|
||||
.purgeCss({
|
||||
folders: ['templates'],
|
||||
extensions: ['html', 'php', 'twig']
|
||||
})
|
||||
```
|
||||
|
||||
^ Can be tricky using Drupal/WordPress as you don't know where the classes could be coming from, no generated output directory
|
||||
|
||||
---
|
||||
|
||||
# **Avoiding Repetition: <br>Extracting Components**
|
||||
|
||||
---
|
||||
|
||||
# Does something **justify** <br>becoming a component?
|
||||
|
||||
---
|
||||
|
||||
# Could the duplication <br>**be moved elsewhere**?
|
||||
|
||||
^ Twig partials
|
||||
Vue components
|
||||
WordPress template parts
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
{# base.html.twig #}
|
||||
|
||||
{% for item in navItems %}
|
||||
<a
|
||||
class="block py-3 px-4 text-sm text-gray-800"
|
||||
href="{{ item.url }}"
|
||||
>
|
||||
{{ item.title }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
^ Using a loop
|
||||
|
||||
---
|
||||
|
||||
```twig
|
||||
{# classes.html.twig #}
|
||||
|
||||
<h2>Adults</h2>
|
||||
|
||||
{% include 'class-list' with {
|
||||
classes: page.classes,
|
||||
type: 'adults',
|
||||
} %}
|
||||
|
||||
<h2>Kids</h2>
|
||||
|
||||
{% include 'class-list' with {
|
||||
classes: page.classes,
|
||||
type: 'kids',
|
||||
} %}
|
||||
```
|
||||
|
||||
^ Move the duplicate markup into a partial, so there's only one version
|
||||
Pass data in.
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
a.btn {
|
||||
@apply text-sm no-underline font-bold;
|
||||
@apply rounded-full inline-block px-5 py-2;
|
||||
@apply text-white bg-blue-600;
|
||||
}
|
||||
|
||||
a.btn:hover {
|
||||
@apply bg-blue-700;
|
||||
}
|
||||
```
|
||||
|
||||
^ Use utilities as mixins
|
||||
Copy classes from markup
|
||||
Still re-using the same design system and constraints as before
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
a.btn {
|
||||
font-size: 0.875rem;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
border-radius: 9999px;
|
||||
display: inline-block;
|
||||
padding-left: 1.25rem;
|
||||
padding-right: 1.25rem;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #fff;
|
||||
background-color: #3182ce;
|
||||
}
|
||||
|
||||
a.btn:hover {
|
||||
background-color: #2b6cb0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# **Customising Tailwind**
|
||||
|
||||
---
|
||||
|
||||
# `npx tailwind init`
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
plugins: [],
|
||||
variants: {}
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
[.code-highlight: 5-7]
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
colors: {
|
||||
inherit: 'inherit'
|
||||
},
|
||||
extend: {}
|
||||
},
|
||||
plugins: [],
|
||||
variants: {}
|
||||
}
|
||||
```
|
||||
|
||||
^ Overrides all colours.
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 5-9]
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
inherit: 'inherit'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [],
|
||||
variants: {}
|
||||
}
|
||||
```
|
||||
|
||||
^ Extends Tailwind's default colours
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 1,4-5]
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
module.exports = {
|
||||
prefix: '',
|
||||
important: false,
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
plugins: [],
|
||||
variants: {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# `npx tailwind init --full`
|
||||
|
||||
---
|
||||
|
||||
# **Extending Tailwind CSS <br>with Plugins**
|
||||
|
||||
---
|
||||
|
||||
# `npm install --save-dev tailwindcss-list-reset`
|
||||
|
||||
---
|
||||
|
||||
[.code-highlight: 7-9]
|
||||
|
||||
```js
|
||||
// tailwind.config.js
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
plugins: [
|
||||
require('tailwindcss-list-reset')()
|
||||
],
|
||||
variants: {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```css
|
||||
.list-reset {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js
|
||||
// index.js
|
||||
|
||||
module.exports = (variants) => ({ addUtilities }) => {
|
||||
addUtilities({
|
||||
'.list-reset': {
|
||||
listStyle: 'none',
|
||||
padding: 0
|
||||
}
|
||||
}, variants)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# **Demo**
|
||||
|
||||
---
|
||||
|
||||
## **Resources**
|
||||
|
||||
- tailwindcss.com
|
||||
- tailwindcomponents.com
|
||||
- builtwithtailwind.com
|
||||
- github.com/aniftyco/awesome-tailwind
|
||||
- youtube.com/adamwathan
|
||||
- opdavi.es/tailwind-repos
|
||||
- opdavi.es/tags/tailwind-css
|
||||
|
||||
---
|
||||
|
||||
# **Questions?**
|
||||
|
||||
---
|
||||
|
||||
# **Thanks!**
|
||||
# opdavi.es/talks/tailwind
|
||||
## _@opdavies_ <br>_oliverdavies.uk_
|
||||
|
||||
^ Find this talk at opdavi.es/talks/tailwind
|
||||
Follow me on Twitter
|
||||
oliverdavies.uk where I blog about PHP, Drupal, Symfony, automated testing, Tailwind etc.
|
||||
Subscribe to the RSS feed
|