Aunque trabajamos principalmente en el backend, todo desarrollador Laravel necesita entender HTML y CSS. Son la base sobre la que construimos nuestras vistas y componentes Blade.
Este artículo cubre los fundamentos que debes dominar para escribir componentes Blade sólidos.
Qué es HTML
HTML (HyperText Markup Language) es el lenguaje que define la estructura y el contenido de una página web. Funciona mediante etiquetas que envuelven el contenido.
<p>Esto es un párrafo</p>Las etiquetas tienen un nombre entre signos <>. La mayoría necesitan una etiqueta de apertura y una de cierre con /:
<etiqueta>contenido</etiqueta>Algunas etiquetas son auto-cerrantes, no necesitan cierre:
<img src="foto.jpg" alt="Descripción">
<input type="text" name="email">
<br>
<hr>Estructura básica de un documento HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Título de la página</title>
</head>
<body>
<!-- Aquí va el contenido visible -->
</body>
</html>El <head> contiene metadatos, el <body> contiene lo que ve el usuario.
Etiquetas esenciales
Texto:
<h1>Título principal</h1>
<h2>Subtítulo</h2>
<h3>Título de sección</h3>
<!-- h4, h5, h6 para niveles menores -->
<p>Párrafo de texto normal.</p>
<strong>Texto importante (negrita)</strong>
<em>Texto enfatizado (cursiva)</em>
<a href="https://ejemplo.com">Enlace</a>Listas:
<!-- Lista sin orden -->
<ul>
<li>Elemento 1</li>
<li>Elemento 2</li>
</ul>
<!-- Lista ordenada -->
<ol>
<li>Primero</li>
<li>Segundo</li>
</ol>Contenedores:
<div>Contenedor genérico (bloque)</div>
<span>Contenedor genérico (en línea)</span>Semánticos:
<header>Cabecera de página o sección</header>
<nav>Navegación</nav>
<main>Contenido principal (uno por página)</main>
<article>Contenido independiente</article>
<section>Sección temática</section>
<aside>Contenido secundario (sidebar)</aside>
<footer>Pie de página o sección</footer>Formularios:
<form action="/enviar" method="POST">
<label for="email">Email</label>
<input type="email" id="email" name="email">
<label for="mensaje">Mensaje</label>
<textarea id="mensaje" name="mensaje"></textarea>
<select name="pais">
<option value="es">España</option>
<option value="mx">México</option>
</select>
<button type="submit">Enviar</button>
</form>Imágenes:
<img src="ruta/imagen.jpg" alt="Descripción de la imagen">Atributos
Las etiquetas pueden tener atributos que añaden información o comportamiento:
<a href="https://ejemplo.com" target="_blank" title="Ir a ejemplo">
Enlace
</a>
<input
type="email"
name="email"
id="email"
placeholder="[email protected]"
required
>Los atributos más comunes son id (identificador único), class (clases CSS) y style (estilos en línea).
Qué es CSS
CSS (Cascading Style Sheets) define la apariencia visual del HTML: colores, tamaños, espaciados, posiciones, etc.
Sintaxis básica
selector {
propiedad: valor;
otra-propiedad: otro-valor;
}Ejemplo:
p {
color: blue;
font-size: 16px;
}Selectores principales
/* Por etiqueta */
p { color: black; }
h1 { font-size: 2rem; }
/* Por clase (con punto) */
.destacado { background: yellow; }
.boton { padding: 10px 20px; }
/* Por ID (con almohadilla) - evitar, poco reutilizable */
#header { height: 60px; }
/* Combinados */
p.intro { font-weight: bold; } /* p con clase intro */
.card .title { font-size: 1.2rem; } /* .title dentro de .card */
/* Estados */
a:hover { color: red; } /* Al pasar el ratón */
input:focus { border-color: blue; } /* Al enfocar */Propiedades esenciales
Texto:
.texto {
color: #333; /* Color del texto */
font-size: 16px; /* Tamaño */
font-weight: bold; /* Grosor: normal, bold, 100-900 */
font-family: Arial, sans-serif; /* Tipografía */
text-align: center; /* Alineación: left, center, right */
line-height: 1.5; /* Altura de línea */
}Fondo:
.caja {
background-color: #f5f5f5;
background-image: url('imagen.jpg');
background-size: cover;
background-position: center;
}Espaciado:
.elemento {
/* Margen: espacio exterior */
margin: 20px; /* Todos los lados */
margin: 10px 20px; /* Vertical | Horizontal */
margin: 10px 20px 15px 5px;/* Top Right Bottom Left */
margin-top: 10px; /* Individual */
/* Padding: espacio interior */
padding: 20px;
padding: 10px 20px;
}Dimensiones:
.caja {
width: 100%; /* Ancho */
max-width: 600px; /* Ancho máximo */
min-width: 300px; /* Ancho mínimo */
height: 200px; /* Alto */
}Bordes:
.caja {
border: 1px solid #ccc; /* Grosor estilo color */
border-radius: 8px; /* Esquinas redondeadas */
border-bottom: 2px solid blue; /* Solo un lado */
}Display:
.bloque { display: block; } /* Ocupa toda la línea */
.linea { display: inline; } /* En línea con otros */
.flex { display: flex; } /* Contenedor flexible */
.grid { display: grid; } /* Contenedor en cuadrícula */
.oculto { display: none; } /* Invisible */Unidades
.elemento {
/* Absolutas */
width: 200px; /* Píxeles */
/* Relativas */
width: 50%; /* Porcentaje del padre */
font-size: 1rem; /* Relativo al root (16px por defecto) */
font-size: 1.5em; /* Relativo al padre */
width: 100vw; /* Viewport width */
height: 100vh; /* Viewport height */
}Cómo incluir CSS
Archivo externo (recomendado):
<head>
<link rel="stylesheet" href="estilos.css">
</head>En el documento:
<head>
<style>
p { color: blue; }
</style>
</head>En línea (evitar):
<p style="color: blue;">Texto</p>Componentes Blade con HTML y CSS
Ahora que conoces las bases, veamos cómo aplicarlas en componentes Blade.
Layout base
{{-- resources/views/components/layouts/app.blade.php --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ $title ?? config('app.name') }}</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<header class="header">
<nav class="nav">
{{ $navigation ?? '' }}
</nav>
</header>
<main class="main">
{{ $slot }}
</main>
<footer class="footer">
{{ $footer ?? '' }}
</footer>
</body>
</html>/* resources/css/app.css */
.header {
background-color: #1f2937;
padding: 1rem;
}
.nav {
max-width: 1200px;
margin: 0 auto;
}
.main {
max-width: 1200px;
margin: 0 auto;
padding: 2rem 1rem;
}
.footer {
background-color: #f3f4f6;
padding: 2rem 1rem;
text-align: center;
}Componente botón
{{-- resources/views/components/button.blade.php --}}
@props([
'type' => 'button',
'variant' => 'primary',
])
<button
type="{{ $type }}"
{{ $attributes->class(['btn', "btn-{$variant}"]) }}
>
{{ $slot }}
</button>.btn {
display: inline-block;
padding: 0.5rem 1rem;
font-size: 1rem;
font-weight: 500;
border: none;
border-radius: 0.375rem;
cursor: pointer;
}
.btn-primary {
background-color: #3b82f6;
color: white;
}
.btn-primary:hover {
background-color: #2563eb;
}
.btn-secondary {
background-color: #6b7280;
color: white;
}
.btn-secondary:hover {
background-color: #4b5563;
}
.btn-danger {
background-color: #ef4444;
color: white;
}
.btn-danger:hover {
background-color: #dc2626;
}Uso:
<x-button>Guardar</x-button>
<x-button variant="secondary">Cancelar</x-button>
<x-button type="submit" variant="danger">Eliminar</x-button>Componente input
{{-- resources/views/components/input.blade.php --}}
@props([
'name',
'label',
'type' => 'text',
'value' => null,
])
@php
$id = $name;
$hasError = $errors->has($name);
@endphp
<div class="form-group">
<label class="form-label" for="{{ $id }}">
{{ $label }}
</label>
<input
type="{{ $type }}"
id="{{ $id }}"
name="{{ $name }}"
value="{{ old($name, $value) }}"
{{ $attributes->class(['form-input', 'form-input-error' => $hasError]) }}
>
@error($name)
<p class="form-error">{{ $message }}</p>
@enderror
</div>.form-group {
margin-bottom: 1rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
color: #374151;
}
.form-input {
width: 100%;
padding: 0.5rem 0.75rem;
font-size: 1rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
}
.form-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.form-input-error {
border-color: #ef4444;
}
.form-error {
margin-top: 0.25rem;
font-size: 0.875rem;
color: #ef4444;
}Uso:
<x-input name="email" type="email" label="Correo electrónico" required />
<x-input name="password" type="password" label="Contraseña" />Componente card
{{-- resources/views/components/card.blade.php --}}
@props([
'title' => null,
])
<article {{ $attributes->class(['card']) }}>
@if($title)
<header class="card-header">
<h3 class="card-title">{{ $title }}</h3>
</header>
@endif
<div class="card-body">
{{ $slot }}
</div>
@isset($footer)
<footer class="card-footer">
{{ $footer }}
</footer>
@endisset
</article>.card {
background-color: white;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
}
.card-header {
padding: 1rem;
border-bottom: 1px solid #e5e7eb;
}
.card-title {
margin: 0;
font-size: 1.125rem;
font-weight: 600;
}
.card-body {
padding: 1rem;
}
.card-footer {
padding: 1rem;
background-color: #f9fafb;
border-top: 1px solid #e5e7eb;
}Uso:
<x-card title="Usuario">
<p>Información del usuario...</p>
<x-slot:footer>
<x-button>Editar</x-button>
</x-slot:footer>
</x-card>Componente alerta
{{-- resources/views/components/alert.blade.php --}}
@props([
'type' => 'info',
])
<div {{ $attributes->class(['alert', "alert-{$type}"]) }} role="alert">
{{ $slot }}
</div>.alert {
padding: 1rem;
border-radius: 0.375rem;
margin-bottom: 1rem;
}
.alert-info {
background-color: #eff6ff;
color: #1e40af;
border: 1px solid #bfdbfe;
}
.alert-success {
background-color: #f0fdf4;
color: #166534;
border: 1px solid #bbf7d0;
}
.alert-warning {
background-color: #fffbeb;
color: #92400e;
border: 1px solid #fde68a;
}
.alert-error {
background-color: #fef2f2;
color: #dc2626;
border: 1px solid #fecaca;
}Uso:
<x-alert type="success">Guardado correctamente.</x-alert>
<x-alert type="error">Ha ocurrido un error.</x-alert>Siguiente paso: domina Blade
Una vez tienes claros los fundamentos de HTML y CSS, el siguiente paso es dominar Blade, el motor de plantillas de Laravel. Directivas, componentes, slots, stacks... todo lo que necesitas para construir vistas potentes y reutilizables.
👉 Laravel Blade: guía completa del motor de plantillas de Laravel
Conclusión
HTML define la estructura, CSS define la apariencia. Con estos fundamentos y la potencia de los componentes Blade puedes construir interfaces consistentes y mantenibles sin necesidad de ser un experto en frontend.
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción