12k
All articles

Cómo crear un tema hijo de WordPress

Crea un tema hijo de WordPress para conservar tus cambios al actualizar el tema principal. Configura temas clásicos y de bloques, carga estilos y sobrescribe plantillas.

OpenReplay Team
OpenReplay Team
Cómo crear un tema hijo de WordPress

Para crear un tema hijo de WordPress, añade una carpeta nueva en wp-content/themes, coloca dentro un archivo style.css cuya cabecera Template coincida con el nombre de la carpeta del tema padre y actívalo. El tema hijo hereda las plantillas, los estilos y la funcionalidad del tema padre, y solo contiene tus cambios.

Si alguna vez has editado directamente los archivos de un tema y después has visto cómo la siguiente actualización los borraba, un tema hijo es la forma de evitarlo.

Esta guía explica la configuración que funciona en el WordPress actual. Recorre un tema hijo clásico con una carga correcta de estilos (enqueueing), la sobrescritura de plantillas y funciones, qué cambia en los temas de bloques como Twenty Twenty-Four y los casos en los que no necesitas ningún tema hijo.

Puntos clave

  • El único archivo estrictamente obligatorio en un tema hijo es style.css. Su cabecera Template debe coincidir exactamente con el nombre de la carpeta del tema padre; para Twenty Twenty-Four, el valor es twentytwentyfour.
  • El functions.php de un tema hijo no sustituye al del tema padre. WordPress carga ambos, y el del hijo se ejecuta primero.
  • Carga los estilos del tema hijo con wp_enqueue_style() en el hook wp_enqueue_scripts, no con @import.
  • Para sobrescribir una plantilla, una parte de plantilla o un patrón, coloca en el tema hijo un archivo con el mismo nombre. Los patrones de bloques también necesitan el mismo Slug.
  • Los cambios que deben mantenerse tras un cambio de tema, como los tipos de contenido personalizados, deben ir en un plugin, no en un tema hijo.

¿Por qué falla editar directamente el tema padre?

Cuando un tema se actualiza, WordPress sustituye sus archivos por los de la nueva versión, de modo que cualquier modificación que hayas hecho dentro de la carpeta del tema se pierde. Un tema hijo guarda tus cambios en una carpeta independiente que las actualizaciones nunca tocan. La guía de temas hijo del Theme Handbook lo presenta como la forma de recibir las actualizaciones del tema padre sin renunciar a tus propias modificaciones. El sistema de temas se limita a dos niveles, un padre y un hijo, así que no puedes instalar un tema «nieto» por encima.

Cómo crear un tema hijo en WordPress (temas clásicos)

Un tema hijo clásico necesita una carpeta, un style.css con la cabecera Template y, en la mayoría de los casos, un functions.php que cargue la hoja de estilos. La estructura es la misma de carpeta, style.css y functions.php descrita en nuestra guía para crear un tema responsive de WordPress con Bootstrap. La diferencia es que el tema hijo solo contiene lo que modifica.

wp-content/themes/
├── twentytwentyfour/
└── tt4-child/
    ├── style.css
    └── functions.php

La cabecera de style.css

Solo style.css es estrictamente obligatorio. La documentación de la hoja de estilos principal indica que cualquier tema necesita al menos la cabecera Theme Name, y un tema hijo añade además Template.

/*
 * Theme Name:  TT4 Child
 * Template:    twentytwentyfour
 * Version:     1.0.0
 * Text Domain: tt4-child
 */

Template recibe el nombre de la carpeta del tema padre, no su nombre visible. Si ambos no coinciden carácter por carácter, WordPress no vinculará el tema hijo con su padre.

Cargar hojas de estilos con enqueue en lugar de @import

Carga los estilos del tema hijo con wp_enqueue_style() en el hook wp_enqueue_scripts, no con @import. Muchos tutoriales antiguos cargan los estilos del tema padre con @import al principio del style.css del hijo. Este enfoque está obsoleto:

/* Outdated: do not use */
@import url("../twentytwentyfour/style.css");

El navegador solo descubre el archivo importado después de haber descargado y analizado la hoja de estilos del tema hijo, por lo que las dos peticiones se realizan una tras otra y ambas bloquean el renderizado. Además, la importación queda fuera del sistema de enqueue de WordPress, lo que significa que WordPress no puede gestionar sus dependencias, versionarla ni evitar que se cargue por duplicado.

La alternativa es wp_enqueue_style() llamada desde una función enganchada a wp_enqueue_scripts. Ese mismo hook también carga scripts, como se explica en nuestro artículo sobre cómo añadir JavaScript personalizado a los temas de WordPress.

<?php
// functions.php
add_action( 'wp_enqueue_scripts', 'tt4child_enqueue_styles' );

function tt4child_enqueue_styles() {
	wp_enqueue_style(
		'tt4child-style',
		get_stylesheet_uri(), // the active (child) theme's style.css
		array(),              // $deps: handles that must load first
		'1.0.0'               // $ver: appended as a cache-busting query string
	);
}

El código de enqueue adecuado para un tema hijo depende de lo que ya cargue el tema padre:

Qué carga el tema padreQué hace el tema hijo
Tanto su propia hoja de estilos como la del hijoNada
Solo su propia hoja de estilosCargar la del hijo con get_stylesheet_uri() (código anterior)
Solo la del tema activo, mediante get_stylesheet_uri()Cargar la del padre con get_parent_theme_file_uri( 'style.css' )
Nada (Twenty Twenty-Four, según el Handbook)Cargar la del hijo con get_stylesheet_uri()

Para el caso de la tercera fila, utiliza esto:

function tt4child_enqueue_styles() {
	wp_enqueue_style(
		'tt4child-parent-style',
		get_parent_theme_file_uri( 'style.css' )
	);
}

Para averiguar qué caso se aplica, busca wp_enqueue_style en el functions.php del tema padre o revisa las etiquetas <link> de hojas de estilos en el código fuente de la página. El orden de las hojas de estilos no es fijo: sigue el orden de las llamadas de enqueue, y el argumento $deps recibe un array de handles registrados que deben cargarse antes. Para que la hoja del hijo se imprima después de la del padre, pasa el handle del padre en $deps, tomando el nombre del handle del código del tema padre. Cuando la URL de la hoja de estilos del tema hijo es incorrecta, la petición devuelve un 404 y la página se renderiza solo con el CSS del padre. Una herramienta de session replay que registre las peticiones de red junto a la reproducción visual muestra la petición fallida al lado de la página sin estilos.

¿Cómo se sobrescriben las plantillas del tema padre?

Para sobrescribir una plantilla del tema padre, copia el archivo (no lo muevas) en la misma ruta relativa dentro del tema hijo. Cuando WordPress recorre la jerarquía de plantillas, revisa la carpeta del hijo antes que la del padre, de modo que se utiliza el archivo con el mismo nombre del tema hijo. Mover el archivo en lugar de copiarlo modifica el tema padre, y la siguiente actualización lo restaurará de todos modos.

twentytwentyfour/page.php  →  copy to  →  tt4-child/page.php

La misma regla se aplica a las partes de plantilla. También puedes añadir plantillas nuevas que el tema padre no tenga.

Sobrescribir funciones del tema padre

El functions.php de un tema hijo no sustituye al del padre. Según el Handbook, WordPress ejecuta ambos archivos, empezando por el del hijo y pasando inmediatamente al del padre. De este orden de carga se derivan dos consecuencias. Las funciones del padre envueltas en function_exists() (funciones pluggable) pueden redefinirse en el tema hijo. Cualquier otra función del padre tiene que desengancharse o complementarse. Tampoco pegues el código del functions.php del padre en el del hijo: declarar dos veces los mismos nombres de función detiene el sitio con un error fatal.

Una función pluggable en el tema padre tiene este aspecto:

// Parent theme
if ( ! function_exists( 'parenttheme_credit' ) ) {
	function parenttheme_credit() { /* ... */ }
}

Como el tema hijo se ejecuta primero, definir el mismo nombre en el hijo hace que se omita la versión del padre:

// Child theme
function parenttheme_credit() {
	echo '<p>Custom credit line</p>';
}

Si la función no es pluggable, elimínala con remove_action(), usando el mismo hook y la misma prioridad con los que se registró. Una llamada a remove_action() situada en el nivel superior del archivo del hijo se ejecuta antes de que el padre haya añadido su hook, así que todavía no hay nada que eliminar. Ejecútala desde after_setup_theme, que se dispara una vez cargados los archivos functions.php de ambos temas:

// Parent theme
add_action( 'init', 'parenttheme_setup_extra', 20 );

// Child theme
add_action( 'after_setup_theme', function () {
	remove_action( 'init', 'parenttheme_setup_extra', 20 );
} );

remove_filter() funciona del mismo modo con los filtros. Para ampliar una función del padre en lugar de sustituirla, engancha tu propia función al mismo hook con una prioridad posterior. La prioridad por defecto de add_action() es 10, y los números más altos se ejecutan más tarde:

add_action( 'parent_footer', 'tt4child_footer_extra', 20 );

¿Cómo funcionan los temas hijo con los temas de bloques?

Un tema hijo de un tema de bloques, como uno basado en Twenty Twenty-Four, a menudo solo necesita style.css y theme.json. La mayor parte de los estilos se define en theme.json, por lo que el Handbook señala que cargar style.css suele ser innecesario, y muchos temas hijo de bloques no tienen ningún functions.php.

Tema hijo clásicoTema hijo de bloques
Archivo obligatoriostyle.cssstyle.css
Dónde se definen los estilosstyle.css (cargado con enqueue)theme.json
functions.phpNormalmente sí, para el enqueueA menudo ninguno
PlantillasArchivos .php en la raíz del temaArchivos .html en templates/
Partes de plantillaArchivos .php como header.phpArchivos .html en parts/
PatronesArchivos PHP en patterns/ o register_block_pattern()Archivos PHP en patterns/
tt4-child/
├── style.css
├── theme.json
├── templates/
│   └── single.html
├── parts/
│   └── header.html
└── patterns/
    └── (same filename as the parent pattern).php

Para sobrescribir una plantilla, una parte o un patrón, añade un archivo con el mismo nombre. En el caso de los patrones, la cabecera Slug registrada también debe coincidir con la del padre, así que cópiala del archivo del tema padre:

<?php
/**
 * Title: Footer
 * Slug: parent-slug/pattern-name
 */
?>

Un theme.json mínimo fija el esquema y utiliza la versión 3, que requiere WordPress 6.6 o posterior:

{
	"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
	"version": 3,
	"styles": {
		"typography": {
			"lineHeight": "1.7"
		}
	}
}

Los archivos theme.json del padre y del hijo se combinan según unas reglas de fusión específicas, y los valores del hijo tienen prioridad. Las personalizaciones guardadas en el Editor del sitio también se almacenan en la base de datos y se sitúan por encima del tema hijo en el modelo de capas del Handbook. Si parece que se ignora una plantilla del tema hijo, borra la personalización guardada de esa plantilla en el Editor del sitio.

Cuándo no necesitas un tema hijo

Para pequeños ajustes visuales o funcionalidades, no necesitas un tema hijo. En un tema clásico, el CSS adicional del Personalizador basta para unas pocas reglas. Con un tema de bloques activo, el CSS personalizado se añade desde el panel Estilos del Editor del sitio. Los cambios funcionales, como los tipos de contenido personalizados, deben ir en un plugin para que sigan funcionando tras un cambio de tema. Si tus cambios crecen tanto que el tema hijo se vuelve difícil de gestionar, el Handbook sugiere hacer un fork del tema padre y convertirlo en un tema propio.

Conclusión

Un tema hijo se reduce a una carpeta y un style.css cuyo valor Template coincide con el nombre de la carpeta del tema padre. En los temas clásicos, añade el código de enqueue que corresponda a lo que carga el padre. En los temas de bloques, theme.json y los archivos de plantilla con el mismo nombre hacen el trabajo. Empieza comprobando qué hojas de estilos carga tu tema padre y, después, añade solo los archivos que realmente necesites modificar.

Preguntas frecuentes

¿Cuál es la diferencia entre get_template_directory_uri() y get_stylesheet_directory_uri() en un tema hijo?

Cuando hay un tema hijo activo, get_template_directory_uri() devuelve la URL del directorio del tema padre, mientras que get_stylesheet_directory_uri() devuelve la URL del directorio del tema hijo. Utiliza la variante stylesheet para los archivos almacenados en el tema hijo. Desde WordPress 4.7, get_theme_file_uri() suele ser la mejor opción: devuelve la copia del archivo en el tema hijo si existe y, en caso contrario, recurre al archivo del tema padre.

¿Por qué han desaparecido mis ajustes del Personalizador y las ubicaciones de los menús tras activar un tema hijo?

WordPress guarda los ajustes del Personalizador (theme mods) por separado para cada tema, asociados al nombre de la carpeta del tema activo, de modo que un tema hijo empieza con su propio conjunto vacío y no hereda los del padre. Tus menús siguen existiendo, pero tienes que volver a asignarlos a las ubicaciones de menú y volver a introducir o importar el resto de ajustes. Los ajustes del tema padre permanecen en la base de datos y se recuperan si vuelves a activar el padre.

¿Qué ocurre con un archivo de plantilla copiado en un tema hijo cuando se actualiza el tema padre?

La copia del tema hijo se mantiene exactamente como la guardaste, y WordPress sigue utilizándola en lugar del archivo actualizado del padre. Las correcciones de errores, los parches de seguridad o los cambios de marcado que el padre introduzca en ese archivo nunca llegan a tu versión sobrescrita. Tras cada actualización del tema padre, compara tus archivos sobrescritos con las nuevas versiones del padre e incorpora lo que necesites. Sobrescribe el menor número de archivos posible para que esto siga siendo manejable.

¿Puedo crear un tema hijo para un tema de bloques sin escribir código?

Sí. El plugin oficial Create Block Theme de WordPress.org incluye la opción Create Child Theme. Genera un tema hijo del tema de bloques activo, como Twenty Twenty-Four, y escribe en los archivos del hijo los cambios que hayas hecho en el Editor del sitio. El plugin está diseñado para temas de bloques, así que un tema hijo de un tema padre clásico sigue necesitando la configuración de style.css y functions.php descrita anteriormente.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.