Básicamente crear un bloque consiste en hablar con WordPress y decirle.

"Oye, mete esta funcionalidad por favor".

Eso podemos hacerlo desde el functions.php de nuestro theme activo o directamente creando un plugin.

Yo te recomiendo tirar por la vía de crear el plugin porque así puedes activarlo y desactivarlo y llevártelo a otro theme. Es decir, tenerlo como algo independiente.

Yo voy a crear un plugin que se llama Mi Bloquesito. Así, originalidad total y suprema.

En la carpeta /wp-content/plugins/ creo la carpeta mi-bloquesito y dentro el archivo mi-boquesito.php

<?php
/**
 * Plugin Name: Mi Bloquesito
 * Description: Crear un bloque pa Gutenberg
 * Author: Salamarkesa
 * Version: 1.0
*/

Recuerda: Cómo crear un plugin en WordPress

Y ya está, lo único que falta es dar las instrucciones adecuadas que consisten en:

  • Cargar los elementos para mostrar el bloque en el editor
  • Cargar los elementos para mostrar el bloque en el front

Y ya está.

// Cargar los elementos necesarios para el editor en el back
add_action('enqueue_block_editor_assets', 'mi_bloquesito_elementos_editor');

// Cargar los elementos necesarios para el front
add_action('wp_enqueue_scripts', 'mi_bloquesito_elementos_front');

function mi_bloquesito_elementos_editor(){

	wp_enqueue_script(
 		'mi-bloquesito-editor-js', // Identificador
		plugin_dir_url( __FILE__ ) . 'js/mi-bloquesito-editor.js', // URL
		array('wp-blocks', 'wp-element'), // Dependencias
		filemtime( dirname( __FILE__ ) . '/js/mi-bloquesito-editor.js') // Última modificación
	);

	wp_enqueue_style(
		'mi-bloquesito-editor-css', // Identificador
		plugin_dir_url( __FILE__ ) . 'css/mi-bloquesito-editor.css',  // URL
		array('wp-edit-blocks'), // Dependencias
		filemtime(dirname( __FILE__ ) . '/css/mi-bloquesito-editor.css') // Última modificación
	);

}

function mi_bloquesito_elementos_front(){

	wp_enqueue_style(
		'wp-block-misha-newsletter-css', // Identificador
		plugin_dir_url( __FILE__ ) . 'css/mi-bloquesito-front.css',  // URL
		array(), // Dependencias (ninguna)
		filemtime(dirname( __FILE__ ) . '/css/mi-bloquesito-front.css') // Última modificación
	);

}

Fíjate que añadimos como parámetro en la carga de los elementos la marca de tiempo de la última modificación, tirando de la función de PHP filemtime(). Eso es así para que puedas editarlo y hacer pruebas y que se te cargue el nuevo archivo cuando esté modificado.

Y para darle el estilo usamos lenguaje CSS.

Para llevar un cierto orden, voy a guardar los archivos css en una carpeta llamada css y los archivos javascript en una carpeta llamada js, quedando finalmente este árbol de archivos.

La gracia más graciosa del asunto está en el archivo mi-bloquesito-editor.js, ya que será la semilla de nuestro bloque. Donde lo vamos a definir como tal.

En ese archivo ponemos algo como esto:

( function( blocks, element ) {

const el = element.createElement;

const { registerBlockType } = blocks;

const iconitoBloque = el('svg', { width: 20, height: 20 },
	el( 'path',
		{
			d: "m 10 2 l -8 18 h 16 z"
		}
	)
);

registerBlockType( 'salamarkesa/mi-bloquesito', {
	title: 'Mi Bloquesito',
	icon: iconitoBloque,
	category: 'widgets',
	keywords: [ 'salamarkesa', 'bloquesito' ],

	// La función que muestra el bloque en el editor
	edit: function( props ) {
		return (
			el( 'div', {  },
				'HOLA, SOY EL BLOQUESITO EN EL EDITOR'
			)
		);
	},

	// La función que muestra el bloque guardado en el front
	save: function( props ) {
		return (
			el( 'div', {},
				'HOLA, SOY EL BLOQUESITO EN EL FRONT'
			)
		);
	},
} );
} )(
window.wp.blocks,
window.wp.element,
);

Las distintas partes del código están bastante diferenciadas.

  • La definición del iconito
  • La definición del bloque en el editor
  • La definición del bloque una vez guardado y visto en la parte del front

En este caso la parte más rara es la menos importante, que es la definición del iconito que le agregaremos al bloque y en la que hemos agregado un path SVG. Por si no lo sabes, un path SVG no es más que un conjunto de coordenadas para pintar algo.

En este caso hemos pintado un triangulo en un lienzo de 20 x 20 con "m 10 2 l -8 18 h 16 z".

  • m 10 2 dice muévete al punto (x, y) = (10, 2)
  • l -8 18 dice dibuja una línea hacia atrás -8 y hacia abajo 18
  • h 16 dice dibuja una línea horizontal 16 unidades a la derecha
  • y la z dice cierra el camino

¿Qué tenemos?

Pues un triángulo:

Lo normal es usar un programa de diseño gráfico y exportar lo que dibujes a SVG y pegarlo y punto.

El caso es que si activamos el plugin y vamos al editor, ya podemos ver el bloque disponible:

Para añadirlo al contenido pues pulsamos encima y pues se añade, quedando así:

Y si le damos a publicar el contenido o a vista previa, en el front lo veremos así:

Y eso está muy bonito pero me preguntarás:

¿Por qué quiero que el bloque salga distinto en el editor y en el front?

Pues puede ser que en el editor quieras ponerle algún CSS especial o ponerle por ejemplo un input para escribir algo que luego ya aparezca fijo en el front.

Por ejemplo, los típicos bloques de insertar elementos como videos de Youtube muestran en la parte del editor el campo para meter la URL del vídeo pero una vez renderizado en el front, se carga el vídeo con esa URL que has especificado.

Ejemplo de bloque

Vamos a crear un bloque pero esta vez con otro iconito y con una utilidad un poco más realista.

Haremos un cajetín para suscribirse como este:

Quizá te crees que es un mundo pero es lo mismo que antes, solo añadiendo unos toques.

El código javascript:

( function( blocks, element ) {

	const el = element.createElement;

	const { registerBlockType } = blocks;

	const svgAvionPapel = el('svg', { width: 20, height: 20 },
		el( 'path',
			{
				d: "M17.218,2.268L2.477,8.388C2.13,8.535,2.164,9.05,2.542,9.134L9.33,10.67l1.535,6.787c0.083,0.377,0.602,0.415,0.745,0.065l6.123-14.74C17.866,2.46,17.539,2.134,17.218,2.268 M3.92,8.641l11.772-4.89L9.535,9.909L3.92,8.641z M11.358,16.078l-1.268-5.613l6.157-6.157L11.358,16.078z"
			}
		)
	);

	registerBlockType( 'salamarkesa/cajetin-suscribirse', {
		title: 'Cajetín de suscribirse',
		icon: svgAvionPapel,
		category: 'widgets',
		keywords: [ 'salamarkesa', 'suscribirse' ],

		// La función que muestra el bloque en el editor
		edit: function( props ) {
			return (
				el( 'div', { className: props.className },
					el( 'div', { className: 'cajetin-suscribirse' },
						el( 'div', {},
							'E-mail'
						),
						el( 'div', {},
							'Suscribirme'
						)
					)
				)
			);
		},

		// La función que muestra el bloque guardado en el front
		save: function( props ) {
			return (
				el( 'div', { className: props.className },
					el( 'form', { className: 'cajetin-suscribirse' },
						el( 'input', { 'type': 'email', 'placeholder' : 'E-mail' } ),
						el( 'button', {}, 'Suscribirme' )
					)
				)
			);
		},
	} );
} )(
window.wp.blocks,
window.wp.element,
);

Lo único que cambia es el iconito, que ahora tiene un svg con un path un poco más elaborado.

El típico avioncito de papel:

Y bueno ahora sí que el contenido del bloque en el editor es distinto al del front. En el editor ponemos simplemente dos div con texto, porque en el editor no necesitamos que tenga funcionalidad ni que salga un input de texto.

Y en el front sí que mostramos ya el input y el button como tal.

El código CSS para la parte del editor:

.wp-block-salamarkesa-cajetin-suscribirse{
background: rgb(131,58,180);
color: #fff;
padding: 3rem;
}

.cajetin-suscribirse{
border: 2px solid #000;
display: flex;
justify-content: space-between;
max-width: 40rem;
margin-left: auto;
margin-right: auto;
font-size: 1.3rem;
}

.cajetin-suscribirse div:first-child{
padding: 1rem 2rem;
width: 100%;
}

.cajetin-suscribirse div:last-child{
background-color: #000;
padding: 1rem 2rem;
font-weight: bold;
}

Como verás, en este caso no me ha dado la gana ponerle ningún degradado. Lo he dejado en color plano, si de todas formas es para yo verlo en el back al editar.

El código CSS para la parte del front:

.wp-block-salamarkesa-cajetin-suscribirse{
background: rgb(131,58,180);
color: #fff;
background: linear-gradient(90deg, rgba(131,58,180,1) 0%, rgba(253,29,29,1) 50%, rgba(252,176,69,1) 100%);
padding: 3rem;
}

.cajetin-suscribirse{
border: 2px solid #000;
display: flex;
justify-content: space-between;
max-width: 40rem;
margin-left: auto;
margin-right: auto;
font-size: 1.3rem;
}

.cajetin-suscribirse input[type="email"]{
padding: 1rem 2rem;
border: 0;
width: 100%;
color: #fff;
background: none;
display: block;
}

.cajetin-suscribirse input[type="email"]:focus{
color: #fff;
}

.cajetin-suscribirse input[type="email"]::placeholder{
color:rgba(255,255,255,0.5);
}

.cajetin-suscribirse button{
background-color: #000;
color: #fff;
padding: 1rem 2rem;
font-weight: bold;
display: block;
border-radius: 0;
border: none;
}

Y ahora sí pues ya es un input en el que puedo escribir y le he metido un degradado de fondo y tal.

¿Quieres descargarte el código del ejemplo?

Aquí lo tienes.