diff --git a/core/modules/ckeditor5/ckeditor5.libraries.yml b/core/modules/ckeditor5/ckeditor5.libraries.yml
index a4f082c2c5ca946a949a5fc6eec63a84a08a3f9c..d25a96a0ca19b7c62d125e5efa9905795bb724f5 100644
--- a/core/modules/ckeditor5/ckeditor5.libraries.yml
+++ b/core/modules/ckeditor5/ckeditor5.libraries.yml
@@ -21,6 +21,7 @@ drupal.ckeditor5:
       css/quickedit.css: { }
   dependencies:
     - core/jquery
+    - core/once
     - core/drupal
     - core/drupal.debounce
     - core/ckeditor5.editorClassic
diff --git a/core/modules/ckeditor5/js/ckeditor5.es6.js b/core/modules/ckeditor5/js/ckeditor5.es6.js
index a200557fe74d52bca9a682b5f28691247d6e3bb7..e41d911c1f012b6bee06261c546ee516e120dcfc 100644
--- a/core/modules/ckeditor5/js/ckeditor5.es6.js
+++ b/core/modules/ckeditor5/js/ckeditor5.es6.js
@@ -3,7 +3,7 @@
  * CKEditor 5 implementation of {@link Drupal.editors} API.
  */
 /* global CKEditor5 */
-((Drupal, debounce, CKEditor5, $) => {
+((Drupal, debounce, CKEditor5, $, once) => {
   /**
    * The CKEDITOR instances.
    *
@@ -165,55 +165,131 @@
     });
   }
 
+  /**
+   * Process a group of CSS rules.
+   *
+   * @param {CSSGroupingRule} rulesGroup
+   *  A complete stylesheet or a group of nested rules like @media.
+   */
+  function processRules(rulesGroup) {
+    try {
+      // eslint-disable-next-line no-use-before-define
+      [...rulesGroup.cssRules].forEach(ckeditor5SelectorProcessing);
+    } catch (e) {
+      // eslint-disable-next-line no-console
+      console.warn(
+        `Stylesheet ${rulesGroup.href} not included in CKEditor reset due to the browser's CORS policy.`,
+      );
+    }
+  }
+
+  /**
+   * Processes CSS rules dynamically to account for CKEditor 5 in off canvas.
+   *
+   * This is achieved by doing the following steps:
+   * - Adding a donut scope to off canvas rules, so they don't apply within the
+   *   editor element.
+   * - Editor specific rules (i.e. those with .ck* selectors) are duplicated and
+   *   prefixed with the off canvas selector to ensure they have higher
+   *   specificity over the off canvas reset.
+   *
+   * The donut scope prevents off canvas rules from applying to the CKEditor 5
+   * editor element. Transforms a:
+   *  - #drupal-off-canvas strong
+   * rule into:
+   *  - #drupal-off-canvas strong:not([data-drupal-ck-style-fence] *)
+   *
+   * This means that the rule applies to all <strong> elements inside
+   * #drupal-off-canvas, except for <strong> elements who have a with a parent
+   * with the "data-drupal-ck-style-fence" attribute.
+   *
+   * For example:
+   * <div id="drupal-off-canvas">
+   *   <p>
+   *     <strong>Off canvas reset</strong>
+   *   </p>
+   *   <p data-drupal-ck-style-fence>
+   *     <!--
+   *       this strong elements matches the `[data-drupal-ck-style-fence] *`
+   *       selector and is excluded from the off canvas reset rule.
+   *     -->
+   *     <strong>Off canvas reset NOT applied.</strong>
+   *   </p>
+   * </div>
+   *
+   * The donut scope does not prevent CSS inheritance. There is CSS that resets
+   * following properties to prevent inheritance: background, border,
+   * box-sizing, margin, padding, position, text-decoration, transition,
+   * vertical-align and word-wrap.
+   *
+   * All .ck* CSS rules are duplicated and prefixed with the off canvas selector
+   * To ensure they have higher specificity and are not reset too aggressively.
+   *
+   * @param {CSSRule} rule
+   *  A single CSS rule to be analysed and changed if necessary.
+   */
+  function ckeditor5SelectorProcessing(rule) {
+    // Handle nested rules in @media, @support, etc.
+    if (rule.cssRules) {
+      processRules(rule);
+    }
+    if (!rule.selectorText) {
+      return;
+    }
+    const offCanvasId = '#drupal-off-canvas';
+    const CKEditorClass = '.ck';
+    const styleFence = '[data-drupal-ck-style-fence]';
+    if (
+      rule.selectorText.includes(offCanvasId) ||
+      rule.selectorText.includes(CKEditorClass)
+    ) {
+      rule.selectorText = rule.selectorText
+        .split(/,/g)
+        .map((selector) => {
+          // Only change rules that include #drupal-off-canvas in the selector.
+          if (selector.includes(offCanvasId)) {
+            return `${selector.trim()}:not(${styleFence} *)`;
+          }
+          // Duplicate CKEditor 5 styles with higher specificity for proper
+          // display in off canvas elements.
+          if (selector.includes(CKEditorClass)) {
+            // Return both rules to avoid replacing the existing rules.
+            return [
+              selector.trim(),
+              selector
+                .trim()
+                .replace(
+                  CKEditorClass,
+                  `${offCanvasId} ${styleFence} ${CKEditorClass}`,
+                ),
+            ];
+          }
+          return selector;
+        })
+        .flat()
+        .join(', ');
+    }
+  }
+
   /**
    * Adds CSS to ensure proper styling of CKEditor 5 inside off-canvas dialogs.
    *
    * @param {HTMLElement} element
    *   The element the editor is attached to.
    */
-  const offCanvasCss = (element) => {
-    element.parentNode.setAttribute('data-drupal-ck-style-fence', true);
-
+  function offCanvasCss(element) {
+    const fenceName = 'data-drupal-ck-style-fence';
+    const editor = Drupal.CKEditor5Instances.get(
+      element.getAttribute('data-ckeditor5-id'),
+    );
+    editor.ui.view.element.setAttribute(fenceName, '');
     // Only proceed if the styles haven't been added yet.
-    if (!document.querySelector('#ckeditor5-off-canvas-reset')) {
-      const prefix = `#drupal-off-canvas [data-drupal-ck-style-fence]`;
-      let existingCss = '';
-
-      // Find every existing style that doesn't come from off-canvas resets and
-      // copy them to new styles with a prefix targeting CKEditor inside an
-      // off-canvas dialog.
-      [...document.styleSheets].forEach((sheet) => {
-        if (
-          !sheet.href ||
-          (sheet.href && sheet.href.indexOf('off-canvas') === -1)
-        ) {
-          // This is wrapped in a try/catch as Chromium browsers will fail if
-          // the stylesheet was provided via a CORS request.
-          // @see https://bugs.chromium.org/p/chromium/issues/detail?id=775525
-          try {
-            const rules = sheet.cssRules;
-            [...rules].forEach((rule) => {
-              let { cssText } = rule;
-              const selector = rule.cssText.split('{')[0];
-
-              // Prefix all selectors added after a comma.
-              cssText = cssText.replace(
-                selector,
-                selector.replace(/,/g, `, ${prefix}`),
-              );
-
-              // When adding to existingCss, prefix the first selector as well.
-              existingCss += `${prefix} ${cssText}`;
-            });
-          } catch (e) {
-            // eslint-disable-next-line no-console
-            console.warn(
-              `Stylesheet ${sheet.href} not included in CKEditor reset due to the browser's CORS policy.`,
-            );
-          }
-        }
-      });
+    if (once('ckeditor5-off-canvas-reset', 'body').length) {
+      // For all rules on the page, add the donut scope for
+      // rules containing the #drupal-off-canvas selector.
+      [...document.styleSheets].forEach(processRules);
 
+      const prefix = `#drupal-off-canvas [${fenceName}]`;
       // Additional styles that need to be explicity added in addition to the
       // prefixed versions of existing css in `existingCss`.
       const addedCss = [
@@ -223,7 +299,6 @@
         `${prefix} .ck.ck-content ol li {list-style-type: decimal}`,
         `${prefix} .ck[contenteditable], ${prefix} .ck[contenteditable] * {-webkit-user-modify: read-write;-moz-user-modify: read-write;}`,
       ];
-
       // Styles to ensure block elements are displayed as such inside
       // off-canvas dialogs. These are all element types that are styled with
       // ` all: initial;` in the off-canvas reset that should default to being
@@ -268,15 +343,15 @@
         .join(', \n');
       const blockCss = `${blockSelectors} { display: block; }`;
 
-      const prefixedCss = [...addedCss, existingCss, blockCss].join('\n');
+      const prefixedCss = [...addedCss, blockCss].join('\n');
 
       // Create a new style tag with the prefixed styles added above.
-      const offCanvasCss = document.createElement('style');
-      offCanvasCss.innerHTML = prefixedCss;
-      offCanvasCss.setAttribute('id', 'ckeditor5-off-canvas-reset');
-      document.body.appendChild(offCanvasCss);
+      const offCanvasCssStyle = document.createElement('style');
+      offCanvasCssStyle.textContent = prefixedCss;
+      offCanvasCssStyle.setAttribute('id', 'ckeditor5-off-canvas-reset');
+      document.body.appendChild(offCanvasCssStyle);
     }
-  };
+  }
 
   /**
    * @namespace
@@ -581,4 +656,4 @@
       Drupal.ckeditor5.saveCallback = null;
     }
   });
-})(Drupal, Drupal.debounce, CKEditor5, jQuery);
+})(Drupal, Drupal.debounce, CKEditor5, jQuery, once);
diff --git a/core/modules/ckeditor5/js/ckeditor5.js b/core/modules/ckeditor5/js/ckeditor5.js
index 59e014ae78b8ac367a285026470dce97c1a3e5b3..7e24a25a4dfbcf6d04bd56618148c520beca5e32 100644
--- a/core/modules/ckeditor5/js/ckeditor5.js
+++ b/core/modules/ckeditor5/js/ckeditor5.js
@@ -5,7 +5,7 @@
 * @preserve
 **/
 
-((Drupal, debounce, CKEditor5, $) => {
+((Drupal, debounce, CKEditor5, $, once) => {
   Drupal.CKEditor5Instances = new Map();
   const callbacks = new Map();
   const required = new Set();
@@ -98,39 +98,60 @@
     });
   }
 
-  const offCanvasCss = element => {
-    element.parentNode.setAttribute('data-drupal-ck-style-fence', true);
-
-    if (!document.querySelector('#ckeditor5-off-canvas-reset')) {
-      const prefix = `#drupal-off-canvas [data-drupal-ck-style-fence]`;
-      let existingCss = '';
-      [...document.styleSheets].forEach(sheet => {
-        if (!sheet.href || sheet.href && sheet.href.indexOf('off-canvas') === -1) {
-          try {
-            const rules = sheet.cssRules;
-            [...rules].forEach(rule => {
-              let {
-                cssText
-              } = rule;
-              const selector = rule.cssText.split('{')[0];
-              cssText = cssText.replace(selector, selector.replace(/,/g, `, ${prefix}`));
-              existingCss += `${prefix} ${cssText}`;
-            });
-          } catch (e) {
-            console.warn(`Stylesheet ${sheet.href} not included in CKEditor reset due to the browser's CORS policy.`);
-          }
+  function processRules(rulesGroup) {
+    try {
+      [...rulesGroup.cssRules].forEach(ckeditor5SelectorProcessing);
+    } catch (e) {
+      console.warn(`Stylesheet ${rulesGroup.href} not included in CKEditor reset due to the browser's CORS policy.`);
+    }
+  }
+
+  function ckeditor5SelectorProcessing(rule) {
+    if (rule.cssRules) {
+      processRules(rule);
+    }
+
+    if (!rule.selectorText) {
+      return;
+    }
+
+    const offCanvasId = '#drupal-off-canvas';
+    const CKEditorClass = '.ck';
+    const styleFence = '[data-drupal-ck-style-fence]';
+
+    if (rule.selectorText.includes(offCanvasId) || rule.selectorText.includes(CKEditorClass)) {
+      rule.selectorText = rule.selectorText.split(/,/g).map(selector => {
+        if (selector.includes(offCanvasId)) {
+          return `${selector.trim()}:not(${styleFence} *)`;
         }
-      });
+
+        if (selector.includes(CKEditorClass)) {
+          return [selector.trim(), selector.trim().replace(CKEditorClass, `${offCanvasId} ${styleFence} ${CKEditorClass}`)];
+        }
+
+        return selector;
+      }).flat().join(', ');
+    }
+  }
+
+  function offCanvasCss(element) {
+    const fenceName = 'data-drupal-ck-style-fence';
+    const editor = Drupal.CKEditor5Instances.get(element.getAttribute('data-ckeditor5-id'));
+    editor.ui.view.element.setAttribute(fenceName, '');
+
+    if (once('ckeditor5-off-canvas-reset', 'body').length) {
+      [...document.styleSheets].forEach(processRules);
+      const prefix = `#drupal-off-canvas [${fenceName}]`;
       const addedCss = [`${prefix} .ck.ck-content {display:block;min-height:5rem;}`, `${prefix} .ck.ck-content * {display:initial;background:initial;color:initial;padding:initial;}`, `${prefix} .ck.ck-content li {display:list-item}`, `${prefix} .ck.ck-content ol li {list-style-type: decimal}`, `${prefix} .ck[contenteditable], ${prefix} .ck[contenteditable] * {-webkit-user-modify: read-write;-moz-user-modify: read-write;}`];
       const blockSelectors = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'ol', 'ul', 'address', 'article', 'aside', 'blockquote', 'body', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'header', 'hgroup', 'hr', 'html', 'legend', 'main', 'menu', 'pre', 'section', 'xmp'].map(blockElement => `${prefix} .ck.ck-content ${blockElement}`).join(', \n');
       const blockCss = `${blockSelectors} { display: block; }`;
-      const prefixedCss = [...addedCss, existingCss, blockCss].join('\n');
-      const offCanvasCss = document.createElement('style');
-      offCanvasCss.innerHTML = prefixedCss;
-      offCanvasCss.setAttribute('id', 'ckeditor5-off-canvas-reset');
-      document.body.appendChild(offCanvasCss);
+      const prefixedCss = [...addedCss, blockCss].join('\n');
+      const offCanvasCssStyle = document.createElement('style');
+      offCanvasCssStyle.textContent = prefixedCss;
+      offCanvasCssStyle.setAttribute('id', 'ckeditor5-off-canvas-reset');
+      document.body.appendChild(offCanvasCssStyle);
     }
-  };
+  }
 
   Drupal.editors.ckeditor5 = {
     attach(element, format) {
@@ -334,4 +355,4 @@
       Drupal.ckeditor5.saveCallback = null;
     }
   });
-})(Drupal, Drupal.debounce, CKEditor5, jQuery);
\ No newline at end of file
+})(Drupal, Drupal.debounce, CKEditor5, jQuery, once);
\ No newline at end of file