El problema: WordPress no deja cambiar el icono hamburguesa desde el bloque
Has montado la cabecera con el bloque Navegación de WordPress, has ajustado colores, tipografías y espaciados, y en escritorio todo parece encajar. Luego abres la web en móvil y aparece el detalle incómodo: el icono hamburguesa sigue siendo el que trae WordPress.
No es un error grave, pero en una web con un diseño cuidado se nota. Si el proyecto usa iconos con un trazo concreto, esquinas redondeadas, o una proporción muy definida, ese botón puede parecer de otro sistema visual. Y lo peor es que el bloque no tiene un ajuste nativo para pegar tu propio SVG.
Ahí suelen aparecer varias soluciones rápidas: ocultar el icono con CSS, poner una imagen de fondo, reemplazar el primer <svg> que aparezca o instalar un plugin. Algunas pueden servir, pero no todas son igual de seguras ni igual de fáciles de mantener.
La clave está en no cambiar “un SVG cualquiera”, sino el SVG exacto del botón que abre el menú móvil. Así evitamos tocar otros iconos del bloque, como indicadores de submenú, iconos añadidos por el tema o elementos que puedan aparecer más adelante.
Qué opciones tienes para cambiarlo
Cuando te encuentras con este problema, lo normal es pensar: «vale, si WordPress ya está pintando un SVG, cambio ese SVG y listo». Y sí, por ahí van los tiros. Pero hay varias formas de hacerlo, y no todas son igual de limpias.
La primera opción es usar render_block, el filtro general que permite modificar el HTML final de cualquier bloque. Es potente, porque te deja tocar el marcado cuando WordPress ya lo ha construido. Pero precisamente por eso hay que usarlo con cuidado: se ejecuta para todos los bloques, así que necesitas comprobar que estás dentro de core/navigation antes de cambiar nada.
La segunda opción es usar también render_block, pero apuntando mejor. En vez de reemplazar el primer <svg> que aparezca, buscas el botón que abre el menú móvil, el que lleva la clase wp-block-navigation__responsive-container-open, y cambias solo lo que hay dentro. Es más preciso y reduce bastante el riesgo de tocar un icono que no viene al caso.
La tercera opción es usar directamente el filtro específico del bloque: render_block_core/navigation. Hace lo mismo en el momento adecuado, pero solo se ejecuta cuando WordPress renderiza el bloque Navegación. Para este caso suele ser la opción más clara: menos comprobaciones, menos ruido y una intención más fácil de entender cuando alguien revise el código dentro de unos meses.
También existe render_block_data, pero juega en otra fase. Sirve para modificar los datos del bloque antes de que WordPress genere el HTML. Puede ayudarte a añadir una clase o ajustar atributos, pero no es el camino directo para sustituir un SVG que todavía no existe.
Y si no quieres tocar código, hay plugins que añaden una pantalla para pegar el SVG del icono de apertura y cierre del menú. Puede encajar en una web sencilla, siempre que revises compatibilidad, mantenimiento y que realmente haga justo lo que necesitas.
En resumen, las opciones serían estas:
| Opción | Cuándo encaja | Qué debes vigilar |
|---|---|---|
render_block genérico | Para una prueba rápida o un menú muy controlado. | Puede cambiar el SVG equivocado si el menú tiene más iconos. |
render_block apuntando al botón | Si ya centralizas varias personalizaciones en ese filtro. | Sigue ejecutándose para todos los bloques. |
render_block_core/navigation | Cuando solo quieres tocar el bloque Navegación. | Depende de la estructura del botón responsive. |
render_block_data | Para añadir clases o modificar atributos antes del renderizado. | No sustituye directamente el SVG final. |
| Plugin | Si prefieres una pantalla de ajustes y no tocar código. | Añade una dependencia que conviene revisar. |
La recomendación no es «usa siempre esto», porque en WordPress rara vez hay una única respuesta para todos los proyectos. Para este caso concreto, si estás trabajando con código, yo iría a render_block_core/navigation: es específico, se entiende bien y toca solo el bloque que nos interesa.
Opción 1: usar render_block y cambiar el primer SVG
La primera forma de resolverlo es la más directa: usar render_block, comprobar que estamos dentro del bloque core/navigation y reemplazar el primer SVG que encontremos en el HTML.
Es una opción tentadora porque se entiende rápido. WordPress genera el bloque, tú interceptas el HTML final y cambias un SVG por otro. Para una prueba rápida o para confirmar que el filtro funciona, puede venir bien.
add_filter( 'render_block', 'prefix_cambiar_primer_svg_navegacion', 10, 2 );
function prefix_cambiar_primer_svg_navegacion( $block_content, $block ) {
if ( 'core/navigation' !== ( $block['blockName'] ?? '' ) || is_admin() || wp_is_json_request() ) {
return $block_content;
}
$icono_personalizado = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>';
return preg_replace( '#<svg\b[^>]*>.*?</svg>#s', $icono_personalizado, $block_content, 1 );
}El problema es que este código no sabe qué SVG está cambiando. Solo cambia el primero que aparece.
Si el menú es muy simple, probablemente coincida con el icono hamburguesa. Pero en cuanto el bloque tenga otro SVG antes, por ejemplo, un indicador de submenú, un icono añadido por el tema o una personalización previa, el snippet puede tocar lo que no debe.
Por eso yo lo trataría como una primera aproximación, no como la solución que dejaría en producción. Sirve para entender el mecanismo, pero no tiene suficiente criterio sobre el HTML que está modificando.
La idea que nos interesa conservar de esta opción es buena: render_block permite trabajar cuando el bloque ya está convertido en HTML. Lo que falla no es el filtro, sino lo poco específico que es el reemplazo. Ahí es donde aparece la siguiente mejora: seguir usando render_block, pero apuntar al botón correcto.
Opción 2: usar render_block pero apuntar al botón responsive
La siguiente mejora es bastante lógica: si el problema de la primera opción era que reemplazaba el primer SVG que encontraba, vamos a decirle exactamente dónde tiene que mirar.
En vez de buscar cualquier <svg>, buscamos el botón que abre el menú móvil. WordPress lo marca con la clase wp-block-navigation__responsive-container-open, así que podemos usar esa clase como referencia y sustituir solo el contenido de ese botón.
add_filter( 'render_block', 'prefix_cambiar_icono_navegacion_render_block', 10, 2 );
function prefix_cambiar_icono_navegacion_render_block( $block_content, $block ) {
if ( 'core/navigation' !== ( $block['blockName'] ?? '' ) || is_admin() || wp_is_json_request() ) {
return $block_content;
}
$icono_personalizado = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false"><path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" /></svg>';
$patron = '#(<button\b[^>]*\bclass=(["\'])[^"\']*wp-block-navigation__responsive-container-open[^"\']*\2[^>]*>).*?(</button>)#s';
$reemplazo = '$1' . $icono_personalizado . '$3';
$resultado = preg_replace( $patron, $reemplazo, $block_content, 1 );
return null === $resultado ? $block_content : $resultado;
}Aquí ya no estamos jugando a «a ver cuál es el primer SVG». El patrón busca el botón con la clase del contenedor responsive y mantiene la etiqueta <button> tal como la genera WordPress. Solo cambia lo que hay dentro.
Eso es importante por dos motivos. Primero, porque el botón puede tener atributos que no queremos perder: clases, estados, atributos de accesibilidad o cualquier detalle que WordPress añada para que el menú funcione correctamente. Segundo, porque el código expresa mejor la intención. Quien lo lea dentro de unos meses entenderá que no estamos modificando «un icono del menú», sino el icono del botón que abre el menú móvil.
La mejora no está solo en que el código funcione. Está en que el código falle mejor: si no encuentra el botón esperado, devuelve el HTML original y no rompe la navegación.
Esta opción ya puede encajar en un proyecto real, sobre todo si tienes otras personalizaciones centralizadas en render_block. La pega es que el filtro sigue siendo genérico: WordPress lo ejecuta para cada bloque renderizado y tú tienes que comprobar si ese bloque es core/navigation.
No es un drama de rendimiento, pero sí añade ruido. Si solo queremos tocar el bloque Navegación, podemos dar un paso más y usar el filtro específico del bloque. Ahí es donde la solución empieza a quedar más redonda.
Opción 3: usar render_block_core/navigation
Llegados a este punto, ya tenemos clara la idea: queremos modificar el HTML final del bloque, pero sin tocar cualquier SVG ni ejecutar lógica que no hace falta.
Aquí es donde entra el filtro específico del bloque Navegación: render_block_core/navigation.
WordPress permite filtrar el HTML renderizado de un bloque concreto usando un hook con este formato:
render_block_{$this->name}En el caso del bloque core/navigation, ese hook se convierte en:
render_block_core/navigationLa ventaja es sencilla: este filtro solo se ejecuta cuando WordPress renderiza el bloque Navegación. Ya no hace falta comprobar dentro de la función si estamos ante core/navigation, porque el propio hook ya nos ha llevado al sitio correcto.
/**
* Sustituye el SVG del botón que abre el menú responsive.
*/
add_filter( 'render_block_core/navigation', 'prefix_cambiar_icono_menu_movil', 10, 2 );
function prefix_cambiar_icono_menu_movil( $block_content, $block ) {
// No cambiar la vista previa del editor ni respuestas JSON.
if ( is_admin() || wp_is_json_request() ) {
return $block_content;
}
// Sustituye este SVG por el icono de tu sistema de diseño.
// currentColor hace que herede el color definido para el botón.
$icono_personalizado = '
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false">
<path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>';
// Busca solo el botón que abre el contenedor responsive.
$patron = '#(<button\b[^>]*\bclass=(["\'])[^"\']*wp-block-navigation__responsive-container-open[^"\']*\2[^>]*>).*?(</button>)#s';
$reemplazo = '$1' . $icono_personalizado . '$3';
$resultado = preg_replace( $patron, $reemplazo, $block_content, 1 );
// Si el marcado no coincide, devolver el HTML original sin romper el menú.
return null === $resultado ? $block_content : $resultado;
}Esta es la opción que recomendaría para este caso. No porque sea mágica, sino porque reduce el alcance del código al bloque que realmente queremos modificar.
El snippet hace tres cosas bastante concretas: usa un filtro específico para core/navigation, busca solo el botón de apertura del menú móvil y, si no encuentra el patrón esperado, devuelve el HTML original.
Ese último punto parece pequeño, pero es importante. Si WordPress cambia el marcado del bloque en una actualización futura, prefiero que el menú siga funcionando con el icono original a que el código empiece a sustituir algo que no toca.
El SVG de ejemplo usa currentColor, así que heredará el color del botón según los estilos del tema. Esto suele ser más cómodo que fijar un color directamente dentro del SVG, porque permite que el icono responda mejor a estados, variaciones del diseño o ajustes del bloque.
También he dejado aria-hidden="true" y focusable="false" porque el SVG no es el elemento interactivo. La acción la comunica el botón, no el dibujo. Si tu tema o el bloque ya están generando la etiqueta accesible del botón, el icono debe comportarse como un elemento decorativo.
Con esta opción tienes una solución bastante acotada: no modifica el núcleo, no toca el editor, no cambia otros SVG del menú y deja claro dónde se aplica. Para un ajuste puntual del icono hamburguesa, normalmente es el equilibrio más razonable.
Por qué render_block_data no es la herramienta adecuada
Después de ver render_block y render_block_core/navigation, es fácil pensar: “vale, ¿y si modifico el bloque antes de que WordPress lo renderice?”. Para eso existe render_block_data.
El filtro render_block_data se ejecuta antes de que WordPress convierta el bloque en HTML. Sirve para modificar los datos del bloque, por ejemplo añadir una clase, ajustar atributos o preparar información que después se usará durante el renderizado.
Y eso está bien, pero aquí tenemos un matiz importante: el SVG del botón todavía no existe en esa fase.
Por eso render_block_data no es el camino directo para sustituir el icono hamburguesa. Puedes usarlo para añadir una clase al bloque Navegación y después aplicar CSS, pero no para reemplazar de forma limpia el SVG final del botón.
Un ejemplo razonable sería algo así:
add_filter( 'render_block_data', 'prefix_anadir_clase_navegacion_personalizada', 10, 2 );
function prefix_anadir_clase_navegacion_personalizada( $parsed_block, $source_block ) {
if ( 'core/navigation' !== ( $parsed_block['blockName'] ?? '' ) ) {
return $parsed_block;
}
$class_name = $parsed_block['attrs']['className'] ?? '';
$parsed_block['attrs']['className'] = trim( $class_name . ' tiene-icono-menu-personalizado' );
return $parsed_block;
}Esto puede ser útil si quieres preparar el bloque para estilos personalizados. Por ejemplo, podrías añadir una clase y luego usar CSS para ajustar tamaño, color, separación o incluso ocultar visualmente el icono original y colocar otro recurso.
Pero en ese punto la solución empieza a repartirse entre varias capas: PHP añade una clase, CSS oculta o dibuja otra cosa, y el SVG original sigue estando en el marcado. Puede funcionar, pero no es tan directo como sustituir el SVG inline cuando el HTML ya existe.
Para este caso concreto, yo lo resumiría así: render_block_data sirve para preparar el bloque, no para cambiar el icono ya renderizado.
Si lo que quieres es modificar atributos o añadir una clase, úsalo. Si lo que quieres es cambiar el SVG del botón móvil, tiene más sentido trabajar con el HTML final mediante render_block_core/navigation.
Alternativa sin código: usar un plugin
Si no quieres meter un snippet en el proyecto, también puedes usar un plugin. En este caso, el más directo es Change Icons in Menu Navigation Block, que añade una pantalla de ajustes para pegar el SVG del icono de apertura y cierre del menú móvil.
Aquí la ventaja es evidente: no tienes que tocar código. Entras en los ajustes, pegas el SVG correspondiente y guardas. Para una web pequeña, una prueba rápida, o un proyecto donde quien gestiona el sitio no trabaja con snippets, puede ser suficiente.

Ahora bien, que sea más cómodo no significa que haya que instalarlo sin mirar. Antes de usarlo, revisaría al menos tres cosas:
- compatibilidad declarada con tu versión de WordPress;
- fecha de última actualización;
- que funcione bien con tu tema y con la estructura real de tu menú.
Un plugin muy acotado puede ser una buena solución. Pero sigue siendo una dependencia más. Si el proyecto ya tiene un plugin de funcionalidades o una capa de snippets controlada, quizá compense resolverlo con código. Si no existe esa capa y el equipo necesita algo editable desde el panel, el plugin puede encajar mejor.
También conviene no mezclar necesidades. Este plugin sirve para cambiar los iconos de apertura y cierre del menú móvil. No es lo mismo que añadir un icono a cada enlace del menú, ni que construir un mega menú, ni que crear una navegación completamente personalizada.
En resumen: si necesitas una solución editable desde WordPress, el plugin puede ser suficiente. Si buscas una personalización controlada dentro del desarrollo del proyecto, mejor dejarlo en código.
Qué comprobar antes de darlo por terminado
Cambiar el icono es la parte fácil. Lo importante es comprobar que el menú sigue comportándose como un menú, que parece una obviedad hasta que deja de pasar.
Después de aplicar el snippet o configurar el plugin, revisa primero el comportamiento básico en móvil: el botón debe abrir y cerrar el panel, el icono debe verse con contraste suficiente y el menú no debería moverse de forma rara al cargar la página.
También conviene probarlo con teclado. Si tabulas por la cabecera, el foco debe seguir siendo visible y el botón debe poder activarse. Aquí el icono no debería ser el único elemento que comunique la acción. El SVG es visual; la accesibilidad depende del botón y de su etiqueta.
Si tu navegación tiene submenús, pruébalos también. A veces el menú principal funciona bien, pero los desplegables, estados activos o iconos secundarios se ven afectados por estilos demasiado genéricos. Justo por eso hemos intentado evitar soluciones que cambian cualquier SVG del bloque.
Además, deja anotado que este ajuste conviene revisarlo cuando actualices WordPress o cambies de tema. El bloque Navegación puede cambiar su estructura interna con el tiempo. Si eso ocurre, el snippet recomendado debería devolver el HTML original y mantener el menú funcionando, pero tendrás que revisar el patrón.
Una comprobación rápida sería:
- abrir y cerrar el menú en móvil;
- revisar el foco con teclado;
- comprobar contraste del icono;
- probar submenús si existen;
- confirmar que no se han cambiado otros SVG del menú;
- revisar el ajuste después de una actualización importante de WordPress o del tema.
No hace falta convertir esto en una auditoría enorme. Pero sí merece la pena dedicar dos minutos a comprobarlo, porque el menú es una de esas partes de la web que todo el mundo usa y casi nadie perdona cuando falla.
Cuando el menú empieza a pedir algo más que un icono
Cambiar el icono hamburguesa puede ser suficiente cuando el problema es solo visual: el diseño pide otro SVG y el bloque Navegación cubre bien el resto de necesidades.
Pero a veces el icono es la primera pista de algo más grande. Empiezas cambiando el SVG, luego necesitas iconos por enlace, después un comportamiento distinto en móvil, más tarde un mega menú, y al final tienes una colección de pequeños parches alrededor del bloque.
Ahí conviene parar un momento. Si el menú sigue siendo sencillo, una personalización puntual tiene sentido. Si la navegación empieza a acumular excepciones, estados especiales o estructuras que el editor no gestiona bien, quizá compense revisar el sistema completo: cómo se edita, cómo se renderiza y qué puede mantener una persona no técnica sin miedo a romperlo.
Por eso la idea no es «meter código porque sí», ni instalar un plugin por cada necesidad. La idea es elegir el nivel justo de personalización para el proyecto.
Si solo necesitas cambiar el icono, el filtro específico del bloque Navegación suele ser suficiente. Si el menú empieza a convertirse en una pieza crítica del sitio, merece la pena tratarlo como tal.
Para profundizar o contrastar la parte técnica, puedes revisar estos recursos:
- render_block, el filtro general para modificar el HTML renderizado de cualquier bloque.
- render_block_{$this->name}, el filtro específico que permite actuar sobre un bloque concreto como
core/navigation. - render_block_data, útil para modificar datos del bloque antes de generar el HTML.
En Bubuku ayudamos a revisar y construir desarrollos WordPress a medida cuando el bloque estándar se queda corto, o cuando la edición necesita ser más clara para el equipo que gestiona la web. La idea no es añadir complejidad, sino quitar fricción donde el proyecto realmente la tiene.



