10

NOTE: This has an update below. I will likely change description as it is not a getComputedStyle issue, it is an issue actually with print-media and the fact that Internet Explorer now supports document.styleSheets[].cssRules.


I am a bit confused on this as I thought this worked and I am not sure it just recently broke. I am using getComputedStyle which I thought was support in all modern browsers, but I do not get the expected answer with IE 11. Given this code:

getRealStyle: function(elm, attributes) {
    var returnObj = {};
    var computed = getComputedStyle(elm);
    for(var i=0; i<attributes.length; i++) {
        returnObj[attributes[i]] = computed[attributes[i]];
    }
    return returnObj;
},

Where "attributes" is an array of names which I am interested in getting the computed CSS for. It is like this:

attributes: [
        'lineHeight', 
        'alignmentBaseline', 
        'backgroundImage', 'backgroundPosition', 'backgroundRepeat', 'backgroundColor',
        'baselineShift', 
        'borderTopWidth','borderTopStyle','borderTopColor', 
        'borderBottomWidth','borderBottomStyle','borderBottomColor',
        'borderLeftWidth','borderLeftStyle','borderLeftColor',
        'borderRightWidth','borderRightStyle','borderRightColor',
        'borderCollapse',             
        'clear', 'color', 
        'display', 'direction', 'dominantBaseline', 
        'fill', 'float', 
        'fontStyle', 'fontVariant', 'fontWeight', 'fontSize', 'fontFamily', 
        'height',
        'listStyleType', 'listStyleImage', 
        'marginTop', 'marginBottom', 'marginLeft', 'marginRight','orphans', 
        'paddingTop', 'paddingRight', 'paddingBottom', 'paddingLeft',
        'pageBreakAfter', 'pageBreakBefore', 
        'stroke', 'strokeWidth',
        'strokeOpacity', 'fillOpacity',
        'tableLayout', 
        'textAlign', 'textAnchor','textDecoration', 'textIndent', 'textTransform', 'textShadow',
        'verticalAlign',
        'widows', 'width'],

The only problem I seem to have is "backgroundColor".

If I pass in an "elem" h1 and:

If I set on the "h1" style="background-color:rgb(238, 238, 238);" The computed background color is returned correctly in IE 11, Chrome, Firefox

If however I set the "h1" style in CSS like this:

h1{
border-top:3px solid #111111;
background-color:rgb(238, 238, 238);
font-size:30px;
padding:3px 10px 3px 0px;
}

The computed background-color in IE only is returned as transparent. Chrome and Firefox do not have his problem.

Even more strange in that sample, "attributes" also contains entries for the border like borderTopColor and that is correctly computed with that code in all browsers including IE.

The page in question is here:

http://www.cloudformatter.com/CSS2Pdf

The code runs when selecting the "Out PDF" button.

If you format this with Chrome, the "h1" at the top of the page in the resulting PDF will have the silver background because the background-color is picked up in getComputedStyle. The border-top will also be there. But if you format in IE11 the background-color will be missing because it is returned as "transparent" but the border will be there and both of these are set in the css.

Similar behavior you can see here http://www.cloudformatter.com/CSS2Pdf.Demos.InlineElements

The "Exception" box is 100% in css. The border works but the color and image does not as they are missing. The font color is also missing as that is set in CSS ... but not everything in CSS is ignored. I even added a few console write's (left is IE, right is Chrome).

enter image description here

IN the above code, I have tried this so far and IE returns "transparent" for the background-color BUT returns the correct color for the border:

getRealStyle: function(elm, attributes) {
    var returnObj = {};
    var computed = getComputedStyle(elm);
    if (elm.localName == 'h1'){
    console.log('***** ' + elm.localName + ' *****');
    console.log('BackgroundColor: ' + computed.backgroundColor);
    console.log('PropValue: ' + computed.getPropertyValue('background-color'));
    console.log('BorderTopColor: ' + computed.borderTopColor);
    }
    for(var i=0; i<attributes.length; i++) {
        returnObj[attributes[i]] = computed[attributes[i]];
    }
    return returnObj;
},

So, am I missing something here or is getComputedStyle not working for IE 11 for something's in external CSS?

UPDATE:

After hours and hours I have isolated the issue as NOT being getComputedStyle. It turns out that IE is working and in fact doing so as we expected in our coding. It is the other browsers that had issues we had not noted until now.

The code uses document.styleSheets[].cssRules to iterate over all CSS and extract print media directives to apply for the PDF formatting. One of those linked CSS files on a remote server is "bootstrap.min.css" and buried within it were CSS rules like no background, all black text, etc.

Well, if you run the code in Firefox and try to access the cssRules, it was actually a caught security error so they are not read. On Chrome, it does not throw any (obvious) error but returns "null". So these browsers "worked" because these CSS rules were never read.

Along comes IE and low and behold, it supports it. It reads the values from a remote CSS without failing or security warning. And because of that, the CSS from "bootstrap.min.css" to do all that stuff was being applied.

So, to fix this for all browsers I only needed to follow the advice here:

Accessing cross-domain style sheet with .cssRules

And then implement rules to skip the print media in certain files (like bootstrap.min.css)

Community
  • 1
  • 1
Kevin Brown
  • 8,805
  • 2
  • 20
  • 38
  • 1
    when I log this in the IE11 console, (`getComputedStyle(document.getElementById('Headings')).backgroundColor`)it returns `rgb(238, 238, 238)` for me as expected, so there must be more to the story. – chiliNUT Jun 14 '15 at 04:44
  • I agree. I just tried that also. – Kevin Brown Jun 14 '15 at 04:47
  • And what I mean @chiliNUT to there being more to the story ... what is confusing is that there is no difference between the background and the border in the fact they are both set in CSS. The Javascript above correctly returns the border color, but not the background color. – Kevin Brown Jun 14 '15 at 06:34
  • Well .... the code basically clones everything in the selected div into the DOM while recomputing the resolved CSS. Essentially a way to "scrape" the current complete style for the formatting task to PDF. So, at one point, there is two h1's. – Kevin Brown Jun 14 '15 at 07:24
  • I have now isolated where the issue lies. I will report more tomorrow ... too much wine to think it through. Somewhere in the JS code that is applying the print media style sheet(s) is where things are getting lost. Thanks to @chiliNUT for forcing me to do a simple JSFiddle and of course, I could not break it. It worked perfect. I walked the Javascript backward and removing the code that applies print-media solves the problem (except all the print-media rules break). – Kevin Brown Jun 14 '15 at 07:28
  • No comments are dumb, they are all welcome @user4749485. I know now what the problem is. Inside that Javascript is code that calculates all the print-media rules and copies them into the header (and then deletes them). And here is the issue (or I so hate IE) ... IE seems to have a bunch of print-media rules built in ... that include this: background: none !important; color: rgb(0, 0, 0) !important; How insane is that? No backgrounds and everything black. Now, on to hacking how to NOT include these into what normal people would actually want. – Kevin Brown Jun 14 '15 at 08:06
  • I also hate IE... but most browsers have settings in print-media that disable backgrounds. And I think this is sensible; the good-looking background that you added to your page is often a mess and an ink-consuming nuissance in print-media. .. That has always been a difference between images and backgrounds. Most probably (I don't use IE much) this is an option in the browser settings – vals Jun 14 '15 at 09:54

1 Answers1

0

Just so that this question is closed out, you can examine the question above for the update.

As it turns out, some recent version of Internet Explorer now supports document.styleSheets[] and more importantly supports extracting the cssStyles from those styleSheets no matter if they are hosted locally or remotely.

This change caused our code to start reading a remotely hosted CSS style that was not previously read and not noticed because it actually errors in Chrome and Firefox.

So getting access to remotely hosted CSS stylesheets as an object does not require anything with Internet Explorer now (it works without any changes) but does require one to something different in Chrome and Firefox (like setting crossorigin="anonymous" on the link tag).

Kevin Brown
  • 8,805
  • 2
  • 20
  • 38