How to Get a Computed Style

How do I get a computed style?

See this answer.

It's not jQuery but, in Firefox, Opera
and Safari you can use
window.getComputedStyle(element) to
get the computed styles for an element
and in IE you can use
element.currentStyle. The returned
objects are different in each case,
and I'm not sure how well either work
with elements and styles created using
Javascript, but perhaps they'll be
useful.

The iframe looks about 150px high to me. If its contents are 1196px high (and indeed, you appear to be exploring the html node, according to the screenshot) and that's what you want to get, then you should navigate into the DOM of the iframe's document and apply the above technique to that.

Get the computed style and omit defaults

there you go,
i did this by adding a new dummy DOM element, to know which styles are default for any element.

/**
* IE does not have `getComputedStyle`
*/

window.getComputedStyle = window.getComputedStyle || function( element ) {
return element.currentStyle;
}

/**
* get computed style for an element, excluding any default styles
*
* @param {DOM} element
* @return {object} difference
*/

function getStylesWithoutDefaults( element ) {

// creating an empty dummy object to compare with
var dummy = document.createElement( 'element-' + ( new Date().getTime() ) );
document.body.appendChild( dummy );

// getting computed styles for both elements
var defaultStyles = getComputedStyle( dummy );
var elementStyles = getComputedStyle( element );

// calculating the difference
var diff = {};
for( var key in elementStyles ) {
if(elementStyles.hasOwnProperty(key)
&& defaultStyles[ key ] !== elementStyles[ key ] )
{
diff[ key ] = elementStyles[ key ];
}
}

// clear dom
dummy.remove();

return diff;
}


/**
* usage
*/

console.log( getStylesWithoutDefaults( document.getElementById( 'bar' ) ) );

Notes:

  • the result will have some extra properties, not only those you've mentioned.

demo - console should be opened

Get current / computed style of an HtmlElement in WebBrowser control

The style property returns the value that you have explicitly assigned to style.

To get the computed style, you can use currentStyle property of element or getComputedStyle method of the window.

The following code get computed background-color and computed color for an a element:

webBrowser1.DocumentText = @"
<html>
<head>
<style>
a {background-color:red;}
</style>
<title>Test</title>
</head>
<body>
<a id='a1' href='#' style='color:yellow;'>Test</a>
</body>
</html>";

webBrowser1.DocumentCompleted += (obj, arg) =>
{
dynamic element = webBrowser1.Document.GetElementById("a1").DomElement;
var style = element.currentStyle;

// OR
// dynamic window = webBrowser1.Document.Window.DomWindow;
// var style = window.getComputedStyle(element, null);

var backColor = style.backgroundColor;
var color = style.color;
};

How get all computed css properties of element and its children in Javascript

Here is something I came up with, basically pass the element you want to extract the styles of and ones of its children, and it will return you the stylesheet as a string. Open your console before running the snippet and you will see the output from the console.log.

Because I wanted to support the extraction of every element even those without a selector, I had to replace each element id by a unique uuid specifically generated for them in order to facilitate the styling of your output. The problem with this approach is in case you are using ids for styling or for user interaction, you are going to loose such functionality on concerned elements after calling extractCSS.

However, it is pretty trivial to use the oldId I'm passing to change back once your pdfKit process finished the generation. Simply call swapBackIds passing the elements returned by the function. You can see the difference of behavior if you uncomment the call in my snippet: the #root pink background would disappear because the styling targets an element id.

All in all, you need to:

  1. Call extractCSS with the element you want to extract
  2. Generate your pdf using res.stylesheet
  3. Call swapBackIds with res.elements

// Generate an unique id for your element
// From https://stackoverflow.com/a/2117523/2054072
function uuidv4 () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}

// Flatten an array
// https://stackoverflow.com/a/15030117/2054072
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}

function recursiveExtract (element) {
var id = uuidv4()
var oldId = element.id

var computed = window.getComputedStyle(element)
var style = computed.cssText

// Now that we get the style, we can swap the id
element.setAttribute('id', id)

// The children are not a real array but a NodeList, we need to convert them
// so we can map over them easily
var children = Array.prototype.slice.call(element.children)
return [{ id: id, style: style, oldId: oldId }].concat(children.map(recursiveExtract))
}

function extractCSS (element) {
if (!element) { return { elements: [], stylesheet: '' } }

var raw = recursiveExtract(element)
var flat = flatten(raw)

return {
elements: flat,
stylesheet: flat.reduce(function (acc, cur) {
var style = '#' + cur.id + ' {\n' + cur.style + '\n}\n\n'
return acc + style
}, '')
}
}

var pdfElement = document.querySelector('#root')
var res = extractCSS(pdfElement)

console.log(res.stylesheet)

function swapBackIds (elements) {
elements.forEach(function (e) {
var element = document.getElementById(e.id)
element.setAttribute('id', e.oldId)
})
}

swapBackIds(res.elements)
#root {
background-color: pink;
}

.style-from-class {
background-color: red;
width: 200px;
height: 200px;
}

.style-from-id {
background-color: green;
width: 100px;
height: 100px;
}
<div id="root">
<span>normal</span>
<span style="background: blue">inline</span>
<div class="style-from-class">
style-class
</div>
<div class="style-from-id">
style-id
<div style="font-size: 10px">a very nested</div>
<div style="font-size: 12px; color: white">and another</div>
</div>
</div>

<div id="ignored-sibling">
</div>

Computed style as a JavaScript object

While I'm not aware of a pre-rolled function which will do the work for us, it's fairly trivial to grab all of the properties as you've indicated you'd like to.

Here's some code that will achieve it. First, we define a function that will give us forEach functionality on non-array objects. Next, we get the computedStyle of the target element before finally iterating through the collection of returned CSSStyleDeclaration objects, adding the property name and value to an object we later return.

"use strict";
// useful for NodeList & HtmlCollection typesfunction forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
window.addEventListener('load', onDocLoaded, false);function onDocLoaded(evt){ var computedStyle = getTheStyle( document.getElementById('elem-container') ); alert("Element has a height of: " + computedStyle.height + "\n" + "And a position of: " + computedStyle.position);}
function getTheStyle(tgtElement){ var result = {}, properties = window.getComputedStyle(tgtElement, null); forEach( properties, function(prop) { result[prop] = properties.getPropertyValue(prop); } ); console.log(result); return result;}
 #elem-container{   position: absolute;   left:     100px;   top:      200px;   height:   100px; }
<div id="elem-container">dummy</div><div id="output"></div> 


Related Topics



Leave a reply



Submit