1

Is it possible to compute resulting css style on the element manually (without need to render it)?

Lets say I'm supposed to have an HTML structure:

<p style="some_style1">
  <span style="some_style2">
    <span style="some_style3">
       TEXT
    </span>
  </span>
</p>

I know what are some_style1, some_style2, some_style3 in terms of JS object (for example i have data for each element like: {font: 'Times New Roman' 12px bold; text-align: center;})

I want to MANUALLY (without need to render in browser the whole structure) compute resulting style that will effect "TEXT".

What algorithm (or solution) should I use?

Christoph
  • 50,121
  • 21
  • 99
  • 128
WHITECOLOR
  • 24,996
  • 37
  • 121
  • 181
  • 1
    Not quite sure what you ae looking for. Do you want Style1 to have a fontsize of 10 and then Style2 would have a size of Style1.fontsize + 2? – Limey Jun 20 '12 at 11:59
  • Just for `style` attributes, or do you need to consider the effect of stylesheets (page, user, user-agent) as well? – T.J. Crowder Jun 20 '12 at 12:20

4 Answers4

1

There exist browsers that don't need rendering in a window (headless browser). You can load a page and query what you want. It won't be easier than in a normal browser to obtain what you ask though.

JSCSSP is a CSS parser written in cross-browser JavaScript that could be a first step to achieve what you want from scratch or quite. Give it a stylesheet and it'll tell you what a browser would've parsed. You still must manage:

  • the DOM,
  • inheritance of styles,
  • determine which rules apply to a given element with or without class, id, attributes, siblings, etc
  • priorities of selectors
  • etc

Its author is D. Glazman, co-chairman of the W3C CSS group and developer of Kompozer, NVu and BlueGriffon so it should parse CSS as expected :)

FelipeAls
  • 21,711
  • 8
  • 54
  • 74
  • JSCSSP looks good, but I'm not seeing how it would handle `style` attributes and the HTML structure quoted. Looks fantastic for a bunch of other things, though. – T.J. Crowder Jun 20 '12 at 12:49
  • It won't, if I understood its intended use. The rest is done by rendering engines (minus the graphical part) and you'd have to parse HTML, have a list of classes, id, attributes and apply or not each rule based on its selector with their relative priority – FelipeAls Jun 20 '12 at 13:20
  • Ok, you did give me some ideas to think =) Thanks, marked the answer – WHITECOLOR Jun 20 '12 at 19:56
  • Meh, I finally found the names of browsers I was searching for: PhantomJS and alike (search for "**headless browser**" on SO and Google, not "chromeless browser" as I did) – FelipeAls Jun 21 '12 at 10:54
0

The simplest thing I can think of is to wrap the whole thing in a a container that you set display: none on, and append it to the DOM. The browser won't render it, but you'll then be able to query the computed style.

Here's an example showing how jQuery can't find the style information when the structure isn't connected to the DOM, but when it is, it can:

jQuery(function($) {

  // Disconnected structure
  var x = $("<p style='color: red'><span style='padding: 2em'><span style='background-color: white'>TEXT</span></span></p>");

  // Get the span
  var y = x.find("span span");

  // Show its computed color; will be blank
  display("y.css('color'): " + y.css('color'));

  // Create a hidden div and append the structure
  var d = $("<div>");
  d.hide();
  d.append(x);
  d.appendTo(document.body);

  // Show the computed color now; show red
  display("y.css('color'): " + y.css('color'));

  // Detach it again
  d.detach();

  function display(msg) {
    $("<p>").html(String(msg)).appendTo(document.body);
  }
});

Live copy | source

I can't guarantee all values will be exactly right, you'll have to try it and see; browsers may defer calculating some things until/unless the container is visible. If you find that some properties you want aren't calculated yet, you may have to make the div visible, but off-page (position: absolute; left: -10000px);

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

I found some articles about this: Can jQuery get all styles applied to an element on Stackoverflow.

Also this one on quirksmode: Get Styles that shows the following function:

function getStyle(el,styleProp)
{
    var x = document.getElementById(el);
    if (x.currentStyle)
        var y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
    return y;
}

This allows you to query for style properties

Community
  • 1
  • 1
Bart Vangeneugden
  • 3,436
  • 4
  • 33
  • 52
  • I think you need to re-read the qusetion. The above presupposes the elements have been added to the DOM. – T.J. Crowder Jun 20 '12 at 12:10
  • Fair enough, but doesn't your solution provide exactly the same? The only difference being your hides the rendered/added to dom elements – Bart Vangeneugden Jun 20 '12 at 14:34
  • 1
    @ Bart: Avoiding *rendering* them is different from avoiding *adding* them, and I highlighted that I was doing it, what the pitfalls of that might be, etc. That's the key difference (and I took advantage of the fact he was using jQuery, so I wouldn't have to deal with the `currentStyle` / `getComputedStyle` stuff). – T.J. Crowder Jun 20 '12 at 15:14
0

Styles override each other in the order in which they're defined: So anything in some_style3 that overrides the same selector in some_style2, say, will do. Otherwise, it will just be a union of the sets of selectors.

EDIT Some selectors won't override, but instead act relatively on a previous definition, so you've got to be careful about that.

Xophmeister
  • 8,884
  • 4
  • 44
  • 87
  • 1
    Granted the examples the OP gave use `style`, for which the above is *mostly* true (`!important` styles in stylesheets will still override inline `style`, so `

    ` could well be red). Throw proper stylesheets in, and it gets a **lot** more complicated.

    – T.J. Crowder Jun 20 '12 at 12:15