Cómo crear una página web con HTML, CSS y JavaScript paso a paso

Crea paso a paso una página web responsive con HTML, CSS y JavaScript: slider, preguntas frecuentes, menú hamburguesa y formulario. Código gratis en GitHub.

Aprende cómo crear una página web con HTML, CSS y JavaScript desde cero: una landing page completa, adaptable a móviles, con slider de testimonios, preguntas frecuentes animadas, menú hamburguesa y un formulario que funciona de verdad.

Aquí tienes el video completo para que lo veas y lo sigas paso a paso, el código de cada paso explicado y el repositorio para descargarlo.

Al finalizar este tutorial lograrás:

  • Resultado: una landing page responsive para un curso de CSS, publicada en internet.
  • Tecnologías: HTML, CSS (Grid, Flexbox, custom properties) y JavaScript.
  • Nivel: principiante con nociones básicas de HTML y CSS.
  • Ir directo al código fuente

Qué vas a construir

Una página de venta para un curso de CSS: sección principal con imagen de fondo, beneficios del curso, tabla de precios, testimonios con slider, preguntas frecuentes y un pie de página con formulario de suscripción. Todo sin frameworks, solo con HTML, CSS y JavaScript.

Página web hecha con HTML, CSS y JavaScript: landing page de un curso de CSS con slider, tabla de precios y preguntas frecuentes

Cada parte de la página practica una técnica distinta:

Parte de la páginaTécnica que aprendes
Cabecera con imagen de fondoCSS Grid, ::before y clip-path
Beneficios del cursoGrid responsive sin media queries (auto-fit + minmax)
Tabla de preciosFlexbox con flex-wrap y custom properties
TestimoniosSlider con JavaScript y atributos data-id
Preguntas frecuentesAcordeón con scrollHeight y transiciones
Menú en móvilMenú hamburguesa con media queries y JavaScript
Pie de páginaFormulario funcional con Formspree

Qué necesitas

  • Un navegador con herramientas de desarrollo. En el video uso Firefox por su inspector de Grid.
  • Visual Studio Code, un editor de código para manipular archivos HTML.
  • Conocimientos básicos de HTML y CSS. El JavaScript se explica desde cero.

Paso a paso

Prepara la estructura del proyecto

Crea una carpeta con tres subcarpetas: css, images y js. En css van dos archivos: normalize.css, que iguala los estilos por defecto de todos los navegadores, y estilos.css, que será tu hoja de estilos. En la raíz crea el index.html y enlaza los dos CSS en este orden, para que tus estilos tengan la última palabra:

<link rel="shortcut icon" href="./images/favicon.png" type="image/x-icon">
<link rel="stylesheet" href="./css/normalize.css">
<link rel="stylesheet" href="./css/estilos.css">

Crea la sección principal con CSS Grid y custom properties

La cabecera (.hero) ocupa la altura de la pantalla y se divide en dos filas con Grid: 100 px para el menú y el resto para el título. La imagen de fondo va en un pseudoelemento ::before, con un degradado oscuro encima para que el texto se lea y un clip-path que le da el corte en pico de la parte inferior.

:root {
    --padding-container: 100px 0;
    --color-title: #001A49;
}

.hero {
    height: 100vh;
    min-height: 600px;
    max-height: 800px;
    position: relative;
    display: grid;
    grid-template-rows: 100px 1fr;
    color: #fff;
}

.hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(180deg, #0000008c 0%, #0000008c 100%), url('../images/computer.jpg');
    background-size: cover;
    clip-path: polygon(0 0, 100% 0, 100% 80%, 50% 95%, 0 80%);
    z-index: -1;
}

La custom property --padding-container es el truco que se repite en todo el proyecto. Cada sección puede redefinirla, por ejemplo --padding-container: 0 en el menú, sin crear clases nuevas.

Haz la sección de beneficios responsive sin media queries

Las tarjetas de «Qué aprenderás» se reacomodan solas según el ancho de la pantalla. La clave es repeat(auto-fit, minmax(260px, auto)): Grid crea tantas columnas de al menos 260 px como quepan, y en móvil pasan a una sola.

.about__main {
    display: grid;
    gap: 1em;
    grid-template-columns: repeat(auto-fit, minmax(260px, auto));
}

Diseña la tabla de precios con Flexbox

Las tres tarjetas de precios usan Flexbox con flex-wrap, así que bajan a otra línea cuando no caben. Los colores de cada tarjeta son custom properties: la tarjeta destacada solo cambia sus valores con el modificador --best, sin repetir ni una regla.

.price__element {
    --color-plan: #696871;
    --color-price: #1D293F;
    --bg-cta: #fff;
    width: 330px;
    padding: 40px;
}

.price__element--best {
    --color-plan: rgb(255 255 255 / 75%);
    --color-price: #fff;
    --bg-cta: #9F3919;
    width: 370px;
    background-color: #FF7143;
}

.price__price {
    color: var(--color-price);
}

Programa el slider de testimonios con JavaScript

Cada testimonio es un section.testimony__body con un data-id (1, 2, 3…). Solo el que tiene la clase --show es visible. Los botones de siguiente y anterior suman o restan 1 a la posición. Si te pasas del último vuelves al primero, y al revés.

const sliders = [...document.querySelectorAll('.testimony__body')];

const changePosition = (add) => {
    const currentTestimony = document.querySelector('.testimony__body--show').dataset.id;
    let value = Number(currentTestimony) + add;

    sliders[Number(currentTestimony) - 1].classList.remove('testimony__body--show');
    if (value === sliders.length + 1 || value === 0) {
        value = value === 0 ? sliders.length : 1;
    }
    sliders[value - 1].classList.add('testimony__body--show');
};

Como dataset.id devuelve texto, Number() evita que "1" + 1 dé "11". Para añadir otro testimonio solo copias la sección y le pones el siguiente data-id.

Hosting recomendado

Publica tu página web con Hostinger

Hostinger es el patrocinador oficial del curso. Con el cupón ALEXCG tienes hasta un 90 % de descuento en hosting, con dominio gratis y certificado SSL incluidos.

Crea las preguntas frecuentes con efecto acordeón

Las respuestas empiezan con height: 0 y una transición. Al hacer clic en una pregunta, JavaScript lee el scrollHeight de la respuesta (el alto que necesita para mostrarse completa) y se lo asigna. Si ya estaba abierta, la vuelve a 0. De paso gira la flecha.

const titleQuestions = [...document.querySelectorAll('.questions__title')];

titleQuestions.forEach(question => {
    question.addEventListener('click', () => {
        let height = 0;
        const answer = question.nextElementSibling;

        question.children[0].classList.toggle('questions__arrow--rotate');
        if (answer.clientHeight === 0) {
            height = answer.scrollHeight;
        }
        answer.style.height = `${height}px`;
    });
});

Un detalle que casi nadie explica: scrollHeight devuelve el alto del contenido, pero no el padding del contenedor. Por eso cada pregunta va dentro de un div extra, y JavaScript le añade la clase questions__padding--add (padding-bottom: 30px) al abrirla. Si le pones el padding directamente a la respuesta, el acordeón se corta.

Adapta la página a móviles con un menú hamburguesa

Por debajo de 800 px el menú se convierte en una capa negra a pantalla completa, invisible hasta que se pulsa el icono. La X de cerrar usa otra custom property, --show, que solo se define cuando el menú está abierto.

@media (max-width: 800px) {
    .nav__link--menu {
        position: fixed;
        inset: 0;
        background-color: #000;
        display: flex;
        flex-direction: column;
        justify-content: space-evenly;
        align-items: center;
        opacity: 0;
        pointer-events: none;
        transition: .7s opacity;
    }

    .nav__link--show {
        --show: block;
        opacity: 1;
        pointer-events: unset;
    }
}
const openButton = document.querySelector('.nav__menu');
const menu = document.querySelector('.nav__link');
const closeMenu = document.querySelector('.nav__close');

openButton.addEventListener('click', () => menu.classList.add('nav__link--show'));
closeMenu.addEventListener('click', () => menu.classList.remove('nav__link--show'));

Si prefieres un menú que se despliega hacia abajo, mira el menú desplegable con HTML, CSS y JavaScript.

Haz funcionar el formulario con Formspree

El formulario de suscripción del pie de página envía los correos sin programar un backend. Te registras gratis en Formspree, creas un formulario y pegas su dirección en el action. El name="_replyto" le indica a Formspree que ese campo es el correo de quien escribe.

<form class="footer__form" action="https://formspree.io/f/TU_ID" method="POST">
    <h2 class="footer__newsletter">Suscríbete a la newsletter</h2>
    <div class="footer__inputs">
        <input type="email" placeholder="Email:" class="footer__input" name="_replyto">
        <input type="submit" value="Regístrate" class="footer__submit">
    </div>
</form>

Si quieres un formulario de contacto con varios campos y otra alternativa gratuita, tienes la guía del formulario HTML funcional sin backend.

Agrega las metaetiquetas para Google y redes sociales

El title y la description son lo que ve la gente al encontrar tu página en Google. Las etiquetas Open Graph y Twitter controlan cómo se ve el enlace al compartirlo en Facebook, WhatsApp o X, con imagen incluida.

<title>Aprende CSS desde cero</title>
<meta name="description" content="Descripción de tu página para Google.">

<meta property="og:type" content="website">
<meta property="og:title" content="Aprende CSS desde cero">
<meta property="og:image" content="https://tu-dominio.com/images/css.jpg">
<meta property="twitter:card" content="summary_large_image">

Publica tu página web en internet

En el video ves dos caminos. GitHub Pages es gratis: creas un repositorio llamado tu-usuario.github.io, subes los archivos con GitHub Desktop y en unos minutos la página está en línea. Hostinger te da tu propio dominio, certificado SSL y correo: comprimes los archivos, los subes a public_html desde el administrador de archivos y los descomprimes ahí.

Consejo

Si al publicar en Hostinger tu dominio no carga con https://, activa «Forzar HTTPS» en la sección de SSL del panel.

Código fuente

El repositorio tiene el proyecto completo: index.html, estilos.css, normalize.css, los tres scripts (slider.js, questions.js y menu.js) y todas las imágenes. Es el código de la página web con HTML, CSS y JavaScript tal como queda al final del video.

Preguntas frecuentes

¿Puedo usar este código en mis proyectos?

Sí. El proyecto es libre: descárgalo, cámbiale los textos y los colores y úsalo como base para tu portafolio o para la página de un cliente. Si lo publicas, me encantaría verlo en los comentarios del video.

¿Necesito saber JavaScript para seguir el tutorial?

No. El JavaScript del proyecto son tres scripts cortos y en el video se explican línea por línea: seleccionar elementos, escuchar clics y añadir o quitar clases. Con saber HTML y un poco de CSS puedes seguirlo de principio a fin.

¿Cómo subo mi página web a internet gratis?

Con GitHub Pages. Creas una cuenta en GitHub, un repositorio con el nombre tu-usuario.github.io y subes ahí tus archivos. Tu página queda en esa dirección sin pagar nada. Si quieres un dominio propio (.com), necesitas un hosting.

Más proyectos