Question

I have an issue with a web application I am creating. On the left hand side of the page I have an editable area, on the right a live preview. The live preview area is actually a HTML file with specially crafted fields that can be manipulated using the edit area. The problem is because the users HTML can be anything they wish. Some of the CSS can bleed out into the rest of my page. It's not uncommon for a user to do: background:red; in their design and cause my whole page to be red.

So, the solution to this (at least the one I have come up with), is to wrap the users styles into a parent class. Then have that parent class on the preview area. This way the users styles cannot bleed out into my design. I was considering something with like this with LESS and jQuery:

//psuedo code
less.Compile(".ParentClass { " + $("style").html() + "}");

However, I cant find any less libraries I can use like this. Does anyone know of a way I can append a CSS parent class to all the elements in a tag?

Examples:

<div id="Preview">
  <style>
     div { background: red; }
  </style>
  <div>I'm red</div>
</div>

Would become:

<div id="Preview">
  <style>
     #Preview div { background: red; }
  </style>
  <div>I'm red</div>
</div>

Edit: I know styles should really be in the head. However, the html documents being manipulated are actually going to be sent as emails. Email client support for CSS styling is shoddy at best, in some cases it's better to be in the body. Its frustrating but I have to work with my target.

Was it helpful?

Solution

Try this.

I loop through all style elements in dom, storing the rules and removing them from the dom when stored.

Then build the less style sheet, including the discovered style rules.

Finally, retrieve the less script and parse the style rules, adding them to the body, then set the master class to the body.

<html>
    <head>
    <script type="text/javascript"
      src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js">
    </script>
    <script type="text/javascript">
        $(function() {
            //Loop through all style elements in dom, storing the rules and removing them from the dom when stored
            var styles = "";

            $.each($("style"), function(index, value){
                styles += $(value).text();
                $(value).remove();
            });

            //Build the less stylesheet, including the discovered style rules
            var lessStyles = ".master { " + styles + " }";

            //Retrieve less and parse the style rules, adding them to the body, then set the master class to the body
            $.getScript("http://cdnjs.cloudflare.com/ajax/libs/less.js/1.7.0/less.min.js",function(){
                var parser = new(less.Parser);
                parser.parse(lessStyles, function (err, tree) {
                    if (err) { return console.error(err) }

                    var css = tree.toCSS();

                    $("<style/>").html(css).appendTo("body");
                    $("body").addClass("master");
                });
            });
        });
    </script>
    <style type="text/css">
        h2{
            color:green;
        }
    </style>
    </head>
    <body>
        <style type="text/css">
            .class2{
                color:red;
            }
        </style>

        <h1 class="class2">H1</h1>
        <h2>H2</h1>
    </body>
</html>

OTHER TIPS

Add a scoped attribute to the <style> element.

Browser support is currently awful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top