Blog personal de IT, viajes y otros hobbies

Categoría: Informática Página 1 de 13

Como «Freelancer» escribo artículos sobre mis experiencias en el mundo del desarrollo web, emprendimiento, nomadismo digital y también sobre mi participación activa en la Comunidad de WordPress ❤️.
¿Puedo ayudarte? ➡ mg@maugelves.com | +34 600984224

1001 formas de crear bloques de Gutenberg

Este artículo lo escribí básicamente para poner un poco de orden en mi cabeza ya que hay muchas formas y situaciones específicas para crear bloques de Gutenberg.

Veamos a continuación el diagrama de flujo de datos que he creado y en qué situación nos deja cada situación:

¿Debo usar bloques de Gutenberg? De ser así, ¿cuál es la solución adecuada?

Zona de principiantes

Bloques por defecto y reutilizables.

A día de hoy WordPress tiene por defecto una gran cantidad de bloques de Gutenberg que pueden ayudarte con tus múltiples necesidades para tu Web.

Algunos de los bloques por defecto de Gutenberg

Si uno o varios de estos bloques por defecto pueden servirte para dar solución a tu necesidad utilízalos directamente.

Ten en cuenta que también podrías generar un «bloque reutilizable» para reutilizar (valga la redundancia) este bloque o conjunto de ellos en el mismo o cualquier otro post.

Ten en cuenta que cualquier cambio que realices a un bloque reutilizable se modificará en todas sus instancias.

Aquí te dejo un ejemplo de cómo puedes crear un bloque reutilizable del foro en español de WordPress.

Directorio de patrones o plugins

En caso de que WordPress no tengo bloques por defecto que puedan servirte, bien puedes buscar en el Directorio de patrones (recientemente añadido a la Web de WordPress).

Directorio de patrones de Gutenberg

En este directorio solo tendrás que buscar si alguno de los patrones te sirve, para después copiarlo, pegarlo directamente en tu contenido y luego hacer los ajustes que sean necesarios.

Si aún no encuentras lo que estás buscando, lo ideal sería que instales un plugin que implemente lo que estás necesitando para tu Web.

No tengo mucha experiencia en este sector, pero estos son algunos de los más utilizados:

También puedes buscar en el directorio de plugins con la palabra clave «Gutenberg».

Resultados de plugins con la palabra clave «Gutenberg»

Zona de PHP

Si quieres desarrollar tu bloque en forma personalizada y sin mojarte las manos en Javascript, entonces tendrás que buscar alguna solución con PHP.

Crear bloques con Advanced Custom Field

Este plugin me salvó las papas durante mis 6 años de Freelance en España y afortunadamente no se ha quedado atrás desde Gutenberg irrumpió en el ecosistema de WordPress.

Sigue siendo muy fácil de diseñar, programar, ajustar y utilizar. Para ello debes simplemente seguir las instrucciones de su tutorial oficial y en nada tendrás tu bloque de Gutenberg personalizado.

Demo de bloque de Gutenberg desarrollado con ACF

¿Conoces alguna otra librería o plugin con el que puedas realizar bloques de Gutenberg solamente con PHP? Déjame un comentario así luego lo investigo.

Zona de Javascript

Si por narices te toca realizar el bloque de Gutenberg con Javascript, que sepas que aún así hay varias formas de implementarlo.

Variaciones

Utiliza variaciones si necesitas implementar un bloque por defecto de Gutenberg con ciertos valores de configuración predeterminado.

Ten en cuenta que creará un nuevo icono en el listado de bloques de Gutenberg.

Ejemplo de una variación del bloque «Columns» donde añade por defecto un icono y 3 columnas vacías.

wp.blocks.registerBlockVariation(
  'core/columns', {
    name: 'project-intro',
    title: 'Project Intro',
    icon: 'portfolio',
    scope: ['inserter'],
    innerBlocks: [
      ['core/column'],
      ['core/column'],
      ['core/column'],
    ],
  }
);

Link a la documentación oficial.

Estilos

Registrar un estilo hará que tu bloque tenga una clase CSS única que puedes utilizar para dar solución a tu necesidad.

A diferencia de las «variaciones», los estilos no crearán un icono nuevo en el listado de bloques. En su lugar mostrará un estilo nuevo en el sidebar del bloque en cuestión.

wp.blocks.registerBlockStyle( 'core/quote', {
    name: 'fancy-quote',
    label: 'Fancy Quote',
} );
Ejemplo de «estilos» para el bloque de imágenes.

Patrones

Registrando un patrón puedes crear una plantilla con bloques por defecto o personalizados. Una vez que se selecciona desde el listado de bloques solo nos queda modificar sus valores.

También puede especificarse en su código si el usuario puede seguir añadiendo bloques al patrón o bien editar sus valores.

register_block_pattern(
    'my-plugin/my-awesome-pattern',
    array(
        'title'       => __( 'Two buttons', 'my-plugin' ),
        'description' => _x( 'Two horizontal buttons, the left button is filled in, and the right button is outlined.', 'Block pattern description', 'my-plugin' ),
        'content'     => "<!-- wp:buttons {\"align\":\"center\"} -->\n<div class=\"wp-block-buttons aligncenter\"><!-- wp:button {\"backgroundColor\":\"very-dark-gray\",\"borderRadius\":0} -->\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-background has-very-dark-gray-background-color no-border-radius\">" . esc_html__( 'Button One', 'my-plugin' ) . "</a></div>\n<!-- /wp:button -->\n\n<!-- wp:button {\"textColor\":\"very-dark-gray\",\"borderRadius\":0,\"className\":\"is-style-outline\"} -->\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link has-text-color has-very-dark-gray-color no-border-radius\">" . esc_html__( 'Button Two', 'my-plugin' ) . "</a></div>\n<!-- /wp:button --></div>\n<!-- /wp:buttons -->",
    )
);

Enlace a la documentación oficial de los patrones.

Bloques con renderizado en el servidor

Si tu bloque es muy complejo para implementar todo el código en el editor o su almacenamiento, puedes optar por capturar solamente los valores y luego enviarlos a una plantilla de PHP para su posterior renderizado.

Con esta opción ganarás en facilidad de implementación pero como punto negativo no podrás ver la actualización en tiempo real en el editor.

Enlace a la documentación oficial.

Creación personalizada

Si todos los puntos anteriores no te han valido, entonces no queda más que crear el bloque en forma totalmente personalizada, registrando todos los valores a guardar, indicando cómo se mostrará en el editor y también su posterior almacenamiento y renderizado en el Frontend.

Por mi parte, aprendí a programar esos bloques siguiendo el curso de Javascripforwp.com (no hay enlace de afiliado ocutlo, solo lo recomiendo por el valor que aporta).

Mi charla en WordCamp Pontevedra

Te dejo también este vídeo con la charla sobre las «1001 formas de crear bloques de Gutenberg» que di en la WordCamp de Pontevedra.

Cambiar estilos CSS de un iframe externo

Toda la vida pensé que no se podían modificar los estilos de un iframe, hasta hoy que me tocó implementarlo por narices para la Web de un cliente (a veces las necesidades imperiosas agudizan el ingenio).

Después de mucho indagar por internet y algo de triquiñuelas personales logré implementarlo. Tal vez no sea una solución muy elegante, pero funciona.

Vamos al lío.

Agrega un EventListener

Tendremos que escuchar cada cierto tiempo si el iframe externo terminó de cargarse correctamente…

Para ello asignamos a una variable una función setInterval.

const variableDeIntervalo = setInterval( modificarIframe, 500 );

Crea la función principal

Una vez creado el intervalo, creo la función y añado las primeras verificaciones.

function modificarIframe() {
	// Busco el iframe en el DOM.
	let iframeAModificar = document.querySelector( 'iframe' );
	// Verifico si el iframe ya está cargado.
	if (
		! iframeAModificar
		|| typeof iframeAModificar === 'undefined'
	) {
		return;
	}
}

Cuando el iframe esté cargado

En la misma función y una vez que el iframe esté cargado obtengo su contenido y lo modifico con los nuevos estilos.

// Detengo el intervalo para evitar el consumo de recursos del navegador.
clearInterval( variableDeIntervalo );
// Obtengo el contenido del elemento iframe.
let doc = iframeAModificar.contentDocument;
let nuevosEstilos = `
<style>
	.alguna-clase {
		color: #ffffff;
	}
	
	/* Aplica todos los estilos que desees aquí. */
</style>
`;
// La siguiente línea sobrescribe el contenido del iframe con los nuevos estilos.
doc.body.innerHTML = doc.body.innerHTML + nuevosEstilos;

Control extra

A esta función debería agregar otro condicional para que en el caso de que en cierto límite de tiempo el iframe no se cargue correctamente, el intervalo deje de ejecutarse.

Para ello podemos modificar la función agregando al principio los siguientes condicionales (al final te daré todo el código completo para que no tengas que estar adivinando dónde ubicarlo, solo separo el código para que sea más fácil explicar su funcionamiento).

let iteracionContador = 0;
let iteracionMaxima = 10;
const variableDeIntervalo = setInterval( modificarIframe, 500 );
function modificarIframe() {
	// Chequeo que el contador de iteraciones no supere el iterador máximo para evitar el consumo de recursos.
	if ( iteracionContador === iteracionMaxima ) {
		// Paro el intervalo.
		clearInterval( variableDeIntervalo );
		return;
	}
}

Código completo

Ahora sí, te dejo el código completo con todo lo explicado anteriormente.

( function () {
	let iteracionContador = 0;
	let iteracionMaxima = 10;
	const variableDeIntervalo = setInterval( modificarIframe, 500 );
	function modificarIframe() {
		// Chequeo que el contador de iteraciones no supere el iterador máximo para evitar el consumo de recursos.
		if ( iteracionContador === iteracionMaxima ) {
			// Paro el intervalo.
			clearInterval( variableDeIntervalo );
			return;
		}
		
		// Busco el iframe en el DOM.
		let iframeAModificar = document.querySelector( 'iframe' );
		// Verifico si el iframe ya está cargado.
		if (
			! iframeAModificar
			|| typeof iframeAModificar === 'undefined'
		) {
			iteracionContador++;
			return;
		}
		
		// Detengo el intervalo para evitar el consumo de recursos del navegador.
		clearInterval( variableDeIntervalo );
		// Obtengo el contenido del elemento iframe.
		let doc = iframeAModificar.contentDocument;
		let nuevosEstilos = `
		<style>
			.alguna-clase {
				color: #ffffff;
			}
			
			/* Aplica todos los estilos que desees aquí. */
		</style>
		`;
		// La siguiente línea sobrescribe el contenido del iframe con los nuevos estilos.
		doc.body.innerHTML = doc.body.innerHTML + nuevosEstilos;
	}
} )();

El get_post_meta de Gutenberg se llama getEditedPostAttribute(‘meta’)

Si como yo estás iniciándote en el mundo del desarrollo personalizado de bloques de Gutenberg, seguramente llegarás al momento donde necesitarás implementar valores del post meta tal como hacíamos en PHP con la función get_post_meta.

Bueno, la función equivalente en el mundo Javascript se llama getEditedPostAttribute( 'meta' ) aunque hay que tener algunos puntos en consideración que te explicaré a continuación.

const meta = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );

Si el posta meta fue previamente registrado y configurado para su uso con la API ya solo te queda obtener el valor de la variable meta:

const meta = wp.data.select( 'core/editor' ).getEditedPostAttribute( 'meta' );
const metaExample = meta[ 'mi_valor_meta' ];

Cómo registrar el post meta

Para asegurarte que el post meta esté disponible en Gutenberg tiene que estar registrado y con el atributo show_in_rest con el valor true.

function mg_registrar_post_meta() {
	register_post_meta(
		'post',
		'mi_valor_meta',
		[
			'show_in_rest' => true,
			'single' => true,
			'type' => 'string',
		]
	);
}
add_action( 'init', 'mg_registrar_post_meta');

Cómo obtener el meta de otro post

Si quieres obtener el post meta de otro post, puedes usar la función Javascript getEntityRecord, y pasarle el ID del post que quieres obtener:

const { meta } = wp.data.select( 'core' ).getEntityRecord( 'postType', 'post', 36 );

La función javascript getEntityRecord es el equivalente al get_post que utilizamos en PHP.

Preload el CSS de wp-block-library

Al día de la fecha, WordPress sigue encolando el CSS de los bloques por defecto de Gutenberg sin ningún tipo de optimización (defer, async o preload), lo cual hace saltar las alarmas de cualquier test de performance de sitios webs, ¿Cómo podemos resolverlo?

Simplemente basta con que agregues el siguiente bloque de código a tu functions.php o plugin personalizado.

/**
 * Función que agregar el preload a archivos CSS.
 */
function agregar_rel_preload( $html, $handle, $href, $media ) {
    if ( is_admin() ) {
		return $html;
	}
	
	// Aplicar rel preload solo a los assets que estén dentro de este array.
	$assets = [ 'wp-block-library' ];
	if ( ! in_array( $handle, $assets ) ) {
		return $html;
	}
    $html = <<<EOT
<link rel='preload' as='style' id='$handle' href='$href' type='text/css' media='$media' />
EOT;
    return $html;
}
add_filter( 'style_loader_tag', 'agregar_rel_preload', 10, 4 );

Este código puede servirte para agrear el rel="preload" de cuaqluier CSS, solo basta que agregues el handle del fichero en el array de la línea 10.

Quitar las etiquetas y categorías por defecto de las entradas

WordPress por defecto asigna dos taxonomías a nuestras entradas: las clásicas categorías y etiquetas. El tema es que no siempre las necesitamos y mi filosofía de trabajo es que si algo no es necesario para el cliente mejor quitarlo para evitar posibles dolores de cabeza.

Remover estas taxonomías de las entradas es muy sencillo, basta con agregar el siguiente código al functions.php de nuestro tema o bien a un fichero de configuración de un plugin.

/**
 * Esta función quita las etiquetas de las entradas.
 */
function mgwp_unregister_tags() {
   unregister_taxonomy_for_object_type( 'post_tag', 'post' );
}
add_action( 'init', 'mgwp_unregister_tags' );
/**
 * Esta función quita las categorías de las entradas.
 */
function mgwp_unregister_categories() {
   unregister_taxonomy_for_object_type( 'category', 'post' );
}
add_action( 'init', 'mgwp_unregister_categories' );

Como puedes ver la función unregister_taxonomy_for_object_type nos permite quitar cualquier taxonomía de cualquier tipo de post.

En caso de que necesites quitar las dos taxonomías a la vez, une las dos líneas en el mismo action ⬇️ :

/**
 * Esta función quita las categorías y las etiquetas de las entradas.
 */
function mgwp_unregister_categories() {
   unregister_taxonomy_for_object_type( 'post_tag', 'post' );
   unregister_taxonomy_for_object_type( 'category', 'post' );
}
add_action( 'init', 'mgwp_unregister_categories' );
Carga segura de ficheros SVG limitada por roles de usuario

Carga segura de ficheros SVG en WordPress

WordPress por defecto no permite la carga de ficheros SVG debido a que pueden contener código malicioso.

Aún así, a veces tendremos que permitir la carga de este tipo de ficheros aunque podríamos limitarlo a uno o más tipos de roles de usuarios (administradores, editores o autores) para asegurarnos que son personas responsables que saben lo que están cargando al sitio Web.

Aquí les dejo el código que cumple exactamente con esa función:

<?php
/**
 * Permito cargar ficheros SVG's solamente a usuarios con
 * el rol de administrador.
 *
 * @param $mimes
 *
 * @return mixed
 */
function mg_agregar_svg_mime_type( $mimes ) {
	// Guardo en una variable el usuario actual.
	$usuario = wp_get_current_user();
    // Una vez que compruebo que el usuario tiene el rol adecuado,
    // Agrego el tipo de fichero (SVG) a la lista de los permitidos
    // por WordPress.
	if ( in_array( 'administrator', $usuario->roles ) ) :
		$mimes['svg'] = 'image/svg+xml';
	endif;
	return $mimes;
}
add_filter( 'upload_mimes', 'mg_agregar_svg_mime_type' );

Bola Extra 🌟
Aquí te dejo el artículo «Por qué no es buena idea usar vectores SVG en WordPress» de Fernando Tellado donde explica con detalles los problemas de seguridad que pueden tener este tipo de ficheros.

Insertar Google AdSense automáticamente en tus artículos de WordPress

Cómo añadir publicidad AdSense automáticamente en tus artículos de WordPress

Hace poco un cliente me pidió que agregara publicidad AdSense en los artículos de su blog, alrededor de unas 6600 entradas, con lo cual tenía que sentarme con tranquilidad y encontrar la mejor solución.

Básicamente hay dos formas de agregar publicidad AdSense o cualquier otro tipo de contenido ajeno a WordPress dentro de nuestros artículos: mediante el uso de ShortCodes/Bloques de Gutenberg (lo que descartaba de cuajo dada la cantidad de artículos a modificar manuamente) o en forma automática como lo explicaré en este artículo.

👍🏻 ¿Por qué sugiero realizarlo de esta manera?

  • Contenido limpio: No vamos a agregar absolutamente nada a nuestros artículos, seguirán estando limpios como cuando se escribieron por primera vez.
  • Gestión desde un único lugar: Manejando algunas variables (que podemos configurar desde un página de opciones personalizadas) seremos capaces de activar/desactivar o modificar el funcionamiento de las publicidades de toda la Web.
  • Evitar herrores umanos: Los autores de entradas no tienen por qué estar acordándose de agregar códigos, shortcodes o bloques especiales para incrustar publicidades. Ellos a lo suyo y nosotros como programadores nos encargamos del resto.

Solución que se me ocurrió

Luego de darle algunas vueltas a la cabeza se me ocurrió la siguiente idea: Insertar el código de Google AdSense automáticamente luego de un número X de ocurrencias de un string específico dentro del cuerpo del artículo utilizando el filtro the_content.

Lo que en castellano podríamos traducir como: «Mira, agarra todo el contenido del artículo y busca la segunda vez que aparezca este código «</p>», acto seguido inserta este código HTML que te paso».

🙂 La idea me cuadraba, ahora a ver cómo podía traducirlo a PHP.

Aquí les dejo el código con los correspondientes comentarios para su entendimiento.

/**
 * Esta función agrega contenido luego de un número
 * dado de párrafos.
 */
function mg_inserta_publi_en_contenido( $content ) {
	
	// Nos aseguramos que solo afecte a los artículo de un post.
	// Puede borrarse o modificarse según las necesidades.
	if( ! is_singular( 'post' ) ) return;
	// ¿Después de qué párrafo agregamos la publicidad?
	$numero_parrafo = 2; // Lo ideal es utilizar algúna página de opción para dinamizar este valor.
	// Publicidad a Insertar.
	// Lo ideal es dinamizar este valor.
	$publicidad = 	'<ins class="adsbygoogle" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-123456789" data-ad-slot="123456788"></ins>
					<script>
						(adsbygoogle = window.adsbygoogle || []).push({});
					</script>';
	// Esta función nos ayudará a encontrar la posición exacta para insertar la publicidad.
	// strposX() es una función personalizada que busca recursivamente una posición específica dentro de un string.
	// "\n" es el código para el nuevo "párrafo" en WordPress. Se puede modificar este valor para buscar por otro código.
	$posicion = strposX( $content, "</p>", $numero_parrafo);
	/*
	* Una vez que tenemos todos los valores, solo se debe devolver
	* el resultado de la función substr_replace con los argumentos
	* previamente calculados.
	*/
	return substr_replace( $content, $publicidad, $posicion, 0 );
}
add_filter( 'the_content', 'mg_inserta_publi_en_contenido', 1 );

Explicación de las líneas más importantes

9. Aplicamos este condicional para que solo afecte a las páginas de artículos (caso contrario podría agregar publicidades en plantillas no deseadas).
Puedes cambiar el condicional según lo que necesites.
12. ¿Después de qué número de párrafos se agrega la publicidad?
Tal como dice el comentario, lo ideal sería que este valor podamos obtenerlo de alguna configuración en WordPress (página de opciones).
16. En este caso estoy insertando una publicidad de Google AdSense pero podría ser cualquier HTML.
24. Llamo a una función personalizada ya que la función strpos() de PHP no permite por defecto búsquedas recursivas.
En esta línea también podríamos reemplazar la lógica a buscar, en lugar de la finalización de un párrafo (</p>) podríamos indicar etiquetas de imágenes, luego de un blockquote, un encabezado h2, etc etc.
31. Con todos los valores ya calculados solo se debe llamar a la función substr_replace() de PHP para realizar el reemplazo de cadenas de textos.

Y esta es la función personalizada que nos permitirá hacer una búsqueda recursiva de un string dentro de otro string:

/**
 * Find the position of the Xth occurrence of a substring in a string
 * @param $haystack
 * @param $needle
 * @param $number integer > 0
 * @return int
 */
function strposX($haystack, $needle, $number){
	if( $number == '1' ){
		return strpos($haystack, $needle);
	}elseif( $number > '1' ){
		return strpos($haystack, $needle, strposX($haystack, $needle, $number - 1) + strlen($needle));
	}else{
		return error_log('Error: Value for parameter $number is out of range');
	}
}

El siguiente vídeo es una demo para comprobar que funciona la inserción de un código «dummy» de HTML luego del 2do párrafo ⬇️


🎉 Genial, por un lado tenemos los artículos limpios, no agregué carga de trabajo para la escritura de nuevas entradas y junto a un panel de control donde el usuario Administrador pueda hacer sus ajustes esta solución funciona a la perfección.

Ahora ya tienes a mano una herramienta para insertar cualquier tipo de contenido dentro de tus posts de WordPress.

Cómo agregar «async» o «defer» a los scripts en WordPress

Cómo agregar «async» o «defer» a los scripts en WordPress

Los atributos async o defer nos ayudan a optimizar el tiempo de carga y ejecución de los distintos recursos Javascript de nuestra Web.

Pero lamentablemente la función wp_register_script(), con la que se encolan los distintos recursos Javascripts, no tiene un parámetro para agregar o indicar de alguna forma estos valores.

Es por este motivo que en la versión 4.1 de WordPress se agregó el filtro script_loader_tag que nos permite modificar el string final de la etiqueta <script>.

Aprovechando este filtro he creado la siguiente función para agregar en forma automática cualquiera de estos dos valores.

/**
 * Esta función agrega los parámetros "async" y "defer" a recursos de Javascript.
 * Solo se debe agregar "async" o "defer" en cualquier parte del nombre del 
 * recurso (atributo "handle" de la función wp_register_script).
 *
 * @param $tag
 * @param $handle
 *
 * @return mixed
 */
function mg_add_async_defer_attributes( $tag, $handle ) {
	// Busco el valor "async"
	if( strpos( $handle, "async" ) ):
		$tag = str_replace(' src', ' async="async" src', $tag);
	endif;
	// Busco el valor "defer"
	if( strpos( $handle, "defer" ) ):
		$tag = str_replace(' src', ' defer="defer" src', $tag);
	endif;
	return $tag;
}
add_filter('script_loader_tag', 'mg_add_async_defer_attributes', 10, 2);

¿Cómo utilizar la función?

Tal como se describe en el comentario de la función, solo debes agregar la palabra async o defer en cualquier posición del parámetro handle de la función wp_register_script y luego encolarlo con la función wp_enqueue_script.

// Ejemplo con "async".
wp_register_script( 'fichero-js-async', get_stylesheet_directory_uri() . '/js/fichero.js', [], false, true );
wp_enqueue_script( 'fichero-js-async' );
// Ejemplo con "defer".
wp_register_script( 'fichero-js-defer', get_stylesheet_directory_uri() . '/js/fichero.js', [], false, true );
wp_enqueue_script( 'fichero-js-defer' );

La próxima vez que GTMetrix o Google Lighthouse te regañen por ficheros javascripts que bloquean el renderizado de tu HTML ya tienes aquí una simple solución para implementar en tu código.


🗒 Si quieres saber un poco más sobre al diferencia entre async y defer, te recomiendo este artículo de Juan Padial que lo explica a la perfección.

Desactivar Sitemap WordPress 5.5

Cómo desactivar el Sitemap de WordPress 5.5

La última versión 5.5 de WordPress introdujo la creación de un Sitemap XML por defecto en el Core aunque la gran mayoría de los sitios Webs utilizan plugins como Yoast que ya lo están generado siguiendo sus configuraciones.

Si vas a utilizar este tipo de plugins, lo ideal sería que desactives esta nueva funcionalidad con el siguiente y simple código con el fin de optimizar los recursos del servidor:

add_filter( 'wp_sitemaps_enabled', '__return_false' );

¡Y eso es todo!, tan simple como agregar esta línea en tu functions.php o tu plugin personalizado y a correr.

Contact Form 7 - Cómo agregar CSS personalizado

Estilos CSS personalizados para Contact Form 7

El plugin Contact Form 7 tiene un fichero de CSS para dar estilos mínimos al formulario pero estos no siempre concuerdan con la estética de nuestra Web. Sigue los pasos de este artículo para que puedas aplicar tus propias líneas de CSS y hacer que tu formulario luzca perfecto.

Desgranando el HTML

Lo primero que tendrás que hacer es entender el HTML que genera este plugin con sus correspondientes clases, para que luego puedas atacarlas desde tu tema hijo o bien desde el personalizador.

El formulario básico

Formulario básico de Contact Form 7
Estilos de Contact Form 7 en el tema Twenty Twenty

A modo de ejemplo voy a transcribir parte de la estructura de HTML que general el Contact Form 7 y sus respectivas clases:

<form class="wpcf7-form"> <!-- (1) -->
    <p><!-- (2) -->
        <label> Tu nombre (obligatorio)<br><!-- (3) -->
            <span class="wpcf7-form-control-wrap your-name"><!-- (4) -->
                <input type="text" name="your-name" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required"><!-- (5) -->
            </span>
        </label>
    </p>
    <p>
        <input type="submit" value="Enviar" class="wpcf7-form-control wpcf7-submit"><!-- (6) -->
    </p>
</form>

Como podrás ver, agregué un par de comentarios en el HTML para explicar cada uno de los puntos:

  1. Puedes ver que todo el formulario está agrupado bajo el elemento <form> con la clase .wpcf7-form la cual te servirá para atacar los estilos en forma general.
    Por ejemplo, podrías asignarle el atributo display: grid para cambiar la estructura general del mismo.
  2. Cada campo y hasta el botón de enviar se encierran automáticamente con un elemento <p>. Poco más que agregar aquí.
  3. Los campos que damos de alta en el Administrador de WordPress (a excepción del botón enviar) se encierran dentro de la etiqueta label.
  4. A su vez, cada campo se encierra en un span con algunas clases que nos facilitarán su selección para aplicar estilos. Las clases que se agregan son:
    • wpcf7-form-control-wrap: clase genérica para representar cualquier campo.
    • [campo name del input]: agrega también una clase dinámica con el mismo nombre del atributo name del input. En el ejemplo, agrega la clase your-name.
  5. Ahora sí ya estás en el input mismo, donde CF7 agrega una serie de clases en forma automática, a saber:
    • wpcf7-form-control: clase genérica para todos los campos.
    • wpcf7-text: clase con el tipo de campo configurado en el Administrador de WordPress (más adelante te mostraré las clases de los otros tipos de campos).
    • wpcf7-validates-as-required: CF7 agregará esta clase en caso de que el campo sea obligatorio.

Las clases para cada tipo de campo de Contact Form 7

  • Campo de texto => wpcf7-text
  • Campo de email => wpcf7-email
  • Campo de URL => wpcf7-url
  • Campo de teléfono => wpcf7-tel
  • Campo numérico => wpcf7-num
  • Campo fecha => wpcf7-date
  • Campo de textarea => wpcf7-textarea
  • Campo desplegable => wpcf7-select
  • Campo de verificación => wpcf7-checkbox
  • Botones de selección => wpcf7-radio
  • Campo de aceptación => wpcf7-acceptance
  • Campo de archivo => wpcf7-file

Mensajes

Tanto como si el formulario se envía correcta o incorrectamente, el plugin genera un mensaje con una estructura de HTML definida y algunas clases que podrás utilizar para modificar su estilo.

Mensaje de éxito

Mensaje de éxito de Contact Form 7
Mensaje de éxito de Contact Form 7
<!-- mensaje de éxito -->
<form class="wpcf7-form sent">
    <div class="wpcf7-response-output wpcf7-display-none wpcf7-mail-sent-ok">Gracias por tu mensaje. Ha sido enviado.</div>
</form>

Aquí puedes ver el HTML del mensaje exitoso que genera el plugin además de agregar la clase sent al formulario.

Mensaje de error

Mensaje de error de Contact Form 7
Mensaje de error de Contact Form 7
<!-- mensaje de error -->
<form class="wpcf7-form invalid">
    <div class="wpcf7-response-output wpcf7-display-none wpcf7-validation-errors">Uno o más campos tienen un error. Por favor, revísalos e inténtalo de nuevo.</div>
</form>

Al igual que el mensaje anterior, el plugin genera un HTML específico para el mensaje y también agrega la clase invalid al formulario.

Ejemplos de modificaciones

Cambios en el formulario

¿Qué tal si agregamos borde, cambiamos de color y ponemos un poco de sombra? Así quedaría el CSS final.

.wpcf7-form {
    background-color: #ffffff;
    border: 3px solid #000000;
    box-shadow: 0px 9px 21px 6px rgba(0,0,0,0.5);
    padding: 2em;
    overflow: none !important;
}

Campos con bordes animados

Ya sabes que tienes clases que afectan a todos los campos independientemente del tipo que sean. Vamos a hacer uso de esta clase para darle un toque más original al formulario.

.wpcf7-form .wpcf7-text,
.wpcf7-form .wpcf7-textarea {
    background-color: transparent ;
    border-bottom: 1px solid #001;
    border-top: 1px solid transparent;
    border-left: 1px solid transparent;
    border-right: 1px solid transparent;
    margin-bottom: 40px;
	outline: none;
	transition: 0.4s border;
}
.wpcf7-form .wpcf7-text:focus,
.wpcf7-form .wpcf7-textarea:focus,
.wpcf7-form .wpcf7-text:hover,
.wpcf7-form .wpcf7-textarea:hover {
	border: 1px dashed #001;
}

Editando el mensaje de éxito

Podemos darle al mensaje de éxito un toque más parecido a las alertas de Bootstrap. Como verás, solo basta con atacar a la clase wpcf7-mail-sent-ok que es la que se agrega al mensaje en cuanto el formulario se envía correctamente.

.wpcf7-mail-sent-ok {
    background-color: #d4edda;
    border: 2px solid #c3e6cb;
    border-radius: .55rem;
    display: block;
    color: #155724;
    font-family: roboto;
    margin-bottom: 1rem;
    padding: .75rem 1.25rem;
    position: relative;
}

Como puedes ver, la estructura de HTML puedes modificarla fácilmente desde el configurador de formularios y la estética puedes cambiarla con algunas líneas de CSS seleccionando las clases que Contact Form 7 agrega automáticamente.

Ánimo y a ajustar los colores de esos formularios 💪🏻

Página 1 de 13

Funciona con WordPress & Tema de Anders Norén