Proyectos · HTML y CSS · Básico

Tarjeta de presentación

Tu primera página: una tarjeta con tu nombre, a qué te dedicas y tus enlaces, centrada, con modo oscuro automático y adaptada al móvil.

  • 5 pasos
  • 40 minutos aproximadamente
  • 126 líneas de código
  • Editor en vivo

Lo que vas a construir

El mejor primer proyecto web: pequeño, útil y que puedes publicar el mismo día. Vas a escribir el HTML de una tarjeta personal y darle estilo con CSS, desde centrarla en la pantalla hasta que cambie de colores sola con el modo oscuro del sistema.

Lo que vas a practicar

  • Estructurar una página con HTML
  • Centrar con CSS Grid
  • Dar estilo a enlaces y botones
  • Usar variables CSS
  • Modo oscuro y diseño para móvil
Resultado final

Antes de empezar, conviene haber hecho estas lecciones

Paso 1 de 5

El contenido en HTML

Escribe primero el contenido, sin pensar en el aspecto: el nombre en un <h1> (el título principal de la página), a qué te dedicas, una frase sobre ti y una lista con tus enlaces. El navegador ya lo muestra, aunque con su estilo por defecto.

mailto: abre el programa de correo con tu dirección. Cambia los datos de ejemplo por los tuyos.

index.html
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Lucía Martín · Diseñadora web</title>
  <link rel="stylesheet" href="estilos.css">
</head>
<body>
  <main class="tarjeta">
    <h1>Lucía Martín</h1>
    <p class="cargo">Diseñadora web</p>
    <p>Hago webs claras, rápidas y accesibles para pequeños negocios. Me encanta el café y los mapas antiguos.</p>
    <ul class="enlaces">
      <li><a href="mailto:lucia@ejemplo.es">Correo</a></li>
      <li><a href="https://github.com/">GitHub</a></li>
      <li><a href="https://www.linkedin.com/">LinkedIn</a></li>
    </ul>
  </main>
</body>
</html>
estilos.css
/* Los estilos llegan en el paso 2 */

Paso 2 de 5

Centrar y dar forma a la tarjeta

display: grid con place-items: center en el body centra la tarjeta en horizontal y en vertical. min-height: 100vh hace que el cuerpo ocupe al menos toda la altura de la ventana.

El círculo con tus iniciales es un div con el mismo ancho y alto y border-radius: 50%. Lleva aria-hidden="true" porque es decorativo: el nombre ya está en el título.

index.htmlLo nuevo, resaltado
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Lucía Martín · Diseñadora web</title>
  <link rel="stylesheet" href="estilos.css">
</head>
<body>
  <main class="tarjeta">
    <div class="avatar" aria-hidden="true">LM</div>
    <h1>Lucía Martín</h1>
    <p class="cargo">Diseñadora web</p>
    <p>Hago webs claras, rápidas y accesibles para pequeños negocios. Me encanta el café y los mapas antiguos.</p>
    <ul class="enlaces">
      <li><a href="mailto:lucia@ejemplo.es">Correo</a></li>
      <li><a href="https://github.com/">GitHub</a></li>
      <li><a href="https://www.linkedin.com/">LinkedIn</a></li>
    </ul>
  </main>
</body>
</html>
estilos.css
* { box-sizing: border-box; }

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f1f5f9;
  color: #0f172a;
  font-family: system-ui, sans-serif;
  line-height: 1.6;
}

.tarjeta {
  width: min(100%, 380px);
  padding: 32px 28px;
  border-radius: 20px;
  background: #ffffff;
  text-align: center;
  box-shadow: 0 12px 32px rgb(15 23 42 / 0.12);
}

.avatar {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: #4f46e5;
  color: #ffffff;
  font-size: 2rem;
  font-weight: 700;
}

h1 { margin: 0; font-size: 1.6rem; }

.cargo {
  margin: 4px 0 16px;
  color: #4f46e5;
  font-weight: 600;
}

Paso 3 de 5

Enlaces con forma de botón

Con display: flex y gap, los enlaces se colocan en fila con la misma separación. Quitando el subrayado y añadiendo relleno y border-radius: 999px parecen pastillas.

transition suaviza el cambio al pasar el ratón y :focus-visible marca bien el enlace cuando se navega con el teclado.

estilos.cssLo nuevo, resaltado
* { box-sizing: border-box; }

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f1f5f9;
  color: #0f172a;
  font-family: system-ui, sans-serif;
  line-height: 1.6;
}

.tarjeta {
  width: min(100%, 380px);
  padding: 32px 28px;
  border-radius: 20px;
  background: #ffffff;
  text-align: center;
  box-shadow: 0 12px 32px rgb(15 23 42 / 0.12);
}

.avatar {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: #4f46e5;
  color: #ffffff;
  font-size: 2rem;
  font-weight: 700;
}

h1 { margin: 0; font-size: 1.6rem; }

.cargo {
  margin: 4px 0 16px;
  color: #4f46e5;
  font-weight: 600;
}

.enlaces {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.enlaces a {
  display: inline-block;
  padding: 8px 14px;
  border-radius: 999px;
  background: #eef2ff;
  color: #3730a3;
  font-weight: 600;
  text-decoration: none;
  transition: background-color 200ms ease, transform 200ms ease;
}

.enlaces a:hover {
  background: #c7d2fe;
  transform: translateY(-2px);
}

.enlaces a:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}

Paso 4 de 5

Colores en variables y modo oscuro

Los colores se repiten en varios sitios. Guardándolos en variables CSS (--acento) en :root, se cambian en un solo lugar.

Así el modo oscuro es fácil: dentro de @media (prefers-color-scheme: dark) se da otro valor a las mismas variables, y la tarjeta cambia sola cuando el sistema está en modo oscuro.

estilos.cssLo nuevo, resaltado
* { box-sizing: border-box; }

:root {
  --fondo: #f1f5f9;
  --tarjeta: #ffffff;
  --texto: #0f172a;
  --acento: #4f46e5;
  --acento-suave: #eef2ff;
  --acento-texto: #3730a3;
}

@media (prefers-color-scheme: dark) {
  :root {
    --fondo: #0f172a;
    --tarjeta: #1e293b;
    --texto: #e2e8f0;
    --acento: #818cf8;
    --acento-suave: #312e81;
    --acento-texto: #e0e7ff;
  }
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--fondo);
  color: var(--texto);
  font-family: system-ui, sans-serif;
  line-height: 1.6;
}

.tarjeta {
  width: min(100%, 380px);
  padding: 32px 28px;
  border-radius: 20px;
  background: var(--tarjeta);
  text-align: center;
  box-shadow: 0 12px 32px rgb(15 23 42 / 0.12);
}

.avatar {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--acento);
  color: #ffffff;
  font-size: 2rem;
  font-weight: 700;
}

h1 { margin: 0; font-size: 1.6rem; }

.cargo {
  margin: 4px 0 16px;
  color: var(--acento);
  font-weight: 600;
}

.enlaces {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.enlaces a {
  display: inline-block;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--acento-suave);
  color: var(--acento-texto);
  font-weight: 600;
  text-decoration: none;
  transition: background-color 200ms ease, transform 200ms ease;
}

.enlaces a:hover {
  background: var(--acento);
  color: #ffffff;
  transform: translateY(-2px);
}

.enlaces a:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}

Paso 5 de 5

Lista para el móvil

En pantallas estrechas, los tres enlaces en fila no caben bien: una consulta @media (max-width: 420px) los apila en columna y reduce el relleno.

Por último, respeta a quien pide menos movimiento en su sistema quitando la animación con prefers-reduced-motion. Tu tarjeta está lista para publicarse, por ejemplo con GitHub Pages.

estilos.cssLo nuevo, resaltado
* { box-sizing: border-box; }

:root {
  --fondo: #f1f5f9;
  --tarjeta: #ffffff;
  --texto: #0f172a;
  --acento: #4f46e5;
  --acento-suave: #eef2ff;
  --acento-texto: #3730a3;
}

@media (prefers-color-scheme: dark) {
  :root {
    --fondo: #0f172a;
    --tarjeta: #1e293b;
    --texto: #e2e8f0;
    --acento: #818cf8;
    --acento-suave: #312e81;
    --acento-texto: #e0e7ff;
  }
}

body {
  min-height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--fondo);
  color: var(--texto);
  font-family: system-ui, sans-serif;
  line-height: 1.6;
}

.tarjeta {
  width: min(100%, 380px);
  padding: 32px 28px;
  border-radius: 20px;
  background: var(--tarjeta);
  text-align: center;
  box-shadow: 0 12px 32px rgb(15 23 42 / 0.12);
}

.avatar {
  display: grid;
  place-items: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--acento);
  color: #ffffff;
  font-size: 2rem;
  font-weight: 700;
}

h1 { margin: 0; font-size: 1.6rem; }

.cargo {
  margin: 4px 0 16px;
  color: var(--acento);
  font-weight: 600;
}

.enlaces {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.enlaces a {
  display: inline-block;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--acento-suave);
  color: var(--acento-texto);
  font-weight: 600;
  text-decoration: none;
  transition: background-color 200ms ease, transform 200ms ease;
}

.enlaces a:hover {
  background: var(--acento);
  color: #ffffff;
  transform: translateY(-2px);
}

.enlaces a:focus-visible {
  outline: 3px solid #f59e0b;
  outline-offset: 3px;
}

@media (max-width: 420px) {
  .tarjeta { padding: 24px 18px; }
  .enlaces { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
  .enlaces a { transition: none; }
  .enlaces a:hover { transform: none; }
}

Retos para seguir

Has terminado el proyecto. Si quieres ir más allá, prueba a añadirle esto por tu cuenta:

  1. Sustituye las iniciales por una foto tuya con <img>, redonda y con su texto alternativo.
  2. Añade una sección con 3 habilidades y una barra de nivel para cada una.
  3. Publica la tarjeta gratis con GitHub Pages y compártela.

Conceptos clave

Repasa la ruta de HTML y CSS o elige otro proyecto.