REST es un estilo arquitectónico para sistemas distribuidos basado en hipermedia, definido por Roy Fielding en su tesis doctoral del año 2000 ("Architectural Styles and the Design of Network-based Software Architectures"). No es un protocolo ni un estándar, sino un conjunto de principios y restricciones arquitectónicas.
Un servicio web que sigue los principios REST se denomina RESTful.
REST define 6 restricciones arquitectónicas que debe cumplir un sistema para ser considerado RESTful:
Cache-Control, ETag, Expires, Last-Modified.Principio central que distingue REST de otros estilos. Se compone de cuatro subprincipios:
Un recurso es cualquier información que pueda ser nombrada: un documento, una imagen, un servicio, una colección de otros recursos, etc.
# Correcto — Sustantivos en plural
GET /usuarios
GET /usuarios/123
GET /usuarios/123/pedidos
# Incorrecto — Verbos en la URI
GET /obtenerUsuarios
POST /crearUsuario/123
-) para separar palabras./..json, .xml)./api/v1/recursos.Los métodos HTTP definen la acción a realizar sobre el recurso:
| Método | Operación CRUD | Descripción | Idempotente | Seguro |
|---|---|---|---|---|
GET |
Read | Obtiene la representación de un recurso | Sí | Sí |
POST |
Create | Crea un nuevo recurso subordinado | No | No |
PUT |
Update/Replace | Reemplaza completamente un recurso | Sí | No |
PATCH |
Update/Modify | Modifica parcialmente un recurso | No* | No |
DELETE |
Delete | Elimina un recurso | Sí | No |
HEAD |
— | Igual que GET pero sin cuerpo de respuesta | Sí | Sí |
OPTIONS |
— | Describe las opciones de comunicación del recurso | Sí | Sí |
Idempotente: Realizar la misma operación múltiples veces produce el mismo resultado que hacerla una sola vez.
Seguro: La operación no modifica el estado del servidor.
Los códigos de estado son fundamentales en REST para comunicar el resultado de una petición:
| Código | Nombre | Uso típico |
|---|---|---|
| 200 | OK | Respuesta exitosa a GET, PUT, PATCH, DELETE |
| 201 | Created | Recurso creado exitosamente (POST) |
| 204 | No Content | Exitoso sin cuerpo de respuesta (DELETE) |
| Código | Nombre | Uso típico |
|---|---|---|
| 301 | Moved Permanently | Recurso movido permanentemente |
| 304 | Not Modified | Respuesta de caché válida (no se retransmite) |
| Código | Nombre | Uso típico |
|---|---|---|
| 400 | Bad Request | Petición malformada |
| 401 | Unauthorized | Autenticación requerida |
| 403 | Forbidden | Autenticado pero sin permisos |
| 404 | Not Found | Recurso no encontrado |
| 405 | Method Not Allowed | Método HTTP no permitido para el recurso |
| 409 | Conflict | Conflicto con el estado actual del recurso |
| 422 | Unprocessable Entity | Entidad semánticamente incorrecta |
| 429 | Too Many Requests | Límite de peticiones excedido |
| Código | Nombre | Uso típico |
|---|---|---|
| 500 | Internal Server Error | Error genérico del servidor |
| 502 | Bad Gateway | El servidor upstream devolvió una respuesta inválida |
| 503 | Service Unavailable | Servidor no disponible (mantenimiento) |
# Petición
Content-Type: application/json # Tipo del cuerpo enviado
Accept: application/json # Tipo esperado en respuesta
Authorization: Bearer <token> # Autenticación
If-None-Match: "abc123" # Validación de caché (ETag)
# Respuesta
Content-Type: application/json # Tipo del cuerpo devuelto
ETag: "abc123" # Identificador de versión del recurso
Cache-Control: max-age=3600 # Política de caché
Location: /api/v1/usuarios/456 # URI del recurso creado (201 Created)
Authorization: Bearer <token>. Estructura: header.payload.signature.Hypermedia As The Engine Of Application State es el nivel más alto de madurez REST (nivel 3 del modelo de Richardson).
Permite que el cliente navegue por la API dinámicamente a través de los enlaces proporcionados por el servidor, sin necesidad de conocer las URIs de antemano.
{
"id": 123,
"nombre": "Juan García",
"estado": "activo",
"_links": {
"self": { "href": "/api/v1/usuarios/123" },
"pedidos": { "href": "/api/v1/usuarios/123/pedidos" },
"desactivar": { "href": "/api/v1/usuarios/123/desactivar", "method": "POST" }
}
}
Define 4 niveles de adopción de REST:
| Nivel | Nombre | Descripción |
|---|---|---|
| 0 | The Swamp of POX | Un único endpoint, todo mediante POST |
| 1 | Resources | URIs individuales por recurso |
| 2 | HTTP Verbs | Uso correcto de los métodos HTTP |
| 3 | Hypermedia Controls | HATEOAS — la API es autodescriptiva |
| Característica | REST | SOAP | GraphQL |
|---|---|---|---|
| Protocolo | HTTP | HTTP, SMTP, TCP... | HTTP |
| Formato | JSON, XML... | XML obligatorio | JSON |
| Contrato | OpenAPI/Swagger | WSDL | Schema GraphQL |
| Flexibilidad | Alta | Baja | Muy alta |
| Overfetching | Posible | Posible | No |
| Caché | Nativa HTTP | Compleja | Limitada |
| Curva aprendizaje | Baja | Alta | Media |
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos basado en texto, fácil de leer y escribir para humanos, y fácil de parsear y generar para máquinas.
application/json.JSON define seis tipos de valores:
"Hola mundo"
"Texto con \"comillas\" escapadas"
"Carácter Unicode: \u00E9"
".", \, /, y los de control (\n, \r, \t, \b, \f).
42
-17
3.14159
2.5e10
-1.5E-3
NaN, Infinity ni -Infinity.true
false
true o false (en minúscula).
null
{
"nombre": "María",
"edad": 28,
"activa": true
}
,.["rojo", "verde", "azul"]
[1, 2, 3, 4, 5]
[true, null, 42, "texto"]
Un documento JSON válido tiene exactamente un valor raíz (puede ser cualquier tipo, aunque habitualmente es un objeto o array):
{
"usuario": {
"id": 1001,
"nombre": "Ana López",
"email": "ana.lopez@ejemplo.es",
"activo": true,
"perfil": null,
"roles": ["admin", "editor"],
"preferencias": {
"idioma": "es",
"notificaciones": true,
"tema": "oscuro"
},
"ultimoAcceso": "2024-03-15T10:30:00Z"
}
}
{ }.[ ].undefined.JSON Schema permite definir la estructura y validación de documentos JSON. Es un vocabulario que permite anotar y validar documentos JSON.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Usuario",
"type": "object",
"required": ["id", "nombre", "email"],
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"nombre": {
"type": "string",
"minLength": 2,
"maxLength": 100
},
"email": {
"type": "string",
"format": "email"
},
"edad": {
"type": "integer",
"minimum": 0,
"maximum": 150
}
},
"additionalProperties": false
}
| Característica | JSON | XML |
|---|---|---|
| Legibilidad | Alta | Media (más verboso) |
| Tamaño | Menor | Mayor (etiquetas de cierre) |
| Tipos de datos | 6 tipos nativos | Solo texto (tipos via XSD) |
| Comentarios | No soportados | Soportados |
| Arrays | Nativos | Emulados con elementos repetidos |
| Namespaces | No | Sí |
| Validación | JSON Schema | XSD, DTD, RELAX NG |
| Transformación | jq, JSONPath | XSLT, XPath |
| Uso principal | APIs REST, configuración | Documentos, SOAP, config legacy |
// Serialización: objeto JS → string JSON
const obj = { nombre: "Juan", edad: 30 };
const json = JSON.stringify(obj);
// '{"nombre":"Juan","edad":30}'
// Con formato (indentación de 2 espacios)
const jsonFormateado = JSON.stringify(obj, null, 2);
// Con replacer (filtrar propiedades)
const jsonFiltrado = JSON.stringify(obj, ['nombre']);
// '{"nombre":"Juan"}'
// Deserialización: string JSON → objeto JS
const texto = '{"nombre":"Juan","edad":30}';
const objeto = JSON.parse(texto);
// { nombre: 'Juan', edad: 30 }
// Con reviver (transformar valores durante el parseo)
const resultado = JSON.parse(texto, (clave, valor) => {
if (clave === 'edad') return valor + 1;
return valor;
});
JSONPath es un lenguaje de consulta para JSON, análogo a XPath para XML.
$.store.book[*].author → Todos los autores
$..author → Todos los autores (recursivo)
$.store.book[0].title → Título del primer libro
$.store.book[?(@.price < 10)] → Libros con precio < 10
$.store.book[-1:] → Último libro
$.store.book[0,1] → Primero y segundo libro
@context.HTML (HyperText Markup Language) es el lenguaje de marcado estándar para crear páginas web. HTML5 es la quinta versión principal, desarrollada conjuntamente por el W3C (World Wide Web Consortium) y el WHATWG (Web Hypertext Application Technology Working Group).
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Descripción de la página">
<title>Título de la Página</title>
<link rel="stylesheet" href="estilos.css">
</head>
<body>
<!-- Contenido de la página -->
<script src="script.js" defer></script>
</body>
</html>
<head>:<!DOCTYPE html>: Declaración de tipo de documento. Obliga al navegador a usar modo estándar.<meta charset="UTF-8">: Define la codificación de caracteres.<meta name="viewport">: Fundamental para diseño responsive.<title>: Título que aparece en la pestaña del navegador y en los resultados de búsqueda.HTML5 introdujo un conjunto de elementos semánticos que describen el significado del contenido, mejorando la accesibilidad y el SEO:
<header> <!-- Encabezado del sitio o sección -->
<nav> <!-- Navegación principal -->
<main> <!-- Contenido principal (único por página) -->
<article> <!-- Contenido independiente y reutilizable -->
<section> <!-- Sección temática del documento -->
<aside> <!-- Contenido tangencialmente relacionado (sidebar) -->
<footer> <!-- Pie de página -->
<body>
<header>
<nav>
<ul>
<li><a href="/inicio">Inicio</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h1>Título del artículo</h1>
<time datetime="2024-03-15">15 de marzo de 2024</time>
</header>
<section>
<h2>Primera sección</h2>
<p>Contenido...</p>
</section>
<footer>
<p>Autor: <address>Juan García</address></p>
</footer>
</article>
<aside>
<h2>Artículos relacionados</h2>
</aside>
</main>
<footer>
<p>© 2024 Mi Sitio Web</p>
</footer>
</body>
| Elemento | Descripción |
|---|---|
<figure> |
Contenido independiente (imagen, diagrama, código) |
<figcaption> |
Leyenda para <figure> |
<time> |
Fecha u hora (atributo datetime en formato ISO) |
<mark> |
Texto resaltado/marcado |
<details> |
Widget de divulgación (expand/collapse) |
<summary> |
Resumen visible de <details> |
<dialog> |
Cuadro de diálogo o ventana modal |
<meter> |
Medida escalar dentro de un rango conocido |
<progress> |
Progreso de una tarea |
<output> |
Resultado de un cálculo |
HTML5 potencia enormemente los formularios con nuevos tipos de <input> y atributos de validación:
<input type="email"> <!-- Valida formato de email -->
<input type="url"> <!-- Valida formato de URL -->
<input type="tel"> <!-- Campo para teléfono -->
<input type="number" min="0" max="100" step="5">
<input type="range" min="0" max="100">
<input type="date"> <!-- Selector de fecha -->
<input type="datetime-local"> <!-- Fecha y hora -->
<input type="month"> <!-- Mes y año -->
<input type="week"> <!-- Semana y año -->
<input type="time"> <!-- Hora -->
<input type="color"> <!-- Selector de color -->
<input type="search"> <!-- Campo de búsqueda -->
<input required> <!-- Campo obligatorio -->
<input minlength="5" maxlength="20"> <!-- Longitud mínima y máxima -->
<input min="0" max="100"> <!-- Valor mínimo y máximo -->
<input pattern="[A-Za-z]{3,}"> <!-- Validación con regex -->
<input autocomplete="email"> <!-- Autocompletado -->
<input placeholder="Introduce tu email"> <!-- Texto de ayuda -->
<input autofocus> <!-- Foco automático -->
<input novalidate> <!-- Desactivar validación -->
<datalist id="opciones"> <!-- Lista de sugerencias para input -->
<option value="Madrid">
<option value="Barcelona">
</datalist>
<input list="opciones">
<fieldset> <!-- Agrupa controles relacionados -->
<legend>Datos personales</legend>
</fieldset>
HTML5 incluye numerosas APIs JavaScript que amplían las capacidades del navegador:
<canvas id="miCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('miCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#FF0000';
ctx.fillRect(10, 10, 150, 100);
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.stroke();
</script>
// localStorage — persiste sin expiración
localStorage.setItem('clave', 'valor');
localStorage.getItem('clave');
localStorage.removeItem('clave');
localStorage.clear();
// sessionStorage — persiste solo mientras dure la sesión
sessionStorage.setItem('clave', 'valor');
sessionStorage.getItem('clave');
Diferencia con cookies: mayor capacidad (~5-10 MB), no se envían al servidor automáticamente, no tienen
expires.
navigator.geolocation.getCurrentPosition(
(posicion) => {
const lat = posicion.coords.latitude;
const lon = posicion.coords.longitude;
},
(error) => console.error(error),
{ enableHighAccuracy: true, timeout: 5000 }
);
<div draggable="true" ondragstart="drag(event)" id="elemento">Arrastra</div>
<div ondragover="allowDrop(event)" ondrop="drop(event)">Zona de destino</div>
// Hilo de trabajo (worker.js)
self.onmessage = function(e) {
const resultado = calcularAlgoComplejo(e.data);
self.postMessage(resultado);
};
// Hilo principal
const worker = new Worker('worker.js');
worker.postMessage(datos);
worker.onmessage = (e) => console.log(e.data);
history.pushState({ pagina: 1 }, 'Título', '/nueva-url');
history.replaceState({ pagina: 2 }, 'Título', '/otra-url');
history.back();
history.forward();
history.go(-2);
const ws = new WebSocket('wss://servidor.ejemplo.com/socket');
ws.onopen = () => ws.send('Hola servidor');
ws.onmessage = (e) => console.log('Recibido:', e.data);
ws.onerror = (e) => console.error(e);
ws.onclose = () => console.log('Conexión cerrada');
const eventSource = new EventSource('/api/eventos');
eventSource.onmessage = (e) => console.log(e.data);
eventSource.addEventListener('actualizacion', (e) => { /* ... */ });
<!-- Audio -->
<audio controls autoplay loop muted preload="auto">
<source src="audio.mp3" type="audio/mpeg">
<source src="audio.ogg" type="audio/ogg">
Tu navegador no soporta el elemento audio.
</audio>
<!-- Vídeo -->
<video controls width="800" height="450" poster="thumbnail.jpg" preload="metadata">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<track kind="subtitles" src="subs_es.vtt" srclang="es" label="Español" default>
Tu navegador no soporta el elemento video.
</video>
WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) es una especificación del W3C que define formas de hacer el contenido web más accesible.
<!-- Roles ARIA -->
<div role="button" tabindex="0" aria-pressed="false">Botón personalizado</div>
<nav role="navigation" aria-label="Menú principal">...</nav>
<!-- Estados y propiedades ARIA -->
<input type="text" aria-required="true" aria-invalid="false">
<div aria-live="polite" aria-atomic="true">Contenido dinámico</div>
<button aria-expanded="false" aria-controls="menu-id">Menú</button>
<ul id="menu-id" aria-hidden="true">...</ul>
<!-- Landmark roles -->
<header role="banner">
<nav role="navigation">
<main role="main">
<footer role="contentinfo">
<aside role="complementary">
<!-- SEO básico -->
<meta name="description" content="Descripción de la página (150-160 caracteres)">
<meta name="keywords" content="palabra1, palabra2, palabra3">
<meta name="robots" content="index, follow">
<meta name="author" content="Nombre del autor">
<!-- Open Graph (redes sociales) -->
<meta property="og:title" content="Título para redes sociales">
<meta property="og:description" content="Descripción para redes sociales">
<meta property="og:image" content="https://ejemplo.com/imagen.jpg">
<meta property="og:url" content="https://ejemplo.com/pagina">
<meta property="og:type" content="website">
<!-- Twitter Cards -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@usuario">
<!-- Responsive -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
CSS (Cascading Style Sheets) es un lenguaje de hojas de estilo utilizado para describir la presentación de un documento HTML. CSS3 es la versión más reciente, organizada en módulos independientes, cada uno en su propia especificación, en constante evolución.
* { /* Selector universal */ }
div { /* Selector de tipo/elemento */ }
.clase { /* Selector de clase */ }
#id { /* Selector de ID */ }
div, p { /* Selector de lista/agrupación */ }
div p { /* Descendiente (cualquier nivel) */ }
div > p { /* Hijo directo */ }
div + p { /* Hermano adyacente (inmediatamente después) */ }
div ~ p { /* Hermanos generales (todos los siguientes) */ }
a:hover { /* Al pasar el cursor */ }
a:focus { /* Al recibir foco */ }
a:visited { /* Enlace visitado */ }
a:active { /* Al hacer clic */ }
p:first-child { /* Primer hijo de su padre */ }
p:last-child { /* Último hijo de su padre */ }
p:nth-child(2n) { /* Hijos pares (even) */ }
p:nth-child(2n+1){ /* Hijos impares (odd) */ }
p:not(.excluido) { /* Negación */ }
input:checked { /* Checkbox/radio marcado */ }
input:disabled { /* Campo deshabilitado */ }
input:valid { /* Campo con validación correcta */ }
input:invalid { /* Campo con validación incorrecta */ }
:root { /* Elemento raíz (html) — para variables */ }
p::first-line { /* Primera línea del párrafo */ }
p::first-letter { /* Primera letra del párrafo */ }
div::before { /* Inserta contenido antes del elemento */ }
div::after { /* Inserta contenido después del elemento */ }
::selection { /* Texto seleccionado por el usuario */ }
::placeholder { /* Placeholder de inputs */ }
[href] { /* Elementos con atributo href */ }
[type="text"] { /* Atributo con valor exacto */ }
[class~="btn"] { /* Atributo con valor en lista */ }
[lang|="es"] { /* Atributo igual o con prefijo "es-" */ }
[href^="https"] { /* Atributo comienza con */ }
[href$=".pdf"] { /* Atributo termina con */ }
[href*="ejemplo"] { /* Atributo contiene */ }
Todo elemento HTML es representado como una caja rectangular compuesta por:
+----------------------------------+
| MARGIN |
| +----------------------------+ |
| | BORDER | |
| | +----------------------+ | |
| | | PADDING | | |
| | | +----------------+ | | |
| | | | CONTENT | | | |
| | | +----------------+ | | |
| | +----------------------+ | |
| +----------------------------+ |
+----------------------------------+
/* box-sizing controla cómo se calcula el tamaño */
* {
box-sizing: border-box; /* width/height incluyen padding y border */
}
/* vs */
* {
box-sizing: content-box; /* Valor por defecto: width/height solo contenido */
}
CSS Flexible Box Layout (Flexbox) es un modelo de diseño unidimensional para distribuir espacio entre elementos en una interfaz y mejorar las capacidades de alineación.
.contenedor {
display: flex; /* o inline-flex */
flex-direction: row; /* row | row-reverse | column | column-reverse */
flex-wrap: nowrap; /* nowrap | wrap | wrap-reverse */
flex-flow: row nowrap; /* shorthand de flex-direction y flex-wrap */
justify-content: flex-start; /* Alineación en eje principal */
/* flex-start | flex-end | center | space-between | space-around | space-evenly */
align-items: stretch; /* Alineación en eje cruzado */
/* flex-start | flex-end | center | stretch | baseline */
align-content: flex-start; /* Alineación de líneas en eje cruzado */
gap: 1rem; /* Espacio entre elementos (row-gap column-gap) */
}
.elemento {
flex-grow: 0; /* Factor de crecimiento (por defecto 0) */
flex-shrink: 1; /* Factor de reducción (por defecto 1) */
flex-basis: auto;/* Tamaño base antes de distribuir espacio */
flex: 1; /* Shorthand: flex-grow flex-shrink flex-basis */
/* flex: 1 = flex: 1 1 0% */
align-self: auto;/* Sobreescribe align-items para este elemento */
order: 0; /* Orden de aparición */
}
CSS Grid Layout es un sistema de diseño bidimensional que permite crear layouts de filas y columnas simultáneamente.
.contenedor {
display: grid;
/* Definir columnas */
grid-template-columns: 200px 1fr 1fr; /* Tamaños fijos y fraccionados */
grid-template-columns: repeat(3, 1fr); /* 3 columnas iguales */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* Responsive */
/* Definir filas */
grid-template-rows: auto 1fr auto;
/* Áreas nombradas */
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
/* Espaciado */
gap: 1rem; /* row-gap y column-gap */
row-gap: 1rem;
column-gap: 2rem;
/* Alineación del grid en su contenedor */
justify-content: start; /* start | end | center | stretch | space-around | space-between */
align-content: start;
/* Alineación de los elementos dentro de su celda */
justify-items: stretch; /* start | end | center | stretch */
align-items: stretch;
}
.elemento {
/* Posicionamiento por líneas */
grid-column: 1 / 3; /* Desde línea 1 hasta línea 3 */
grid-column: 1 / span 2; /* Desde línea 1, ocupa 2 columnas */
grid-row: 2 / 4;
/* Posicionamiento por áreas nombradas */
grid-area: header; /* Nombre del área definida en el contenedor */
/* Alineación individual */
justify-self: center;
align-self: end;
}
Introducidas en CSS3, las variables CSS permiten reutilizar valores a lo largo de la hoja de estilos:
/* Declaración (en :root para acceso global) */
:root {
--color-primario: #3498db;
--color-secundario: #2ecc71;
--fuente-principal: 'Georgia', serif;
--espaciado-base: 1rem;
--radio-borde: 8px;
--sombra: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Uso */
.boton {
background-color: var(--color-primario);
font-family: var(--fuente-principal);
padding: var(--espaciado-base);
border-radius: var(--radio-borde);
box-shadow: var(--sombra);
}
/* Con valor de fallback */
.elemento {
color: var(--color-texto, #333);
}
/* Sobreescribir en contexto local */
.tema-oscuro {
--color-primario: #2980b9;
--color-fondo: #1a1a2e;
}
/* Manipulación con JavaScript */
document.documentElement.style.setProperty('--color-primario', '#ff0000');
const valor = getComputedStyle(document.documentElement).getPropertyValue('--color-primario');
.elemento {
/* 2D */
transform: translate(50px, 100px);
transform: rotate(45deg);
transform: scale(1.5);
transform: scale(1.5, 0.8);
transform: skew(15deg, 5deg);
/* Múltiples transformaciones (orden importa) */
transform: rotate(45deg) scale(1.2) translate(10px, 20px);
/* 3D */
transform: rotateX(45deg) rotateY(30deg) translateZ(100px);
transform: perspective(500px) rotateY(45deg);
/* Punto de origen de la transformación */
transform-origin: center center;
transform-origin: top left;
transform-origin: 50% 50%;
/* Contexto 3D para hijos */
transform-style: preserve-3d;
perspective: 1000px;
}
.boton {
background-color: blue;
/* Shorthand */
transition: background-color 0.3s ease-in-out;
/* Múltiples propiedades */
transition: background-color 0.3s ease, transform 0.2s linear, opacity 0.4s;
/* Todas las propiedades */
transition: all 0.3s ease;
/* Con retardo */
transition: background-color 0.3s ease 0.1s;
}
.boton:hover {
background-color: darkblue;
transform: scale(1.05);
}
linear: Velocidad constante.ease (por defecto): Empieza rápido, termina lento.ease-in: Empieza lento.ease-out: Termina lento.ease-in-out: Empieza y termina lento.cubic-bezier(x1, y1, x2, y2): Curva personalizada.steps(n, start|end): Animación escalonada./* Definición de keyframes */
@keyframes deslizarEntrada {
from {
opacity: 0;
transform: translateX(-100px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes latido {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
/* Aplicación de la animación */
.elemento {
animation-name: deslizarEntrada;
animation-duration: 0.5s;
animation-timing-function: ease-out;
animation-delay: 0.2s;
animation-iteration-count: 1; /* número o infinite */
animation-direction: normal; /* normal | reverse | alternate | alternate-reverse */
animation-fill-mode: forwards; /* none | forwards | backwards | both */
animation-play-state: running; /* running | paused */
/* Shorthand */
animation: deslizarEntrada 0.5s ease-out 0.2s 1 normal forwards;
/* Múltiples animaciones */
animation: deslizarEntrada 0.5s ease, latido 1s ease infinite;
}
/* Mobile-first approach (recomendado) */
/* Estilos base para móvil */
.contenedor {
width: 100%;
padding: 1rem;
}
/* Tablet (≥ 768px) */
@media (min-width: 768px) {
.contenedor {
padding: 2rem;
}
}
/* Desktop (≥ 1024px) */
@media (min-width: 1024px) {
.contenedor {
max-width: 1200px;
margin: 0 auto;
padding: 3rem;
}
}
/* Pantallas de alta densidad */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.logo {
background-image: url('logo@2x.png');
}
}
/* Orientación */
@media (orientation: landscape) { /* ... */ }
@media (orientation: portrait) { /* ... */ }
/* Preferencias del sistema */
@media (prefers-color-scheme: dark) {
:root {
--color-fondo: #1a1a2e;
--color-texto: #e0e0e0;
}
}
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
/* Impresión */
@media print {
nav, aside, footer { display: none; }
body { font-size: 12pt; }
}
color: rgb(255, 0, 0);
color: rgba(255, 0, 0, 0.5);
color: hsl(0, 100%, 50%);
color: hsla(0, 100%, 50%, 0.5);
color: oklch(0.7 0.2 30); /* Espacio de color perceptualmente uniforme */
width: calc(100% - 2rem);
width: calc(50% + 20px);
font-size: calc(1rem + 1vw); /* Tipografía fluida */
/* Funciones min(), max(), clamp() */
width: min(100%, 600px); /* El menor de los valores */
width: max(300px, 50%); /* El mayor de los valores */
font-size: clamp(1rem, 2.5vw, 2rem); /* min, preferido, max */
/* Gradiente lineal */
background: linear-gradient(to right, #ff6b6b, #feca57);
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
/* Gradiente radial */
background: radial-gradient(circle at center, #ff6b6b, #feca57);
background: radial-gradient(ellipse 80% 50% at 50% 50%, #ff6b6b, transparent);
/* Gradiente cónico */
background: conic-gradient(from 0deg, red, yellow, green, blue, red);
/* Gradiente repetido */
background: repeating-linear-gradient(45deg, #fff 0, #fff 10px, #eee 10px, #eee 20px);
!important del autor!important del usuario| Selector | Especificidad |
|---|---|
Elementos y pseudoelementos (div, ::before) |
(0, 0, 1) |
Clases, atributos, pseudoclases (.clase, [attr], :hover) |
(0, 1, 0) |
IDs (#id) |
(1, 0, 0) |
Estilos en línea (style="") |
(1, 0, 0, 0) |
!important |
Sobreescribe todo |
Se calcula como (IDs, Clases, Elementos). Mayor número = mayor especificidad.
/* Especificidad: 0,0,1 */
p { color: blue; }
/* Especificidad: 0,1,1 */
p.destacado { color: green; }
/* Especificidad: 1,1,1 */
#main p.destacado { color: red; } /* Gana */
| Unidad | Equivalencia |
|---|---|
px |
Píxel (relativo al dispositivo) |
pt |
Punto tipográfico (1pt = 1/72in) |
cm |
Centímetro |
mm |
Milímetro |
in |
Pulgada (1in = 96px) |
| Unidad | Relativo a... |
|---|---|
em |
Tamaño de fuente del elemento padre |
rem |
Tamaño de fuente del elemento raíz (html) |
% |
Tamaño del elemento padre |
vw |
1% del ancho del viewport |
vh |
1% del alto del viewport |
vmin |
1% del lado menor del viewport |
vmax |
1% del lado mayor del viewport |
ch |
Ancho del carácter "0" en la fuente actual |
ex |
Altura de la letra "x" en la fuente actual |
lh |
Altura de línea del elemento |
Aunque no son CSS puro, son ampliamente utilizados:
Características comunes:
// SCSS - Variables
$color-primario: #3498db;
$fuente-base: 16px;
// Anidamiento
nav {
background: $color-primario;
ul {
list-style: none;
li {
display: inline-block;
&:hover { /* & referencia al selector padre */
background: darken($color-primario, 10%);
}
}
}
}
// Mixin
@mixin flex-centro {
display: flex;
justify-content: center;
align-items: center;
}
.contenedor {
@include flex-centro;
}
/* Bloque: componente independiente */
.card { }
/* Elemento: parte del bloque */
.card__title { }
.card__image { }
.card__body { }
/* Modificador: variación del bloque o elemento */
.card--destacado { }
.card__title--grande { }
Separar estructura de apariencia, y contenedor de contenido.
Categorías: Base, Layout, Module, State, Theme.
Clases de utilidad de propósito único: flex, mt-4, text-center, bg-blue-500.
Documento generado para preparación de oposiciones. Última actualización: 2024.