kb.erickguedes.com
CSS3: Estilização e Layout Moderno

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.