1

Is it possible to retrieve the browsers default value for a CSS property, ignoring any inline/imported styles, using JS?

Some context: I'm using JS to in-line all styles on a specific SVG element and its children (which allows me to turn it into a PNG using canvg). At the moment my output is hugely bloated with every single available style, I would like to be able to discard any properties which are using the browser default values from the array of styles that are include in-line.

Demo of what's happening:

$.extend($.fn, {
  makeCssInline: function() {
    this.each(function(idx, el) {
      var style = el.style;
      var properties = [];
      for (var property in style) {
        if ($(this).css(property)) {
          // TODO: Only in-line this style if it's not browser default
          properties.push(property + ':' + $(this).css(property));
        }
      }
      this.style.cssText = properties.join(';');
      $(this).children().makeCssInline();
    });
  }
});

$(document).ready(function() {
  $("#before").text($("svg")[0].outerHTML.length);
  $("svg").makeCssInline();
  $("#after").text($("svg")[0].outerHTML.length);
});
svg circle {
  fill: #080;
}

svg text {
  fill: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<svg version="1.1" baseProfile="full" width="300" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="150" cy="50" r="50" />
  <text x="150" y="65" font-size="40" text-anchor="middle">SVG</text>
</svg>

<p>Total characters before in-lining styles: <span id="before"></span></p>
<p>Total characters after in-lining styles: <span id="after"></span></p>

As you can see, even for a simple SVG this process adds a huge amount of unnecessary data.

DBS
  • 9,110
  • 4
  • 35
  • 53
  • `I would like to be able to discard any properties which are using the browser default values.` That's not how CSS works. All properties are always set on every single element, regardless of whether you set it or not. You cannot remove a CSS property, only set it back to its default. This is partly why using `css()` is a bad idea. Use classes to style the elements instead, you can then toggle that class on/off as needed. – Rory McCrossan Jul 27 '17 at 09:24
  • @RoryMcCrossan I'm sorry, that was poorly worded. I meant I would like to be able to discard the default styles from my array which will be appended inline. – DBS Jul 27 '17 at 09:26
  • Ah ok. Even in that case you're making a lot of extra work for yourself. I'd strongly suggest using classes instead. – Rory McCrossan Jul 27 '17 at 09:26
  • I wish I could, unfortunately canvg (the library I'm using to go from svg to png) requires the styles to be inline for the output to be produced correctly. And there don't appear to be any other libraries which cater to this. – DBS Jul 27 '17 at 09:28

1 Answers1

2

You can compute the default style value of a newly created element by using getComputedStyle(). But the new element must be inserted in the DOM for this to work:

function getDefaultStyleOf(tagName, name)
{
    var element = document.createElement(tagName);

    document.body.appendChild(element);
    var value = getComputedStyle(element)[name];
    document.body.removeChild(element);

    return value;
}

console.log(getDefaultStyleOf('code', 'font-size'));
Martin Wantke
  • 4,287
  • 33
  • 21
  • 1
    This will not work if the page has a stylesheet that applies rules to the element that's temporarily inserted into the document. – Melab Sep 11 '19 at 22:56