Pré-processadores e TailwindCSS
Aula 6 de 7
SASS/SCSS
SASS é o pré-processador CSS mais maduro, adicionando variáveis, aninhamento, mixins e funções.
Variáveis e Nesting
// Variáveis SCSS
$primary: #3498db;
$secondary: #2ecc71;
$font-stack: 'Inter', system-ui, sans-serif;
$border-radius: 8px;
$spacing-unit: 8px;
// Nesting (aninhamento)
.card {
background: white;
border-radius: $border-radius;
padding: $spacing-unit * 2;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
// & referencia o pai
&-header {
border-bottom: 1px solid #eee;
padding-bottom: $spacing-unit;
h2 {
margin: 0;
color: $primary;
}
}
&:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
}
Mixins e Includes
// Mixin com parâmetros
@mixin respond-to($breakpoint) {
@if $breakpoint == 'sm' {
@media (min-width: 640px) { @content; }
} @else if $breakpoint == 'md' {
@media (min-width: 768px) { @content; }
} @else if $breakpoint == 'lg' {
@media (min-width: 1024px) { @content; }
}
}
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin text-truncate($lines: 1) {
@if $lines == 1 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} @else {
display: -webkit-box;
-webkit-line-clamp: $lines;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
// Uso dos mixins
.hero {
@include flex-center;
min-height: 60vh;
}
.title {
@include text-truncate(2);
font-size: 2rem;
}
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
@include respond-to('md') {
grid-template-columns: repeat(2, 1fr);
}
@include respond-to('sm') {
grid-template-columns: 1fr;
}
}
Extends e Functions
// %placeholder - não gera CSS até ser extendido
%card-base {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
.card-primary {
@extend %card-base;
border-left: 4px solid $primary;
}
.card-danger {
@extend %card-base;
border-left: 4px solid #e74c3c;
}
// Funções customizadas
@function spacing($multiplier) {
@return $spacing-unit * $multiplier;
}
@function rem($px) {
@return $px / 16px * 1rem;
}
.container {
padding: spacing(3); // 24px
font-size: rem(18px); // 1.125rem
}
TailwindCSS
Utility-First
<!-- Abordagem utility-first -->
<div class="flex items-center justify-between p-6 bg-white rounded-xl shadow-md hover:shadow-lg transition-shadow">
<h2 class="text-xl font-bold text-gray-800">Título</h2>
<button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
Clique
</button>
</div>
Configuração
// tailwind.config.js
module.exports = {
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
700: '#1d4ed8',
},
danger: '#e74c3c',
},
spacing: {
'18': '4.5rem',
'88': '22rem',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
animation: {
'fade-in': 'fadeIn 0.3s ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0', transform: 'translateY(10px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
},
},
},
plugins: [],
};
@apply
/* Usando @apply para extrair componentes */
.btn {
@apply px-6 py-3 rounded-lg font-medium transition-all duration-200 inline-flex items-center gap-2;
}
.btn-primary {
@apply btn bg-blue-500 text-white hover:bg-blue-600 active:bg-blue-700;
}
.btn-secondary {
@apply btn bg-gray-200 text-gray-800 hover:bg-gray-300;
}
.card {
@apply bg-white rounded-xl shadow-md p-6 border border-gray-100;
}
CSS Modules
/* Componente.module.css */
.card {
background: white;
border-radius: 12px;
}
.title {
font-size: 1.5rem;
color: #333;
}
import styles from './Componente.module.css';
function Card() {
return (
<div className={styles.card}>
<h2 className={styles.title}>Título</h2>
</div>
);
}
Lab: Componente com SCSS + Tailwind
Crie um card de produto usando SCSS com mixins e, em paralelo, a versão com TailwindCSS. Compare as abordagens.
# Compilar SCSS
npm install -g sass
sass --watch src/styles:dist/styles
# Iniciar Tailwind no projeto
npm install -D tailwindcss
npx tailwindcss init
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
Pré-processadores e utility-first não são concorrentes — cada abordagem resolve problemas diferentes. Escolha a ferramenta certa para o contexto do projeto.