A veces el primer trozo de HTML que escribimos en un nuevo documento es un elemento que envuelve todo lo demás en la página. El término wrapper es común para eso. Le damos una clase, y esa clase se encarga de encapsular todos los elementos visuales de la página.
Siempre he luchado con la mejor manera de implementarlo. He encontrado un hilo relacionado en StackOverflow que tiene más de 250.000 visitas, así que obviamente no soy el único que se lo pregunta. Voy a resumir mis últimas reflexiones en este artículo.
Antes de sumergirnos en ello, vamos a examinar primero la diferencia entre el «wrapper» y el «contenedor».
«Wrapper» vs «Container»
Creo que hay una diferencia entre los elementos wrapper y container.
En los lenguajes de programación, la palabra container se utiliza generalmente para las estructuras que pueden contener más de un elemento. Un wrapper, en cambio, es algo que envuelve a un único objeto para proporcionarle más funcionalidad e interfaz.
Así que, en mi opinión, tiene sentido que tengan dos nombres diferentes porque pretenden funciones distintas.
Hablando del wrapper, es común pensar en un <div>
que contiene todo el resto del HTML del documento. Seguro que muchos de nosotros hemos vivido una época en la que poníamos eso a 960px de ancho y alineábamos al centro todo nuestro contenido principal. Los wrappers también se utilizan para cosas como aplicar un pie de página pegajoso.
El contenedor, por otro lado, suele pretender otro tipo de contención. Uno que a veces es necesario para implementar un comportamiento o estilo de múltiples componentes. Sirve para agrupar elementos tanto semántica como visualmente. Como ejemplo, Bootstrap tiene «clases contenedoras» que albergan su sistema de rejilla o contienen varios otros componentes.
Los términos wrapper y contenedor también pueden significar lo mismo dependiendo del desarrollador y lo que pretende. También puede haber otras convenciones, así que el mejor consejo suele ser implementar lo que tenga más sentido para ti. Pero recuerde, nombrar es una de las partes más fundamentales e importantes de las actividades de los desarrolladores. Las convenciones de nomenclatura hacen que nuestro código sea más legible y predecible. Elige con cuidado!
Aquí tienes un ejemplo de un wrapper de página general:
/** * 1. Centers the content. Yes, it's a bit opinionated. * 2. See the "width vs max-width" section * 3. See the "Additional Padding" section */.wrapper { margin-right: auto; /* 1 */ margin-left: auto; /* 1 */ max-width: 960px; /* 2 */ padding-right: 10px; /* 3 */ padding-left: 10px; /* 3 */}
width vs max-width
Establecer el width
de un elemento a nivel de bloque evitará que se extienda hasta los bordes de su contenedor (bueno para cosas como longitudes de línea legibles). Por lo tanto, el elemento envolvente ocupará el ancho especificado. El problema ocurre cuando la ventana del navegador es más estrecha que la anchura específica de la envoltura. Eso provocará una barra de desplazamiento horizontal, que casi siempre es indeseable.
Usar max-width
en su lugar, en esta situación, es mejor para ventanas de navegador más estrechas. Esto es importante a la hora de hacer que un sitio sea utilizable en dispositivos pequeños. Aquí hay un buen ejemplo que muestra el problema.
Ver el CSS-Tricks de Pen: The Best Way to Implement a CSS Wrapper by Kaloyan Kosev (@superKalo) on CodePen.
En términos de capacidad de respuesta, max-width
es la mejor opción!
Additional Padding
He visto que muchos desarrolladores se olvidan de un caso límite particular. Digamos que tenemos un wrapper con max-width
configurado a 980px. El caso de borde aparece cuando el ancho de la pantalla del dispositivo del usuario es exactamente 980px. El contenido entonces se pegará exactamente a los bordes de la pantalla sin dejar espacio para respirar.
Normalmente queremos un poco de relleno en los bordes. Por eso, si necesito implementar un wrapper con un ancho total de 980px, lo haría así:
.wrapper { max-width: 960px; /* 20px smaller, to fit the paddings on the sides */ padding-right: 10px; padding-left: 10px; /* ... */}
Por eso, añadir padding-left
y padding-right
a tu wrapper puede ser una buena idea, sobre todo en móvil.
O bien, considere la posibilidad de utilizar el tamaño de la caja para que el relleno no cambie el ancho total en absoluto.
Qué elemento HTML elegir
Una envoltura no tiene ningún significado semántico. Simplemente contiene todos los elementos visuales y el contenido de la página. Es sólo un contenedor genérico. En términos de semántica, <div>
es la mejor opción. El <div>
tampoco tiene significado semántico y sólo es un contenedor genérico.
Uno podría preguntarse si tal vez un elemento <section>
podría encajar en este propósito. Sin embargo, esto es lo que dice la especificación del W3C:
El elemento
<section>
no es un elemento contenedor genérico. Cuando un elemento se necesita sólo para fines de estilo o como una conveniencia para las secuencias de comandos, se anima a los autores a utilizar el elemento div en su lugar. Una regla general es que el elemento section es apropiado sólo si los contenidos del elemento se enumeran explícitamente en el esquema del documento.
El elemento <section>
tiene su propia semántica. Representa una agrupación temática de contenidos. El tema de cada sección debe identificarse, normalmente incluyendo un encabezamiento (elemento h1-h6) como hijo del elemento section.
Ejemplos de secciones serían los capítulos, las distintas páginas con pestañas de un cuadro de diálogo con pestañas o las secciones numeradas de una tesis. La página de inicio de un sitio web podría dividirse en secciones para una introducción, noticias e información de contacto.
Puede que no parezca muy obvio a primera vista, pero ¡sí! El viejo y simple <div>
encaja mejor para un wrapper!
Usando la etiqueta <body> vs. Usar un <div>
Cabe mencionar que habrá algunos casos en los que se podría usar el elemento <body>
como envoltorio. La siguiente implementación funcionará perfectamente:
body { margin-right: auto; margin-left: auto; max-width: 960px; padding-right: 10px; padding-left: 10px;}
Y resultará en un elemento menos en tu marcado porque puedes eliminar esa envoltura innecesaria <div>
de esta manera.
Sin embargo, no recomendaría esto, debido a la flexibilidad y la resistencia a los cambios. Imagina que en una fase posterior del proyecto se da alguno de estos escenarios:
- Necesitas forzar un pie de página para que se «pegue» al final del documento (parte inferior del viewport cuando el documento es corto). Incluso si puedes usar la forma más moderna de hacerlo – con flexbox, necesitas una envoltura adicional
<div>
. - Necesitas establecer el
background-color
de toda la página. Normalmente, cualquier fondo que pongas en el<body>
se comportará como si estuviera puesto en el elemento<html>
en caso de que no tenga ya fondo. Es una cosa rara de CSS. Pero si tu elemento<html>
ya tiene un fondo, y estableces el cuerpo a otra cosa, y el cuerpo tiene cualquier tipo de restricción de espacio, los fondos se pondrán raros. Es algo complicado.
Concluiría que sigue siendo la mejor práctica tener un <div>
adicional para implementar una envoltura CSS. De esta manera, si los requisitos de las especificaciones cambian más tarde, no tienes que añadir la envoltura más tarde y lidiar con el movimiento de los estilos. Después de todo, sólo estamos hablando de un elemento DOM extra.