Para enlazar CSS y JavaScript a HTML, añade una etiqueta link para la hoja de estilos y una etiqueta script para el archivo JavaScript. Una estructura sencilla es colocar ambos en head y utilizar defer en el script externo.
<link rel="stylesheet" href="css/estilos.css">
<script src="js/app.js" defer></script>HTML organiza el contenido, CSS controla su presentación y JavaScript añade comportamientos. Separar los tres archivos facilita encontrar errores y reutilizar el código.
Prepara las carpetas del proyecto
Crea un archivo index.html, una carpeta css con estilos.css y otra js con app.js. Los nombres de las carpetas deben coincidir con los que escribas en las rutas.
Puedes hacerlo desde Visual Studio Code. Verifica que tu sistema no haya guardado por error nombres como index.html.txt.
Ejemplo completo con tres archivos
1. El documento index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Mi primer proyecto conectado</title>
<link rel="stylesheet" href="css/estilos.css">
<script src="js/app.js" defer></script>
</head>
<body>
<main>
<h1>HTML, CSS y JavaScript</h1>
<p id="mensaje" aria-live="polite">Pulsa el botón para probar el script.</p>
<button type="button" id="saludar">Probar JavaScript</button>
</main>
</body>
</html>2. La hoja css/estilos.css
body {
margin: 0;
padding: 32px 16px;
font-family: system-ui, sans-serif;
background: #eef6ff;
color: #0f172a;
}
main { max-width: 760px; margin-inline: auto; }
button {
padding: 12px 20px;
border: 0;
border-radius: 8px;
background: #1d4ed8;
color: #fff;
cursor: pointer;
}
button:focus-visible { outline: 3px solid #0f172a; outline-offset: 4px; }3. El archivo js/app.js
const boton = document.querySelector('#saludar');
const mensaje = document.querySelector('#mensaje');
boton.addEventListener('click', () => {
mensaje.textContent = 'Los tres archivos están conectados.';
});Abre el HTML. Si ves el fondo azul claro, CSS está cargando. Si el texto cambia al pulsar el botón, JavaScript también está conectado. Son dos comprobaciones distintas: que funcione uno no garantiza que funcione el otro.
Qué hace defer en un script
En scripts clásicos externos, defer permite descargar el archivo mientras se analiza el documento y ejecutarlo cuando termina el análisis del HTML, antes de DOMContentLoaded. Los scripts diferidos conservan su orden en el documento.
async ejecuta el script cuando está disponible y no garantiza ese mismo orden. No lo utilices como sustituto automático de defer si el código depende del DOM o de otro script.
Rutas relativas y archivos en otras carpetas
La ruta de href o src se resuelve desde el documento HTML. En cambio, una imagen referenciada con url() dentro de un archivo CSS se resuelve normalmente desde ese archivo CSS.
/* Dentro de css/estilos.css, si imagenes está junto a css */
.hero { background-image: url('../imagenes/portada.webp'); }Ese detalle explica muchos fondos que no aparecen aunque la hoja de estilos sí cargue.
Qué revisar cuando CSS o JavaScript no cargan
- Comprueba las rutas, las mayúsculas y las extensiones.
- Abre las herramientas del navegador y busca errores 404 en Red.
- Revisa la consola para detectar errores de sintaxis o selectores que devuelven
null. - Confirma que el servidor devuelve el archivo correcto, no una página HTML de error.
- Si editas y no ves cambios, revisa la caché antes de modificar más código.
Preguntas frecuentes
¿Link lleva etiqueta de cierre?
No. Es un elemento vacío. script sí necesita su cierre.
¿Puedo escribir CSS y JavaScript en el HTML?
Sí, con style y script. Para proyectos que crecen, separarlos suele facilitar el mantenimiento.
Para profundizar en cómo JavaScript encuentra elementos, consulta nuestra guía del DOM. Encontrarás más bases en Aprender HTML.
Referencia técnica: documentación de script en MDN.




