简体   繁体   中英

How are styles within div's made 'safer' (i.e. so they do not override parent styles)

I am implementing an email client. One of the problems that I am facing is the fact that displaying the emails (ie the body of the email) may interrupt the styles of the general web application (not just the div).

Say I have a JS variable:

var element = $(data.bodyHTML);
$('div.result').html(element);

Where data.bodyHTML is the HTML content of the email body which contains the following:

<html>
<head>
<style>
    div, p, span, a {
        padding: 0;
        margin: 0;
        color: black;
    }
    .test-div, .test-p, #test-strong {
        color: blue !important;
    }
</style>
</head>
<body>
    <div class="test-div"><p class="test-p">Signature</p><strong id="test-strong">John Doe</strong></div>
</body>
</html>

The div, p, span, a style destroys the styling in the rest of the web app (as long as I remain on the same page).

I've tried everything to prevent it from happening. I can't use an iFrame. I seen other email clients doing something like so:

<html>
<head>
<style>
    .SafeStyles div, .SafeStyles p, .SafeStyles span, .SafeStyles a {
        padding: 0;
        margin: 0;
        color: black;
    }
    .SafeStyles .test-div, .SafeStyles .test-p, .SafeStyles #test-strong {
        color: blue !important;
    }
</style>
</head>
<body>
    <div class="SafeStyles">
    <div class="test-div"><p class="test-p">Signature</p><strong id="test-strong">John Doe</strong></div>
    </div>
</body>
</html>

.SafeStyles is placed in front of each style tag/class/id so as to prevent any override to the parent.

But how is this being done? That is my question.

Any kind of help or suggestions are appreciated. Thanks.

EDIT: I think people here seem to misunderstanding my question. I know exactly why the styles are overriding the parent, I know enough CSS to understand the basics. The question is this:

Given a string of html in javascript, with javascript, how do you add classes before the styles within the style tag of the given html string?

Simple answer, given how CSS works: CSS doesn't care about where it's declared, it kicks in globally. If you have a rule div { ... } then that applies to all divs, everywhere in the document, and the only way to change what they do is to override properties with more specific rules.

And that's exactly what you do with div.classname : this does not apply to all divs, only to divs with a class classname . Want to be absolutely safe: add your own safety class(es) to each element, and declare CSS with selectors that rely on those:

<div class="personal safety">
  <p class="personal safety">
  </p>
</div>

and now we define the styles we want for these elements:

div.personal.safety { ... }
p.personal.safety { ... }

done, this CSS will only apply to our code.

Except only "sort of", because if you use this on a page that happens to already use "personal safety" as CSS classes, then you still end up with a conflict. The usualy trick is to come up with classes that are specific enough to your use that they won't collide.

And then the second problem of course is that any CSS value you don't explicitly set, you will keep inheriting from the owning document so if there's this in the owning document:

div { background: red }

and you use this for your specific snippet content:

div.personal.safety { font-family: fantasy }

then that will lead to your snippet content being a red div with fantasy font. Because you didn't change the background color for your snippet HTML.

This is all essentially "the basics of CSS" so I'd also strongly urge you to read up on how CSS works. Read an O'Reily book, or google for some tutorials (not w3schools or MDN examples of individual CSS rules, but proper "learn CSS" tutorials).

And read the links you got in the comments: security is no laughing matter, get that part right .

RE the Javascript question:

$('div.result').html(element).parent().addClass('safestyles');

Also, this look like jQuery rather than generic JS, so I've given a jQuery answer.

If you have nested BODY tags, which your post implies, then the BODY tag of the app might be conflicting with the BODY tag of the email itself.

Try putting the emails inside a DIV, and style that DIV.

RE the .safestyles class: it appears you are defining the style in the stylesheet, but not assigning that style to anything in your HTML.

Try:

<body>
    <div class="SafeStyles">
        <div class="test-div"><p class="test-p">Signature</p><strong id="test-strong">John Doe</strong></div>
    </div>
</body>

First make sure you understand Specificity and Selectors and then from your example, and then I'm guessing you could take 2 possible approaches: parsing the style source, either from HTML or CSS files, for all incoming content prepending a SafeStyles. to every CSS selector you find, thereby only allowing those rules to be set on elements inside of the div with that class, then displaying the new content wrapped in a div with class="SafeStyles" . Or the opposite, and protecting your own styles by increasing specificity on all them to the point where its unlikely they'd be overwritten I guess.

http://jsfiddle.net/xLeewd2w/ << Example provided

your provided html code

var myhtml =
'<html><head><style>div, p, span, a {padding: 0;margin: 0;color: black;}.test-div,est-p,#test-strong {color: blue !important;}</style></head><body><div class="test-div"><p class="test-p">Signature</p><strong id="test-strong">John Doe</strong></div></body></html>';

remove the pesky !important tags

var newhtml = myhtml.replace(" !important", "");

this is where I set the html contents, change the id to your chosen container

var example = $("#parsedhtml");

I'll set the html in the container

example.html(newhtml);

and then alter the css going after the id of #test-strong, only within example.

$("#test-strong", example).css({"background-color": "#ffe", "border": "5px solid #ccc", "font-size": "30px", "color":"red", "float":"right"});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM