Este es un diseño de página web con HTML, CSS y JavaScript completo: la web de una agencia con preloader, menú que cambia al hacer scroll, secciones de equipo y servicios, y una galería de trabajos que se filtra por categoría. Todo es responsive y lo haces desde cero.
El curso tiene 4 capítulos. Aquí tienes el primero, el código de cada paso explicado y la plantilla completa para descargarla gratis.
Al finalizar este tutorial lograrás:
- Resultado: la página web de una agencia, adaptable a móviles, lista para usarla como portafolio o para tu empresa.
- Tecnologías: HTML, CSS (variables, Flexbox,
object-fit) y JavaScript con un poco de jQuery. - Nivel: principiante con nociones básicas de HTML y CSS.
- Ir directo al código fuente
Qué vas a construir
Una página de una sola pantalla para una agencia de desarrollo web: cabecera con imagen y degradado, equipo, servicios, trabajos con filtro y pie de página con redes sociales. Cada parte practica una técnica distinta:
| Parte de la página | Técnica que aprendes |
|---|---|
| Pantalla de carga | Preloader de Loading.io que desaparece con jQuery |
| Cabecera | Degradado sobre una imagen y efecto parallax con background-attachment: fixed |
| Menú | Cambia de transparente a sólido al hacer scroll, con JavaScript |
| Equipo y trabajos | Tarjetas con Flexbox y object-fit: cover |
| Galería de trabajos | Filtro por categoría con jQuery |
| Móvil | Menú hamburguesa que se cierra al tocar fuera |

El curso completo son 4 videos:
- Capítulo 1: el HTML de toda la página (37 min)
- Capítulo 2: el diseño con CSS (50 min)
- Capítulo 3: el menú con JavaScript y la versión móvil (41 min)
- Capítulo 4: el filtro de la galería y el scroll a cada sección (19 min)
Qué necesitas
- Un editor de código, por ejemplo Visual Studio Code.
- Los iconos de los servicios, de Flaticon (PNG blanco de 64 px), y los de redes sociales, de Font Awesome.
- jQuery para el filtro y el scroll suave, y un preloader de Loading.io.
- Conocimientos básicos de HTML y CSS. El JavaScript se explica desde cero.
Paso a paso
Prepara el proyecto y los recursos
Crea una carpeta con index.html, estilos.css, una carpeta img para las fotos y una js para los scripts. En el <head> enlaza tu hoja de estilos y la hoja de Font Awesome desde su CDN, que es lo que dibuja los iconos de YouTube, Facebook y GitHub del pie. Los scripts van al final del <body>, con jQuery primero porque filtro.js lo necesita.
<link rel="stylesheet" href="estilos.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU"
crossorigin="anonymous">
<script src="js/jquery.js"></script>
<script src="js/main.js"></script>
<script src="js/filtro.js"></script>
Escribe el menú y la cabecera
El menú vive dentro del <header>: un contenedor con el logo, los cinco enlaces y el icono de menú para móvil. Cada enlace tiene un id propio porque en el último paso JavaScript los usará para hacer scroll a su sección. El icono de hamburguesa es el carácter ☰, así no hace falta otra fuente ni otra imagen.
<nav id="nav" class="nav1">
<div class="contenedor-nav">
<div class="logo">
<img src="img/logo.png" alt="">
</div>
<div class="enlaces" id="enlaces">
<a href="#" id="enlace-inicio" class="btn-header">Inicio</a>
<a href="#" id="enlace-equipo" class="btn-header">Equipo</a>
<a href="#" id="enlace-servicio" class="btn-header">Servicios</a>
<a href="#" id="enlace-trabajo" class="btn-header">Trabajos</a>
<a href="#" id="enlace-contacto" class="btn-header">Contacto</a>
</div>
<div class="icono" id="open">
<span>☰</span>
</div>
</div>
</nav>
Crea las secciones de equipo, servicios y trabajos
Las tres secciones repiten el mismo patrón: un título, un subtítulo con la clase after y una fila de cajas. En la galería, cada trabajo lleva su categoría como clase (programacion, diseño o marketing) y cada botón del filtro la guarda en data-nombre. Esa coincidencia es lo que después usa el filtro.
<div class="botones-work">
<ul>
<li class="filter active" data-nombre='todos'>Todos</li>
<li class="filter" data-nombre='diseño'>Diseño</li>
<li class="filter" data-nombre='programacion'>Programacion</li>
<li class="filter" data-nombre='marketing'>Marketing</li>
</ul>
</div>
<div class="galeria-work">
<div class="cont-work programacion">
<div class="img-work">
<img src="img/programacion1.jpeg" alt="">
</div>
<div class="textos-work">
<h4>Programacion</h4>
</div>
</div>
</div>
Define las variables de CSS
Antes de dar estilo a nada, el capítulo 2 guarda colores, tamaños y espacios en variables dentro de :root. Al estar en la raíz, todos los elementos pueden usarlas. La ventaja se ve en el responsive: para reducir los márgenes en móvil solo cambias --margenes, no cada sección.
:root{
--color1: rgb(219,144,.5);
--color2: rgba(23, 180, 83, 0.877);
--color3: rgba(11,194,211, 0.623);
--fondo: #f2f2f2;
--titulos: 33px;
--margenes: 60px;
--espacios: 10px;
--espacios-contenido:45px;
}
Dale a la cabecera un degradado con efecto parallax
El fondo de la cabecera son dos capas en un solo background: primero un degradado semitransparente de naranja a verde y azul, y debajo la foto. Con background-attachment: fixed la imagen se queda quieta mientras el contenido sube, y ese es el efecto parallax.
header{
width: 100%;
height:600px;
background: linear-gradient(to bottom,
rgba(211,135,20, .6),
rgba(29,241,171, .6),
rgba(7,109,150, .45)
), url(img/fondo.jpg);
background-attachment: fixed;
background-position: center;
background-size: cover;
}
Ordena las tarjetas con Flexbox y object-fit
Las tarjetas del equipo están en una fila Flexbox con flex-wrap, así que bajan de línea cuando no caben. Cada tarjeta mide 400 px de alto: el 80 % para la foto y el 20 % para el texto. object-fit: cover hace que la foto llene su caja sin deformarse, recortando lo que sobra.
.card{
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.content-card{
width: 31%;
box-shadow: 0 0 6px 0 rgba(0,0,0,.5);
overflow: hidden;
height:400px;
}
.content-card img{
width: 100%;
height: 100%;
object-fit: cover;
}
Cambia el menú al hacer scroll
El menú tiene dos estados en CSS: .nav1, transparente y de 80 px, y .nav2, con fondo y de 100 px. En el capítulo 3, JavaScript lee cuánto has bajado (window.pageYOffset) y a partir de 300 px cambia una clase por la otra. La función también se ejecuta al cargar la página, por si alguien la recarga a mitad del scroll.
function menus(){
let Desplazamiento_Actual = window.pageYOffset;
if(Desplazamiento_Actual <= 300){
nav.classList.remove('nav2');
nav.className = ('nav1');
nav.style.transition = '1s';
menu.style.top = '80px';
abrir.style.color = '#fff';
}else{
nav.classList.remove('nav1');
nav.className = ('nav2');
nav.style.transition = '1s';
menu.style.top = '100px';
abrir.style.color = '#000';
}
}
Haz el menú hamburguesa para móviles
Por debajo de 700 px los enlaces pasan a ser un panel fijo con width: 0, es decir, escondido. Al tocar el icono, apertura() le da un 70 % del ancho de la pantalla, y al volver a tocarlo lo cierra. Un tercer evento cierra el menú si tocas en cualquier otra parte de la página.
@media screen and (max-width: 700px){
.enlaces{
position: fixed;
top:80px;
background: #2c3e50;
left: 0;
height: 100%;
transition: 1s;
width: 0;
overflow: hidden;
}
}
function apertura(){
if(cerrado){
menu.style.width = '70vw';
cerrado = false;
}else{
menu.style.width = '0%';
menu.style.overflow = 'hidden';
cerrado = true;
}
}
Muestra un preloader mientras carga la página
El <body> empieza con la clase hidden (sin scroll) y una capa negra a pantalla completa con la animación de Loading.io encima. Cuando la página termina de cargar, jQuery desvanece la capa y quita la clase.
.centrado{
position: fixed;
width: 100vw;
height: 100vh;
background: #000;
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
}
window.addEventListener('load', function(){
$('#onload').fadeOut();
$('body').removeClass('hidden');
menus();
});
Filtra la galería de trabajos con jQuery
En el capítulo 4, al hacer clic en un botón, este se marca como activo y sus hermanos pierden la clase. Después se lee su data-nombre: con «todos» se muestran todas las cajas, y con una categoría se ocultan las que no la tienen y se muestran las que sí.
$('.filter').click(function () {
$(this).addClass('active').siblings().removeClass('active');
let valor = $(this).attr('data-nombre');
if (valor == 'todos') {
$('.cont-work').show('1000');
} else {
$('.cont-work').not('.' + valor).hide('1000');
$('.cont-work').filter('.' + valor).show('1000');
}
});
Lleva cada enlace a su sección con scroll suave
Cada enlace del menú evita su comportamiento normal y anima el scroll hasta la posición de su sección. Se restan 100 px porque es lo que mide el menú fijo: sin eso, el título de la sección quedaría tapado.
let equipo = $('#equipo').offset().top;
$('#enlace-equipo').on('click', function(e){
e.preventDefault();
$('html, body').animate({
scrollTop: equipo -100
},600);
});
Consejo
El curso es de 2018. Hoy puedes conseguir el mismo scroll sin jQuery: pon scroll-behavior: smooth en el html, href="#equipo" en el enlace y scroll-margin-top: 100px en la sección. Y si quieres controlar el tamaño de los subtítulos, añade --subtitulos a :root: .contenedor p la usa, pero no está definida.
Código fuente
La plantilla tiene el proyecto completo: index.html, estilos.css, main.js, filtro.js, jQuery, todas las imágenes y los iconos de Flaticon. Es libre de derechos de autor: úsala como quieras.
Patrocinador oficial del curso
Hostinger es el patrocinador oficial del curso. Si quieres publicar esta página en internet con tu propio dominio, entra con el enlace de AlexCG Design.
Preguntas frecuentes
¿Puedo usar esta plantilla en mis proyectos?
Sí. La plantilla es libre de derechos de autor: descárgala, cambia los textos, las fotos y los colores, y úsala como base para tu portafolio, tu empresa o la página de un cliente. Los iconos de Flaticon sí piden atribuir al autor si no tienes licencia, como explico en el capítulo 1.
¿Necesito jQuery para hacer esta página web?
Solo para dos cosas: el filtro de la galería y el scroll suave del menú, que se usan para ahorrar tiempo. El menú que cambia al hacer scroll y el menú hamburguesa están hechos con JavaScript puro. Si prefieres no usar jQuery, el scroll suave hoy se resuelve con CSS (mira el consejo después de los pasos).
¿Cómo cambio los colores del diseño?
Desde las variables de :root. Los títulos, las líneas bajo los subtítulos y los botones del filtro usan --color1: si cambias su valor, cambian todos a la vez. El archivo trae otros dos colores, verde y azul, preparados en --color2 y --color3.
Más proyectos
- Página web con HTML, CSS y JavaScript paso a paso
- Página web con efecto wave en HTML y CSS
- Página web moderna con HTML5 y CSS3
- Página web con efecto skew
- Menú desplegable con HTML, CSS y JavaScript
Curso
Domina HTML5 y CSS3
Mi curso para diseñar páginas web modernas desde cero, como esta.




:root{
–color1: rgb(219,144,.5);
–color2: rgba(23, 180, 83, 0.877);
–color3: rgba(11,194,211, 0.623);
–fondo: #f2f2f2;
–titulos: 33px;
–margenes: 60px;
–espacios: 10px;
–espacios-contenido:45px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: ‘open sans’;
background: var(–fondo);
}
img{
vertical-align: top;
}
/* Preloader */
.hidden{
overflow: hidden;
}
.centrado{
position: fixed;
width: 100vw;
height: 100vh;
background: #000;
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
}
.lds-facebook {
display: inline-block;
position: relative;
width: 64px;
height: 64px;
}
.lds-facebook div {
display: inline-block;
position: absolute;
left: 6px;
width: 13px;
background: #cef;
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
}
.lds-facebook div:nth-child(1) {
left: 6px;
animation-delay: -0.24s;
}
.lds-facebook div:nth-child(2) {
left: 26px;
animation-delay: -0.12s;
}
.lds-facebook div:nth-child(3) {
left: 45px;
animation-delay: 0;
}
@keyframes lds-facebook {
0% {
top: 6px;
height: 51px;
}
50%,
100% {
top: 19px;
height: 26px;
}
}
/* Header */
header{
width: 100%;
height:600px;
background: linear-gradient(to bottom,
rgba(211,135,20, .6),
rgba(29,241,171, .6),
rgba(7,109,150, .45)
), url(img/fondo.jpg);
background-attachment: fixed;
background-position: center;
background-size: cover;
}
nav{
width: 100%;
position: fixed;
box-shadow: 0 0 10px 0 rgba(0,0,0,.5)
}
.nav1{
background: transparent;
height: 80px;
color:#fff;
}
.nav2{
background: var(–fondo);
height:100px;
color:#000;
}
.contenedor-nav{
display: flex;
margin: auto;
width: 90%;
justify-content: space-between;
align-items: center;
max-width:1000px;
height:inherit;
overflow: hidden;
}
nav .enlaces a{
display: inline-block;
padding: 5px 0;
margin-right: 17px;
font-size: 17px;
font-weight: 300;
text-decoration: none;
border-bottom: 3px solid transparent;
color: inherit;
}
nav .enlaces a:hover{
border-bottom: 3px solid #1498a4;
transition: 0.6s;
}
.logo, .logo img{ height:80px;}
.icono{
display:none;
font-size: 24px;
padding: 23.5px 20px;
}
.textos{
width: 100%;
height: 100%;
display:flex;
justify-content: center;
flex-direction: column;
align-items: center;
color:#fff;
overflow: hidden;
text-align: center;
}
.textos>h1{font-size:80px;;}
.textos>h2{font-size: 30px; font-weight: 300;}
/* Main */
.contenedor{
margin:auto;
padding: var(–margenes) 0;
width: 90%;
max-width: 1000px;
text-align: center;
overflow: hidden;
}
.contenedor h3{
font-size: var(–titulos);
color: var(–color1);
margin-bottom: var(–espacios);
}
.contenedor p{
font-size: var(–subtitulos);
font-weight: 300;
color: var(–color1);
}
.after::after{
content:»;
display: block;
margin: auto;
margin-top: var(–espacios);
width: 100px;
height: 2px;
background: var(–color1);
margin-bottom: var(–espacios-contenido);
}
.card{
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.content-card{
width: 31%;
box-shadow: 0 0 6px 0 rgba(0,0,0,.5);
overflow: hidden;
height:400px;
}
.people{
height: 80%;
}
.content-card img{
width: 100%;
height: 100%;
object-fit: cover;
}
.texto-team{
height: 20%;
width: 100%;
padding: var(–espacios) 0;
}
.about{
background: url(img/teclado.jpg);
height: auto;
}
.servicios{
display: flex;
color:#fff;
justify-content: space-between;
margin: auto;
flex-wrap: wrap;
}
.caja-servicios{
width: 30%;
margin: auto;
text-align: center;
}
.caja-servicios>h4{
margin-bottom: var(–espacios);
}
.caja-servicios>p{
text-align: center;
}
.botones-work{
overflow: hidden;
}
.botones-work li{
display: inline-block;
text-align: center;
margin-left: var(–espacios);
margin-bottom: var(–espacios-contenido);
padding: 6px 12px;
border: 1px solid var(–color1);
list-style: none;
color: var(–color1);
}
.botones-work li:hover{
background: var(–color1);
color:#fff;
cursor: pointer;
}
.botones-work .active{
background: var(–color1);
color:#fff;
}
.galeria-work{
display:flex;
flex-wrap: wrap;
justify-content: space-around;
}
.cont-work{
width: 31%;
box-shadow: 0 0 6px 0 rgba(0,0,0,.5);
height:300px;
overflow: hidden;
margin-bottom: var(–espacios-contenido);
}
.img-work{
height: 90%;
width: 100%;
}
.img-work img{
height: 100%;
width: 100%;
object-fit: cover;
}
.textos-work{
height: 10%;
}
.textos-work h4{
line-height: 30px;
font-weight: 300;
}
/* Footer */
footer{background:url(img/teclado.jpg);}
.marca-logo{
width: 40%;
margin: auto;
margin-bottom: var(–espacios);
}
.marca-logo img{
width: 100%;
}
.iconos{
display: flex;
margin: auto;
justify-content: space-around;
width: 100%;
}
.fab{
font-size:60px;
color: #FFF;
margin-bottom: var(–espacios);
display: inline-block;
}
footer p{
margin-top:var(–espacios);
}
@media screen and (max-width: 700px){
.nav2{
color: #fff;
}
.icono{
display:block;
cursor: pointer;
}
.enlaces{
position: fixed;
top:80px;
background: #2c3e50;
left: 0;
height: 100%;
transition: 1s;
width: 0;
overflow: hidden;
}
.enlaces a{
display: block;
width: 100%;
height: 50px;
padding: 20px;
text-align: center;
background: #34495e;
color:#fff;
}
.textos>h1{font-size: 70px;}
.textos>h2{font-size:35px;}
.content-card{
width: 48%;
margin-bottom:var(–margenes);
}
:root{
–margenes: 30px;
}
}
@media screen and (max-width: 500px){
:root{
–espacios-contenido: 25px;
}
.content-card{
width: 90%;
}
.caja-servicios{
width: 90%;
margin-bottom: var(–margenes);
}
.cont-work{
width: 85%;
}
.marca-logo{
width: 80%;
}
.iconos{
margin: auto;
}
}
este fue el css que le puse a la pagina web
y al momento de que se lo puse
desaparecio el scrollbar
[…] Puedes complementer este proyecto con: Como crear una pagina web desde 0 […]
[…] También puedes complementer este proyecto con: Como crear una pagina web desde 0 […]
[…] Ir al tutorial Descargar la pagina […]