1. Web Design
  2. Email
  3. Email Design

Foundation para correos electrónicos: cómo usar partials de Panini

En este tutorial, usaremos Foundation para emails de ZURB para crear un correo electrónico con funcionamiento simple. Exploraremos varias bibliotecas que ofrece el framework, específicamente «Panini». Panini nos permite hacer algunas cosas, pero nos centraremos en su característica partials.
Scroll to top

Spanish (Español) translation by Carlos (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

En este tutorial, usaremos Foundation para emails de ZURB para crear un correo electrónico con funcionamiento simple. Exploraremos varias bibliotecas que ofrece el framework, específicamente «Panini». Panini nos permite hacer algunas cosas, pero nos centraremos en su característica partials.

Usaremos un diseño creado con Web Wireframe Kit disponible en Envato Elements.

Configurando nuestro proyecto

Foundation ofrece dos versiones; una versión estándar con CSS o una con Sass. Para este tutorial nos apoyaremos en la versión con Sass, pues brinda un flujo de trabajo diferente ya que incluye al lenguaje de plantillas «Inky», así como una mayor personalización de los estilos.

Daré por hecho que ya tienes cierto conocimiento sobre cómo configurar un proyecto usando Foundation, la manera más fácil es con Foundation CLI. Las instrucciones para su instalación mediante la línea de comandos están disponibles en la documentación de Foundation. Como alternativa, si eres un suscriptor de Envato Tuts+ o de Elements puedes seguir a Adi Purdila mientras explica paso a paso todo el proceso de instalación.

En cuanto hayas hecho esto, podemos crear un proyecto con el siguiente comando. Se te pedirá el nombre de la carpeta en la que deseas crear el proyecto.

1
foundation new --framework emails

Antes de empezar con cualquier código, primero me gusta limpiar mi directorio de compilación. Debes ver una carpeta src con la siguiente estructura:

  • assets
  • helpers
  • layouts
  • pages
  • partials

Me gusta borrar todos los archivos, excepto index.html dentro de la carpeta pages (no utilizaremos ninguno de los otros). También borraré index-layout.html en la carpeta layouts.

Nota: Como se mencionó anteriormente, esto no es obligatorio. Solo me gusta mantener mi directorio de compilación limpio y bonito.

El archivo _settings.scss

La versión sass del framework nos permite personalizar los componentes prediseñados para nuestro propio uso. A continuación, he enumerado los cambios que he realizado, incluyendo el encabezado de cada sección de los comentarios. Si lo deseas, puedes cambiar esto en tu archivo _settings.scss o crear un nuevo archivo e importarlo después del archivo de ajustes, pero antes que el del framework de foundation.

1
// 1. Global
2
// ---------
3
4
$primary-color: #ACACB7;
5
$light-gray: #F4F4F6;
6
$medium-gray: #ACACB7;
7
$dark-gray: #4E4E56;
8
$black: #000000;
9
$white: #ffffff;
10
$global-width: 540px;
11
$body-background: $white;
12
$global-radius: 6px;
13
14
// 4. Typography
15
// -------------
16
17
$global-font-color: $dark-gray;
18
$body-font-family: 'Lato', Helvetica, Arial, sans-serif;
19
$global-line-height: 1.5;
20
$header-font-weight: 700;
21
$h1-font-size: 48px;
22
$h2-font-size: 32px;
23
$h3-font-size: 30px;
24
$h4-font-size: 24px;
25
$h5-font-size: 18px;
26
$h6-font-size: 16px;
27
$header-margin-bottom: 0;
28
$paragraph-margin-bottom: 0;
29
30
// 5. Button
31
// ---------
32
33
$button-padding: (
34
  tiny: 4px 8px 4px 8px,
35
  small: 5px 10px 5px 10px,
36
  default: 16px 80px 16px 80px,
37
  large: 10px 20px 10px 20px,
38
);
39
40
// 7. Menu
41
// -------
42
43
$menu-item-padding: 10px;
44
$menu-item-gutter: 10px;
45
$menu-item-color: $dark-gray;

¡Empecemos a codificar!

Siguiendo adelante, es momento de abrir index.html en la carpeta pages. Aquí es donde crearemos el contenido del correo electrónico. Empezaremos con el siguiente código que incluye un elemento espaciador y el elemento contenedor. ¡Recuerda, estamos utilizando el lenguaje de plantillas Inky si esto no te resulta familiar.

1
---
2
subject: Foundation for Emails - Using Panini
3
---
4
5
<spacer size="25"></spacer>
6
7
<container>
8
  
9
</container>

Aquí ya hemos empezado a utilizar las características de Panini, específicamente los datos personalizados. Este es un valor predeterminado de datos que utiliza Foundation. Utiliza un nombre variable de suject que luego se introduce en la plantilla maestra para la etiqueta del título con {{{ subject }}.

La cabecera

¡Ahora podemos empezar a utilizar los partials con Panini! Adelante, crea un nuevo archivo llamado header.html dentro de la carpeta src/partials.

Usaremos el siguiente código para la cabecera, y aunque no es necesario, me gusta envolver mis secciones dentro de la etiqueta wrapper además de una clase para identificación:

1
<wrapper class="header">
2
    <row>
3
		<columns small="12" large="6" valign="middle">
4
			<a href="#" class="logo show-for-large">
5
				<img src="assets/img/logo.png" alt="Company Name">
6
			</a>
7
8
			<a href="#" class="logo hide-for-large">
9
				<center>
10
					<img src="assets/img/logo.png" alt="Company Name">
11
				</center>
12
			</a>
13
		</columns>
14
		<columns small="12" large="6" valign="middle" class="show-for-large">
15
			<p class="webversion text-right">
16
				<a href="#">Not displaying properly?</a>
17
			</p>
18
		</columns>
19
	</row>
20
</wrapper><!-- END .header -->

Tal vez habrás notado que he usado dos etiquetas de anclaje para el logo. Esto se debe a que el logo ha sido centrado en los dispositivos móviles (las imágenes necesitan una etiqueta center alrededor de ellas) así que usé las clases de visibilidad de Foundation para mostrar/ocultar en los dispositivos móviles. También he ocultado el texto del enlace de la versión web en los móviles.

Ahora tal vez te preguntes, ¿cómo hacemos para que esto aparezca? Volviendo al archivo index.html, entre las etiquetas de container, coloca dentro el siguiente código:

1
{{> header}}

Todas las inclusiones partial requieren {{> }} junto con el nombre del archivo partial, en este caso, header.html.

También usaré los siguientes estilos para la cabecera, puedes poner esto en cualquier parte. Yo creé un archivo llamado _styles.scss e importé esto mediante app.scss.

1
// Header
2
// ===================================
3
.header {
4
    .columns {
5
		padding-bottom:0;
6
	}
7
8
	.logo {
9
		img {
10
			max-width:111px;
11
		}
12
	}
13
14
	.webversion {
15
		a {
16
			font-size:14px;
17
			color:inherit;
18
		}
19
	}
20
}

Nota: Quizá habrás notado que no apliqué un ancho a la etiqueta img del logo (¡lo que normalmente deberías hacer!) El framework de Foundation tiene una gran cantidad de estilos que hacen que la imagen se expanda a todo su ancho. En este caso, puesto que estoy admitiendo pantallas retina, creo imágenes @2x. Podemos resolver eligiendo como objetivo a img y aplicando max-width (asegúrate de utilizar max-width, y no solo width)

Sección hero

Para esta sección, decidí mantenerla dentro del archivo index.html; sentí que no requería un partial, pero depende de ti cómo la manejes.

1
<wrapper class="hero">
2
    	<row>
3
			<columns small="12" large="12">
4
				<a href="#" class="play-video">
5
					<center>
6
						<img src="assets/img/play-icon.png" alt="Play">
7
					</center>
8
				</a>
9
			</columns>
10
		</row>
11
12
		<row>
13
			<columns small="12" large="12">
14
				<h1 class="text-center">De Finibus Bonorum<br class="show-for-large"> &amp; Malorum</h1>
15
16
				<spacer size="30"></spacer>
17
18
				<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</p>
19
20
				<spacer size="40"></spacer>
21
22
				<center>
23
					<button href="#" class="radius small-expanded">Sign Up</button>
24
				</center>
25
			</columns>
26
		</row>
27
	</wrapper><!-- END .hero -->
1
// Hero
2
// ===================================
3
.hero {
4
    .wrapper-inner {
5
		padding-bottom:150px;
6
7
		@media only screen and (max-width: #{$global-breakpoint}) {
8
			padding-bottom:75px !important;
9
		}
10
	}
11
12
	.play-video {
13
		display:block;
14
		padding-top:80px;
15
		padding-bottom:80px;
16
17
		img {
18
			max-width:120px;
19
		}
20
21
		@media only screen and (max-width: #{$global-breakpoint}) {
22
			padding-top:60px !important;
23
			padding-bottom:60px !important;
24
25
			img {
26
				max-width:60px !important;
27
			}
28
		}
29
	}
30
31
	p {
32
		font-size:18px;
33
	}
34
35
	@media only screen and (max-width: #{$global-breakpoint}) {
36
		h1 {
37
			font-size:40px !important;
38
		}
39
40
		p {
41
			font-size:16px !important;
42
		}
43
	}
44
}

En cuanto al estilo, probablemente veas algunas cosas aquí que no hayas visto antes. Hemos incorporado algunos estilos para el tamaño de los dispositivos móviles, esto se hace mediante una media query, pero Foundation es muy práctico y suministra una variable Sass para el ancho máximo (max-width).

1
@media only screen and (max-width: #{$global-breakpoint})

Siempre que estés creando los estilos dentro de la media query, a menudo deberás utilizar la etiqueta !important, de lo contrario los estilos de tamaño pequeño serán sobrescritos por los grandes.

Partials restantes

Así que nos quedan tres secciones por completar: Projects, Testimonials y Footer. Cada uno puede ser colocado en su propio archivo dentro de la carpeta src/partial.

projects.html

1
<wrapper class="projects">
2
    <row>
3
		<columns snall="12" large="12">
4
			<h2 class="text-center">Popular Projects</h2>
5
6
			<spacer size="20"></spacer>
7
8
			<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
9
10
			<spacer size="20"></spacer>
11
		</columns>
12
	</row>
13
14
	<row>
15
		<columns small="12" large="6">
16
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
17
		</columns>
18
		<columns small="12" large="6">
19
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
20
		</columns>
21
	</row>
22
23
	<row>
24
		<columns small="12" large="6">
25
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
26
		</columns>
27
		<columns small="12" large="6">
28
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
29
		</columns>
30
	</row>
31
32
	<row>
33
		<columns small="12" large="6">
34
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
35
		</columns>
36
		<columns small="12" large="6">
37
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
38
		</columns>
39
	</row>
40
</wrapper><!-- END .projects -->

testimonials.html

1
<wrapper class="testimonials">
2
    <row>
3
		<columns small="12" large="12">
4
			<h2 class="text-center">Don’t Just Take Our Word For It</h2>
5
6
			<spacer size="20"></spacer>
7
8
			<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
9
10
			<spacer size="20"></spacer>
11
		</columns>
12
	</row>
13
14
	<row>
15
		<columns small="12" large="4" class="show-for-large">
16
			<center>
17
				<img src="assets/img/user-icon.png" alt="User Name" class="user-icon">
18
			</center>
19
		</columns>
20
		<columns small="12" large="4">
21
			<center>
22
				<img src="assets/img/user-icon-primary.png" alt="User Name" class="user-icon">
23
			</center>
24
		</columns>
25
		<columns small="12" large="4" class="show-for-large">
26
			<center>
27
				<img src="assets/img/user-icon.png" alt="User Name" class="user-icon">
28
			</center>
29
		</columns>
30
	</row>
31
32
	<row>
33
		<columns small="12" large="12">
34
			<spacer size="40" class="show-for-large"></spacer>
35
36
			<spacer size="20" class="hide-for-large"></spacer>
37
38
			<p class="quote text-center">“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.”</p>
39
40
			<spacer size="30"></spacer>
41
42
			<center>
43
				<img src="assets/img/star-rating.png" alt="4 out of 5 Stars" class="star-rating">
44
			</center>
45
46
			<spacer size="20"></spacer>
47
48
			<h6 class="user-name text-center">Customer</h6>
49
50
			<spacer size="10"></spacer>
51
52
			<p class="title text-center">Title</p>
53
		</columns>
54
	</row>
55
</wrapper><!-- END .testimonials -->

footer.html

1
<wrapper class="footer">
2
    <container>
3
		<row>
4
			<columns small="4" large="5">
5
				<a href="#" class="facebook social"><img src="assets/img/social-facebook.png" alt="Facebook" class="float-right"></a>
6
			</columns>
7
			<columns small="4" large="2">
8
				<a href="#" class="twitter social"><img src="assets/img/social-twitter.png" alt="Twitter" class="float-center"></a>
9
			</columns>
10
			<columns small="4" large="5">
11
				<a href="#" class="youtube social"><img src="assets/img/social-youtube.png" alt="YouTube" class="float -left"></a>
12
			</columns>
13
		</row>
14
15
		<row>
16
			<columns small="12" large="12">
17
				<center>
18
				  	<menu>
19
				    	<item href="#">Link 1</item>
20
				    	<item href="#">Link 2</item>
21
				    	<item href="#">Link 3</item>
22
				    	<item href="#">Link 4</item>
23
				  	</menu>
24
				</center>
25
			</columns>
26
		</row>
27
	</container>
28
</wrapper><!-- END .footer -->

Estilos

1
// Projects
2
// ===================================
3
.projects {
4
    @media only screen and (max-width: #{$global-breakpoint}) {
5
		h2 {
6
			font-size:28px !important;
7
		}
8
9
		p {
10
			font-size:14px !important;
11
		}
12
	}
13
}
14
15
16
// Testimonials
17
// ===================================
18
.testimonials {
19
	.wrapper-inner {
20
		padding-top:150px;
21
		padding-bottom:100px;
22
23
		@media only screen and (max-width: #{$global-breakpoint}) {
24
			padding-top:75px !important;
25
			padding-bottom:50px !important;
26
		}
27
	}
28
29
	.user-icon {
30
		max-width:90px;
31
	}
32
33
	.quote {
34
		font-size:18px;
35
	}
36
37
	.star-rating {
38
		max-width:94px;
39
	}
40
41
	.title {
42
		color:$medium-gray;
43
	}
44
45
	@media only screen and (max-width: #{$global-breakpoint}) {
46
		h2 {
47
			font-size:28px !important;
48
49
		}
50
51
		p {
52
			font-size:14px !important;
53
		}
54
55
		.quote {
56
			font-size:16px !important;
57
		}
58
	}
59
}
60
61
62
// Footer
63
// ===================================
64
.footer {
65
	background:$light-gray;
66
67
	.container {
68
		background:$light-gray;
69
	}
70
71
	.wrapper-inner {
72
		padding-top:32px;
73
		padding-bottom:10px;
74
	}
75
76
	.social {
77
		img {
78
			max-width:40px;
79
		}
80
	}
81
82
	.menu {
83
		.menu-item {
84
			a {
85
				font-weight:700;
86
			}
87
		}
88
	}

Incluyendo los partials restantes

Ahora que hemos creado las partials finales podemos incluirlos en nuestro index.html. Añade {{> projects}} y {{> testimonials }} inmediatamente después de la etiqueta de cierre de la envoltura de hero.

¿Pero qué sucede con el pie de página? El pie de página se tiene que incluir, pero deberá ser colocado fuera de las etiquetas de <container> . Esto se debe a que utiliza un fondo con un ancho completo. Añade {{> footer}} inmediatamente después de la etiqueta de cierre del contenedor.

Terminando

¡A estas alturas, nuestro correo electrónico debería verse bastante bien! No obstante, quizá hayas notado que las fuentes no se cargan correctamente. Definimos la variable $body-font-family para usar «Lato», junto con soluciones alternativas. Esta es una fuente de Google, por lo que podemos importarla en el archivo app.scss. Asegúrate de importar esto antes que cualquier otra cosa.

1
@import url('https://fonts.googleapis.com/css?family=Lato:400,700');

Ahora que nuestro correo electrónico está terminado, podemos finalizarlo y prepararlo para su distribución. Utilizando los auxiliares de comandos de foundation, simplemente podemos ejecutar foundation build que minimizará las imágenes, css en línea ¡y empaquetará todo!

Conclusión

¡Lo logramos! ¡Hemos creado con éxito un correo electrónico usando el framework Foundation de ZURB y la biblioteca de Panini! Si quieres ver las otras características incluidas en Panini, la documentación completa está disponible.