5

I am making a web application through which user can create an email campaign.

While creating the campaign, the user adds email content using CKEditor. He/she can add internal CSS and JavaScript. Once the campaign is created, it looks like the image given below.

I have to show the email content preview in div #email_content exactly how it will appear. But common CSS written for the page is applied to #email_content and vice-versa. I don't have access to modify the common CSS.


How can I show the email_content preview exactly how it will appear?

Note: I know using iframe for email_content. It is possible, but I am looking for another workaround.

Single Campaign Page

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
aagjalpankaj
  • 1,160
  • 1
  • 15
  • 25
  • Make your page content css very specific so it only targets the elements you want and not the ones in the preview panels - eg use selectors that target ids rather than selectors that target elements. Ps is it a good idea to allow users to add their own css? Do they have good knowledge of the css that is available for email clients - ie it won't appear as it would on a normal webpage – Pete Nov 21 '17 at 12:52

3 Answers3

2

As it is explained in this article, you can create a shadow DOM element, in other words encapsulate your element to have its own CSS as it is shown here..

The outside CSS class will not affect your shadow DOM element..

if (! Element.prototype.createShadowRoot && Element.prototype.webkitCreateShadowRoot) {
  Element.prototype.createShadowRoot = Element.prototype.webkitCreateShadowRoot;
}

var div = document.querySelector('#for-shadow');
var fileTemplate = document.getElementById("file-template");
var shadowDom = div.createShadowRoot();
shadowDom.appendChild(fileTemplate.content);
.outside{
    background: red;
    height: auto;
}
<div class="outside inside">from outside</div>
<div id="for-shadow">
<template id="file-template">
  <style>
    .inside{
      color:blue;
    }
  </style>
  <script>
    console.log('its js code');
  </script>
  <div class="outside inside">
    this is the div inside the template
  </div>
</template>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Renzo Calla
  • 7,486
  • 2
  • 22
  • 37
  • This is what I got running this piece of code: { "message": "Uncaught TypeError: div.createShadowRoot is not a function", "filename": "https://stacksnippets.net/js", "lineno": 35, "colno": 21 } – Branko Radojevic Jun 29 '20 at 14:45
2

This is a common problem that does not (yet) have a simple, universal solution.

Shadow DOM

Ideally you would use Shadow DOM, as it is specifically intended to solve such a problem:

Shadow DOM provides encapsulation for DOM and CSS in a Web Component. Shadow DOM makes it so these things remain separate from the DOM of the main document. You can also use Shadow DOM by itself, outside of a web component.

Why would you want to keep some code separate from the rest of the page? One reason is that on a large site, for example, if the CSS is not carefully organized, the styling for the navigation can "leak" into the main content area where it was not intended to go, or vice-versa. As a site or an app scales, this kind of thing becomes difficult to avoid.

Shadow DOM is well-supported as of 2022.

Iframes

On the other end of the spectrum is an iframe. iframes are supported everywhere, but may require a larger change to the page than you are able to make. More importantly, iframes introduce undesirable scrolling behaviors on iOS that may change from version to version.

Targeted Reset

A practical, though not foolproof, solution is to create a CSS reset that only targets the content you want isolated.

/* The start of a simple reset */
#email_content * {
    border: 0;
    margin: 0;
    padding: 0;
}

This is one of the cases where it may be required to mark a rule as !important.

Targeted Unset (all/initial/unset)

Reset/remove CSS styles for element only

Tim M.
  • 53,671
  • 14
  • 120
  • 163
2

Use this:

#email_content * {
    all: unset;
}

This will reset all global CSS, and after that, you can use inline CSS.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131