Aprendiendo de los Grandes: El feed de Instagram
Sin frameworks. Sólo el viejo y confiable combo de HTML & CSS.
En el proceso de aprender a desarrollar sitios web y utilizar las herramientas más básicas como lo son CSS y HTML, lo más desafiante es elegir ejemplos fáciles que reproducir. Una web que es sorprendentemente familiar a todos con un moderado nivel de dificultad es Instagram. Vamos a ver como resolvemos muchos de los desafíos detrás de crear su feed y aprender en el camino una o dos cosas.
Lo primero que vamos a hacer es armar el tan conocido y emblemático posteo de Instagram en las diferentes partes que después vamos a maquetas con HTML.
🏗 Maquetando
Es bastante claro mirando el posteo, que tenemos
- un área superior que encabeza el componente donde está el usuario y su foto de perfil
- una sección principal donde está la imagen
- un area inferior donde vamos a poner las acciones, los datos y una sección donde el usuario puede comentar.
Ya mismo empezar a maquetar haciendo uso de la etiqueta semántica article
y anidando las futuras secciones usando header
, section
y footer
, las cuales comienzan a darle estructura a nuestro posteo.
<article>
<header></header>
<section></section>
<footer></footer>
</article>
¿Por qué no usar muchos div?
Es inevitable el uso de div
, no te castigues si ves que realmente no podes evitarlo, pero es importante saber que utilizar la menor cantidad posible tiene sus beneficios:
- El código es mucho más fácil de leer, interpretar y mantener.
- Agregar estilo (CSS) a nuestros componentes se vuelve más sencillo y con menos clases.
- Estás utilizando las herramientas mas avanzadas y correctas para el maquetado.
- Mejores puntajes de SEO ✨
- Habla bien de vos como developer
Y ¿por qué estas en particular?
article
es una etiqueta excelente para contenido auto-contenido (como lo es un posteo, un producto, el articulo de un blog, etc).section
define una sección dentro de un documentoheader
representa contenido introductorio o links de navegaciónfooter
es el pie de página o el final del contenido y suele tener información, autor, o contenido relacionado.
🏗 Agregando más elementos
Header
Necesitamos agregar la imagen para la foto de perfil y un título para nuestro usuario.
También vamos a envolver a la imagen en un div
en caso de que necesitemos manipularla dentro de la estructura sin alterar sus proporciones, y el titular va a contar con un a
para llevarnos al perfil que corresponde.
<header>
<div>
<img width="32" height="32" src="https://avatars.dicebear.com/api/avataaars/alebonzo.svg">
</div>
<h2><a href="https://instagram.com/alebonzo">alebonzo</a></h2>
</header>
Maquetando con Placeholders
Para la imagen de perfil use Dicebear Avatars, una librería de imágenes con una amplia cantidad de avatares que podemos usar solo poniendo una URL. Este tipo de librerías es ideal cuando estamos maquetando y aún no tenemos las imágenes finales pero queremos poner algo que denote la intención que va a tener esa imagen. En este caso es el avatar o foto de perfil de un usuario.
Para usarla ponemos la URL cambiando los valores de category
y seed
. La librería nos va a dar es una imagen diferente para cada seed
dentro de cada categoría.
avatars.dicebear.com/api
{category}
/{seed}
.svg
Las categorías están en el link, y el seed puede ser cualquier cosa URL friendly (pst, para los espacios podes-usar-guiones).
Section
Siendo un poco más fácil, acá solo queremos poner una imagen, y de nuevo vamos a poner un div
que la contenga para poder manipularla sin alterar sus proporciones.
<section>
<div class="img-wrapper">
<img src="https://i.imgur.com/bxPoqdw.jpg" alt="">
</div>
</section>
Footer
Vamos a comenzar por poner los iconos en su lugar con svg
(los que nos ahorra tener que hacer iconos para cada tamaño, ya que los SVG son vectores y siempre se van a ver bien) y envolverlos en un div
que los separe del resto de los elementos del footer al que vamos a llamar acciones.
Vamos a poner en .data
quien le dió like, el creador del contenido con su descripción, y en una etiqueta time
hace cuanto se posteó.
<footer>
<div class="actions">
<svg aria-label="Like" height="24" viewBox="0 0 48 48" width="24">...</svg>
<svg aria-label="Comment" height="24" viewBox="0 0 48 48" width="24">...</svg>
<svg aria-label="Share Post" height="24" viewBox="0 0 48 48" width="24">...</svg>
<svg aria-label="Save" height="24" viewBox="0 0 48 48" width="24">...</svg>
</div>
<div class="data">
<div class="likes">Liked by <strong>you</strong> and <strong>others</strong></div>
<div class="description"><strong>ladyahorro</strong></div>
<time>2 hours ago</time>
</div>
<div class="comment">
<div class="emote">
<svg height="24" viewBox="0 0 48 48" width="24">...</svg>
</div>
<input type="text" placeholder="Add a comment...">
<button>Post</button>
</div>
</footer>
🎨 Agregando estilo
¡Ahora es cuando se pone divertido! Con todo el HTML ya escrito, solo queda agregar estilo a los componentes para que se vean exactamente como queremos.
Comenzamos por definir la paleta inicial que vamos a utilizar. En este caso en particular, los obtuve directamente de la página de Instagram.
#ffffff
: Blanco, el fondo del articulo.#dbdbdb
: Gris, para los bordes.#262626
: Negro, para el color de los textos.#0095f6
: Azul, para el botón.
Article
Comenzamos con el aspecto en general de nuestro posteo, un fondo blanco, un borde gris con las esquinas ligeramente redondeadas. Y en caso de que haya algún elemento lo suficientemente rebelde como para extenderse sobre el padre, vamos a ocultarlo. También en caso de que haya más de un posteo al lado del otro, queremos que estén separados entre sí, y para eso usamos márgenes.
💡 PRO CSS TIP: El selector a + b
selecciona un elemento b que esté inmediatamente después de un elemento a. Esto puede ser usado con cualquier elemento, ya sea una clase, una etiqueta o un id.
article {
background-color: #ffffff;
border: 1px solid #dbdbdb;
border-radius: 4px;
overflow: hidden;
}
/* Hacemos uso del selector a + b para seleccionar a cualquier posteo que este seguido de otro, y lo separamos verticalmente desde el lado superior. */
article + article {
margin-top: 1rem;
}
Header
Al header de nuestro posteo le vamos a poner una borde inferior gris del mismo color que nuestro articulo, un poco de espacio entre el contenido y la caja, y vamos a hacer que los hijos estén alineados al medio.
Además de quitarle todo el estilo al link, al titular lo vamos a separar de la imagen desde el lado izquierdo, y vamos redondear los bordes de la imagen de perfil.
article header {
z-index: 20;
background: #ffffff;
display: flex;
width: 100%;
align-items: center;
padding: 1rem;
border-bottom: 1px solid #dbdbdb;
}
article header h2 {
margin: 0;
margin-left: 0.5rem;
font-weight: 500;
font-size: 1rem;
color: #262626;
}
article header h2 a {
text-decoration: none;
color: #262626;
}
article header img {
display: block;
height: 32px;
width: 32px;
padding: 2px;
border-radius: 100%;
border: 1px solid #262626;
}
Section
Para la sección de la foto, vamos a hacer un div
donde poner a nuestra imagen.
Vamos a forzar la relación de aspecto de este elemento a 1:1 usando el truco del padding.
Por último, la imagen va a usar object-fit: cover
para que cubra toda la superficie del padre.
article section {
width: 100%;
position: relative;
height: auto;
}
article section .img-wrapper {
padding-top: 100%;
position: relative;
}
article section img {
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
object-fit: cover;
height: 100%;
width: 100%;
}
Footer
El peso tipográfico de la etiqueta strong
por defecto es bolder (equivale a 700), así que lo suavizamos un poco al reducirlo a 600.
Lo que vamos a hacer es poner las acciones separadas entre sí con márgenes y de los bordes laterales de la caja con padding.
La etiqueta time
va a requerir que le bajemos un poco la intensidad, por lo que en vez de jugar con los colores, sencillamente le bajamos la opacidad,
Vamos a remover los bordes del input
y button
. Para facilitar el armado de la estructura, vamos a usar display: grid
en su padre, pero esta estructura también se puede lograr fácilmente con flex, sólo que con más líneas de código.
article footer strong {
font-weight: 600;
}
article footer svg {
display: block;
}
article footer > * + * {
margin-top: 1rem;
}
article footer > .actions,
article footer > .data > *,
article footer > .comment {
padding-left: 1rem;
padding-right: 1rem;
}
article footer > .data > * + * {
margin-top: .5rem;
}
article footer .actions {
padding-top: 1rem;
display: flex;
}
article footer .actions > * + * {
margin-left: .5rem;
}
article footer .actions > *:last-child {
margin-left: auto;
margin-right: 0;
}
article footer time {
display: block;
opacity: .6;
font-size: .7rem;
text-transform: uppercase;
}
article footer .comment {
display: grid;
grid-template-columns: auto 1fr 50px;
align-items: center;
gap: .15rem;
margin-top: 1rem;
padding-top: .7rem;
padding-bottom: .7rem;
border-top: 1px solid #dbdbdb;
}
article footer .comment input,
article footer .comment button {
line-height: 1;
background-color: #fff;
padding: .5rem 1rem;
border: 0;
}
article footer .comment button {
color: #0095f6;
font-weight: bold;
text-align: center;
cursor: pointer;
}
article footer .comment input::placeholder {
color: #262626ee;
}
💡 PRO CSS TIP: El selector * + *
, también conocido como Owl Selector, o Selector Buho 🦉, es excelente para seleccionar y darle espacio a varios elementos que no conocemos que van a ser; sólo que son hermanos. Combinarlo con el selector de hijos directos >
va a ser ideal para evitar problemas con descendencias mas profundas.
✨ Uniendo todo
Una vez que juntamos todo tenemos y agregamos algunos post más, tenemos una interfaz más que conocida. Que como vimos, es un desafío fácil de tacklear si analizamos previamente que es lo que vamos a necesitar, maquetamos el HTML con conciencia y después le damos estilo.
👋 Palabras Finales
Recrear estos sitios web nos sirve de práctica a la vez que ayuda a incorporar técnicas y reglas de CSS, que eventualmente nos van a salir de forma natural.
En otro posteo vamos a cubrir los pasos que nos faltan para terminar con la home de Instagram, mientras tanto cuéntenme en los comentarios sus opiniones y que les gustaría ver a futuro.
¡Hasta la próxima!