I am writing this article in the spirit of the scientific principle that negative results should be published (but there is some helpful stuff later on.)

Many of us today are not developing new applications but ones which must work with, or sit within other applications that generate HTML and JavaScript. One very common example is developing a WordPress plug-in, others include portlets and working with a home-grown PHP application.

It is possible, and indeed likely, that the WordPress plug-in author wants to carefully control the appearance and positioning of the elements rendered by his plug-in. In my own case I am using a sophisticated JavaScript library that comes with its own style-sheet.

In this case it is necessary to ensure that styles declared in the outer application (WordPress theme) do not apply to the elements rendered by the plug-in. I have tried several approaches to enforcing this but have not been able to create a general solution to the problem.

The starting point for any solution is to create a named DIV To contain the HTML for the plug-in. This HTML could be static, generated by PHP (ASP) or JavaScript.

<DIV ID="myPlugin">
  ....
</DIV>

The next step is to create a stylesheet, or modify the stylesheet for your JavaScript library, so that it applies strictly to the contents of your div. This ensures that your own plugin’s styles only apply with your application and don’t break the outer application.

/* Simple example of a stylesheet that applies only to a single div */
/* Define attributes common to many elements */

div#myPlugin <selector 1>,
div#myPlugin <selector 2>,
div#myPlugin <selector 3>{
   attribute1:value1
   ...
}

/* Define attributes for library styles */
div#myPlugin .<library style 1>{
  attribute1:value1
  ...
}

We have now protected the outer application from our plug-in, but how can we protect our plug-in from styles in the outer application?

You cannot sandbox a div from the outer application

The problem is that the outer application can always create a CSS selector that is more specific than the ones in your plug-in stylesheets. This is a fundamental problem because a well-designed plug-in stylesheet will use as few selectors as possible and rely on the CSS cascade to style the HTML elements that are rendered. Therefore in general plug-in selectors are weakly specific nd will frequently be overwritten by rules in the outer application.

The rules for calculating the specificity of CSS selectors are defined here. It should also be understood that any rule that applies to a particular element is more specific than a rule that applies to its parent. Consider this HTML fragment,

<div id="themeContent">
   <div id="myPlugin">
      <table class="myPlugClass1">
         <tr>
          <td>

We might expect at the table cell, <td> Would be styled using a rule in our stylesheet

div#myPlugin .myPluginClass1{
      border-width:3 /* this is essential */
}

But if the following rule exists in the theme, then that will dominate

div#themecontent <table> <tr> <td> {
       border-width:0
}

We can see that in general it is not possible to protect our plug-in because the author of the application theme can always write a more specific selector even after we have deployed the application.

Failed approaches

When creating a new stylesheet for an application or theme it is common practice to “reset” the browser by defining styles that set the browser to a known condition. This raises the possibility of “resetting a div”. However this is not possible, the authors of reset stylesheets have a good understanding of the default behaviour of web browsers, hence they only need to reset known values. However in our scenario we have no idea about what styles are applied by the outer application.

Final approach

The problem cannot be solved in general and even when it is solved in particular, the solution is not robust because of changes to styles in the outer application can break the plug-in.

Thus the final approach must be one of configuration management. The plug-in must be tested with a particular theme in the outer application. So for example, in the WordPress scenario it might be tested with well-known themes such as Twenty-Ten, Twenty-Eleven … .

Debugging

It is likely that your plug-in will not be styled correctly initially and you will need to create an additional stylesheet to fix issues caused by a particular theme. So for example you may have two stylesheets your plug-in,

  • myPlugIn.css
  • myPlugIn-Fixes-For-Twenty-Ten.css

To find out what I needed to put into myPlugIn-Fixes-For-Twenty-Ten.css I got my plug-in to render some simple tables and and lists. So for example

<table class="myPlugClass1">
  <tr>
    <td>
        What style is applied to me?
    </td>
  </tr>
</table>

I rendered the page and selected the cell text and then used the browser’s development tools to “Inspect element”. By moving through each of the elements in turn it is possible to see where selectors in the outer stylesheet are affecting your plug-in. So, referring back to the example above I can create a new rule in my fix stylesheet.

div#myPlugin <table> <tr> <td> {
       border-width:3 /* this is essential*/
}

In conclusion

CSS does not provide the ability to sandbox a div and it is not possible to robustly protect the styling of the plug-in. It is possible to manually create rules that will ensure your application is styled correctly but the solution is only robust if changes to the style-sheets of the outer application are carefully controlled.

and finally

This is a very technical area and it is possible to have made a mistake or that you have a better approach, if so the please add a comment below.

Advertisements