WordPress and React
In version 5.0, WordPress introduced Gutenberg, a block-based editor with a much more modern interface than the classic one.
Gutenberg is built with React, so from that version on, WordPress ships with the basic React libraries included — react.min.js and react-dom.min.js.
WordPress also provides its own implementation of React in the wp.element object, which contains functions such as render, createElement and useState.
WordPress loads the React libraries only when they are needed, which by default means when you edit a post or page in the Dashboard using Gutenberg.
They can be loaded anywhere on demand, though — even on the front end — simply by adding the wp-element dependency when enqueuing a script.
Material UI
Material UI is an implementation of Google’s Material Design in React. Since WordPress supports React, it is in principle possible to use Material UI with WordPress. Here is how.
The guide in this article describes how to insert React elements into a WordPress page using a shortcode.
These are the basic steps it follows:
- It writes the React code in JSX and builds it, producing a single
main.jsfile. The whole React DOM is rendered inside one container element. - It enqueues
main.jswhen the WordPress page loads, using thewp_enqueue_scriptshook. It adds thewp-elementdependency at the same time, so that WordPress loads the React library. - The shortcode outputs the container
div, inside which the React DOM is rendered.
So when the page loads, the React DOM is rendered inside the container the shortcode created.
Extending that React code to use Material UI components is straightforward: the process is the same, and we simply build a new main.js.
Here is an example render from the Iptanus File Upload plugin, which uses Material UI components for its upload form:

There is a catch, however.
Conflicts with WordPress themes
Material UI is a design system with its own rules for fonts, colours, margins and styling in general. WordPress, meanwhile, uses themes to set the appearance of a site, and every theme imposes rules of its own.
The two conflict.
When the page loads, the Material UI components do not look as they should. They are distorted.
Here is how that same upload form looks with the Hestia WordPress theme when nothing is done about the conflict:

The components have changed size and lost their alignment, and the day buttons in the date picker have picked up a pink shadow imposed by the Hestia theme.
The reason for the distortion is that the WordPress theme’s CSS rules override Material UI’s.
This is not something we can predict. Every theme sets its CSS rules its own way, so there is no telling in advance how a given theme will affect the Material UI components.
When the components live inside a WordPress plugin, though, we need a generic solution — one that works with every theme.
There are two ways to solve it:
- Make the Material UI rules stronger than the theme’s, so that they always win.
- Isolate the Material UI components from the page, but only as far as CSS is concerned — they must go on interacting with the rest of the page normally.
We researched this in depth while building Iptanus File Upload and tested both. Each has its advantages, but the second — isolating the components for styling only — is the more efficient and the more universal.
The Shadow DOM solution
That isolation can be achieved with Shadow DOM, a key part of Web Components encapsulation.
Shadow DOM attaches a hidden, separate DOM to an element. “Hidden” here means that the attached DOM does not inherit the styles of the main one — exactly the isolation we want.
So if the Material UI components are rendered inside a container that sits within a shadow DOM, the theme’s CSS cannot reach them.
Here is part of the Iptanus File Upload plugin’s HTML structure when it is configured to use a shadow DOM:

All of the plugin’s HTML is rendered inside an open shadow DOM, under the plugin’s main container element with the id wordpress_file_upload_block_1.
The Material UI components of the upload form are rendered in separate div containers inside that shadow DOM. Visible here is part of the component that shows the selected filename, rendered inside a container with the id r_wfu_textbox_1.
Implementing the solution is straightforward. The basic steps are:
- Put the HTML to be isolated — or just the container the Material UI components will render into — inside a template element. A
<template>is a special element whose contents are not rendered immediately, but only when they are needed. - Create the shadow DOM under an element with the attachShadow() JavaScript function.
- Append the template’s content inside the shadow DOM.
Once the page is rendered, the components inside the shadow DOM are untouched by any CSS outside it.
Caveats of the Shadow DOM solution
Two things are worth knowing before you use it.
First, elements inside a shadow DOM can no longer be reached from JavaScript in the usual way — document.getElementById(), document.querySelector() and the like — because their root is not the document but the shadow DOM. Instead of document, use the object returned by attachShadow().
Second, CSS that spans both sides of the boundary is awkward. In the markup above, suppose we wanted to hide the component with the id r_wfu_textbox_1, which sits inside the shadow DOM, whenever the article element with the id post-261 — which sits outside it — carries the class hide-filename.
Without a shadow DOM it would look like this:
article#post-261.hide-filename div#r_wfu_textbox_1 {
visibility: hidden;
}
Because of the shadow DOM, that selector will not work.
CSS has a pseudo-class for exactly this case, :host-context(). The correct rule looks like this:
:host-context(article#post-261.hide-filename) div#r_wfu_textbox_1 {
visibility: hidden;
}
The catch is that :host-context() is not supported by every browser, as the compatibility table shows: Safari and Firefox still do not implement it.
Until support is universal, these cases need another approach.
If you have questions, or need more information, please contact us.
The Iptanus team

This is a great approach to integrating Material UI with WordPress using Shadow DOM. Given the potential issues with CSS conflicts between themes and Material UI, do you think this method is still the best solution today, or have there been any updates or new techniques to handle these conflicts more effectively?
I design and code for living. I like to integrate Material UI into WordPress plugins etc, it can enhance the overall aesthetics and usability. However, I often face challenges with conflicts between Material UI and existing WordPress themes or plugins. Most common: Compatibility issues with jQuery versions, Conflicting CSS styles leading to design inconsistencies, JavaScript errors arising from incompatible libraries…