6

I am trying to figure out a way to display an archive of email newsletters on my client's site. The issue is that the newsletters are full of a zillion inline styles, which is great for seeing them in Outlook or wherever, but they're not looking too hot in an otherwise-nicely styled site.

My goal is for my client to be able to copy the entire source code of a generated newsletter (which her list management company* gives her access to) and paste it into the CMS (drupal, if it makes a difference).

*Constant Contact? Mail Chimp? I forget. One of those.

Then I'd like to display it on her site, inside the basic structure (header, nav, etc) of the rest of the site. If this was 1997, I'd say "iframes!" and be done with it, but A) that seems like a lame solution, and B) the code doesn't actually exist on a page by itself, which I think is required for iframes.

Is there some kind of tag I can put around this block of HTML to isolate it from the rest of the site's styles? Or is there another way to go about this entirely?

Thanks!

Eileen
  • 6,630
  • 6
  • 28
  • 29
  • 1
    Can you show an example of this crazy HTML? – Keltex May 29 '09 at 19:44
  • In 1997, iFrames were only in Internet Explorer and IE had less than 20% share. :-) – Nosredna May 31 '09 at 22:32
  • Use a DOM parser and rip out all of the `style` elements, so the standard stylesheet applies. You can also add classes/ids as neccessary to get it to play nice with your existing styles. There is not any real way to ignore them, and you cannot override inline styles from an external stylesheet. Also if you do this in frontend code, it will still appear messed up until the parser triggers, so it is better to do either server side, or to format the text before placing it into the dom if you insist on doing it client side (but then you lose the benefit of having it crawled by search engines). – mopsyd Aug 22 '18 at 14:46

5 Answers5

4

IFrames are the only way to go that I've ever been able to find. The only alternative to this would be to override every style in the parent page's CSS for the newsletter display area.

As you noted, using an iframe will probably require you to host the newsletters in an independent file. The only alternative to this that I'm aware of is that you can use JavaScript to dynamically create and/or populate the iframe.

If you go with this method, you could have the newsletter present in a div with a specific class, and then use JavaScript to move the div into an iframe. The big downside being that this wouldn't happen for users without JavaScript enabled.

AaronSieb
  • 8,106
  • 8
  • 39
  • 58
2

9 years later and there still isn't a better solution.

If you don't have an external source (you can't add html into a frame manually) you need to use js to insert the messy html/css (in my case I use it to view emails)

<iframe class="my-frame" width="100%" height="100%" src="about:blank"></iframe>

and js:

const frame = document.querySelector('.my-frame');

frame.contentWindow.document.open('text/html', 'replace');
frame.contentWindow.document.write(hereGoesYourMessyHtmlCss);
frame.contentWindow.document.close();
Claudiu
  • 3,700
  • 1
  • 38
  • 35
0

Another option that I haven't used myself but am looking to possibly leverage in a similar situation is to use the Shadow DOM which is part of the Web Components spec. My main concern is that we still have some user's using IE 11 and while there seems to be support for polyfills it doesn't look like covering all browser's is real straight forward based on what I've read elsewhere.

Some details on how to use Shadow DOM to this effect can be found here and here. I've also created a small gist that I've created to demonstrate basic idea that I've been formulating as I learn about how the Shadow DOM works which I'll be updating as I learn more. Below you can see a snapshot of the content of that gist.

<!doctype html>
<html>

<head>
    <style>
        .row {
            display: flex;
        }

        .column {
            flex: 50%;
            padding: 10px;
            height: 300px;
        }

        * {
            color: Red;
        }
    </style>
</head>

<body>
    <div class="row">
        <div class="column" style="background-color:#aaa;">
            <h2>Column 1</h2>
            <div id="content1">
                SOME CONTENT FROM CMS
            </div>
        </div>
        <div class="column" style="background-color:#bbb;">
            <h2>Column 2</h2>
            <div id="content2">
                SOME MORE CONTENT FROM CMS
            </div>
        </div>
    </div>

    <script>
        document
            .getElementById("content1")
            .attachShadow({ mode: 'open' })
            .innerHTML = `
                <style>
                    *{all:initial} 
                    style{display: none}
                    div{display: block}
                </style>
                <h3>This text is not red</h3>
                <div>slot content: <slot></slot></div>`;

        document
            .getElementById("content2")
            .attachShadow({ mode: 'open' })
            .innerHTML = `
                <style>
                    *{all:initial} 
                    style{display: none}
                    div{display: block}
                </style>
                <h3>This text is not red</h3>
                <div>slot content: <slot></slot></div>`;
    </script>
</body>

</html>
jpierson
  • 16,435
  • 14
  • 105
  • 149
  • This post helped me to see that you can use shadowDom a bit more directly outside of having to define a Web Component. https://stackoverflow.com/a/47192501/83658 – jpierson Aug 25 '20 at 14:57
0

Is there a reason why you can't use a modal? That would allow you to force a new request and make the page render how you'd want it to by not applying your general stylesheet while at the same time keeping your user on the desired page. Of course, it doesn't display the element inline so-to-speak, but it's nearly functionally equivelent.

K_Cruz
  • 729
  • 6
  • 17
  • In this case, the client *specifically* wants the content to show up inline -- we are replacing a page where one had to click to show the most recent newsletter. – Eileen Jun 01 '09 at 22:33
  • In that case, it's iFrames or bust. – K_Cruz Jun 02 '09 at 01:53
0

Cutting and pasting raw HTML presents too many security problems, in my opinion. Never trust user's input. Even when the content is entirely benign, next week the designer of newsletter might decide to change their formatting or incorporate some javascript and you'll be responsible for anything that might go wrong.

Therefore I would implement a parser that would drop anything but the content part and leave only b, a, h*, blockquote and similar simple elements, like the ones allowed in forum posts, as well as their styles. After that, you can display it as a normal post in a CMS. I don't see any reason why that should look differently.

As for how to isolate that from your other CSS, you don't really need to if you are careful that all of CSS rules of your CMS apply to elements with specific classes. Alternatively, do a CSS reset for your posts:

.post p {
     margin: 0;
     ... 
.post /* all the standard CSS reset rules preceded with .post */

and then

<div class="post"> content parsed from your CMS </div>
ilya n.
  • 18,398
  • 15
  • 71
  • 89
  • You can encounter specificity issues. Overriding all of your css isn't a solution. Especially in the case of unknown (dynamic) css insertion. – Claudiu Aug 22 '18 at 14:19