19

I know that $("#divId").html() will give me innerHtml. I also need its styles (which might be defined by the means of classes) either in-line style attribute or all the styles/classes within a separate <style> tag.

Is it possible?

UPDATE
What if html is like <div id="testDiv">cfwcvb</div> and a css class for #testDiv is defined in external stylesheet?

UPDATE 2
Sorry for not clarifying this earlier

If this is my HTML

<div id="divId">
    <span class="someClass">Some innerText</span>
</div>

And styles are defined in separate style sheet or in head styles.

#divId {
    clear: both;
    padding: 3px;
    border: 2px dotted #CCC;
    font-size: 107%;
    line-height: 130%;
    width: 660px;
}
.someClass {
    color: blue;
}

Then when I try to get inner html of $("#divId").html() or call any other custom function, I need something like below

<style>
#divId {
    clear: both;
    padding: 3px;
    border: 2px dotted #CCC;
    font-size: 107%;
    line-height: 130%;
    width: 660px;
}
.someClass {
    color: blue;
}
</style>

<div id="divId">
    <span class="someClass">Some innerText</span>
</div>

UPDATE 3 for Answer by kirilloid
I ran below code in Command Window of Chrome Debugger tools for this page itself and this is what I see TypeError: Cannot read property 'rules' of undefined

function getElementChildrenAndStyles(selector) {
  var html = $(selector).get(0).outerHTML;

  selector = selector.split(",").map(function(subselector){
    return subselector + "," + subselector + " *";
  }).join(",");
  elts = $(selector);

  var rulesUsed = [];
  // main part: walking through all declared style rules
  // and checking, whether it is applied to some element
  sheets = document.styleSheets;
  for(var c = 0; c < sheets.length; c++) {
    var rules = sheets[i].rules || sheets[i].cssRules;
    for(var r = 0; r < rules.length; r++) {
      var selectorText = rules[r].selectorText;
      var matchedElts = $(selectorText);
      for (var i = 0; i < elts.length; i++) {
        if (matchedElts.index(elts[i]) != -1) {
          rulesUsed.push(CSSrule); break;
        }
      }
    }
  }
  var style = rulesUsed.map(function(cssRule){
    if ($.browser.msie) {
      var cssText = cssRule.style.cssText.toLowerCase();
    } else {
      var cssText = cssRule.cssText;
    }
    // some beautifying of css
    return cssText.replace(/(\{|;)\s+/g, "\$1\n  ").replace(/\A\s+}/, "}");
    //                 set indent for css here ^ 
  }).join("\n");
  return "<style>\n" + style + "\n</style>\n\n" + html;
};
getElementChildrenAndStyles(".post-text:first");
Community
  • 1
  • 1
IsmailS
  • 10,797
  • 21
  • 82
  • 134
  • I think your title should be "How to get all styles ..", also this is similar: http://stackoverflow.com/questions/754607/can-jquery-get-all-css-styles-associated-with-an-element – thirtydot Jan 24 '11 at 11:34
  • can you tell **why** do you need this exactly? perhaps there's an easy way of doing this. – gblazex Feb 03 '11 at 12:40
  • Because I'm copying html of an element from one document to other window's document which is an iFrame. – IsmailS Feb 07 '11 at 20:09

9 Answers9

13

outerHTML (not sure, you need it — just in case)

Limitations: CSSOM is used and stylesheets should be from the same origin.

function getElementChildrenAndStyles(selector) {
  var html = $(selector).outerHTML();

  selector = selector.split(",").map(function(subselector){
    return subselector + "," + subselector + " *";
  }).join(",");
  elts = $(selector);

  var rulesUsed = [];
  // main part: walking through all declared style rules
  // and checking, whether it is applied to some element
  sheets = document.styleSheets;
  for(var c = 0; c < sheets.length; c++) {
    var rules = sheets[c].rules || sheets[c].cssRules;
    for(var r = 0; r < rules.length; r++) {
      var selectorText = rules[r].selectorText;
      var matchedElts = $(selectorText);
      for (var i = 0; i < elts.length; i++) {
        if (matchedElts.index(elts[i]) != -1) {
          rulesUsed.push(rules[r]); break;
        }
      }
    }
  }
  var style = rulesUsed.map(function(cssRule){
    if (cssRule.style) {
      var cssText = cssRule.style.cssText.toLowerCase();
    } else {
      var cssText = cssRule.cssText;
    }
    // some beautifying of css
    return cssText.replace(/(\{|;)\s+/g, "\$1\n  ").replace(/\A\s+}/, "}");
    //                 set indent for css here ^ 
  }).join("\n");
  return "<style>\n" + style + "\n</style>\n\n" + html;
}

usage:

getElementChildrenAndStyles("#divId");
Community
  • 1
  • 1
kirilloid
  • 14,011
  • 6
  • 38
  • 52
  • Thanks for the answer. I tried what you answered. I've updated my question with the output of what I tried. Just a small change I've made to what you have answered is `$(selector).get(0).outerHTML` from `$(selector).outerHTML()` so that I don't need [outerHTML](http://stackoverflow.com/questions/2419749/jquery-get-selected-elements-outer-html). – IsmailS Feb 08 '11 at 11:16
  • There was one stupid err -- I've fixed it (and edited the code in my post). But then I've got another problem: security. In most browsers one cannot access CSS via DOM (i.e. the way, I use) from another domains. On stackoverflow CSS file is placed on http://sstatic.net/stackoverflow/ I've tested changed example at http://www.ibm.com/us/en/sandbox/ver2/ with "#ibm-search-form" and it works, but you'll need to add `var $ = jQuery;` at the beginning of the function, in order to work in @ibm.com – kirilloid Feb 08 '11 at 11:56
  • Thanks, you will definitely get the bounty you deserve. Nicely done job. One more bug though. its missing `http:` when I tested as you had on the link you gave. – IsmailS Feb 09 '11 at 07:51
  • Note that cssText doesn't seem to include any custom styles that an element might have. Most of the time this won't be a problem, but with what I myself am working on, it's something I needed to know. – Perry Monschau Feb 25 '15 at 14:26
  • How to get the styles with Class name grouping? – yenkay Aug 17 '17 at 11:57
  • You need to adjust code somewhere just after when the `selectorText` variable is set. Just store information about the class (in whatever way you get it from selector) and then sort/group by classes before displaying them. – kirilloid Aug 22 '17 at 13:38
8

No jQuery and no IE support, that's all I can do:

enter image description here

<!doctype html>

<html>
    <head>
        <meta charset = "utf-8">

        <script type = "text/javascript">
            Element.prototype.getStyles = function () {
                var array = {};
                var styles = window.getComputedStyle (this, null);

                for (var i = 0; i < styles.length; i ++) {
                    var style = styles[i];

                    array[style] = styles[style];
                }

                return array; // return new Array (array, this.innerHTML); You can also return the HTMl content. I don't think its necessary
            }

            window.addEventListener ("load", function () {
                var divId = document.getElementById ("divId");
                var someClass = document.getElementsByClassName ("someClass");

                var string = "";
                var styles = divId.getStyles ();

                for (var i in styles) {
                    string += i + ": " + styles[i] + "\n";
                }

                alert (string);
                alert ("In-line style: Height ->" + styles["height"] + "\n" + "Out-line style: Width ->" + styles["width"])
                alert ("HTML: " + divId.innerHTML);

                // Same thing with the span element
            }, false);
        </script>

        <style>
            #divId {
                clear: both;
                padding: 3px;
                border: 2px dotted #CCC;
                font-size: 107%;
                line-height: 130%;
                width: 660px;
            }
            .someClass {
                color: blue;
            }
        </style>

        <title>Test</title>
    </head>

    <body>
        <div id = "divId" style = "height: 100px">
            <span class = "someClass">Some innerText</span>
        </div>
    </body>
</html>
Caio
  • 3,178
  • 6
  • 37
  • 52
  • I need styles like ` ` even when they are defined in separate style sheet. And then the html mark up – IsmailS Feb 08 '11 at 14:51
7

You can get hold of a style object representing the computed style for an element using window.getComputedStyle() in most browsers and the element's currentStyle property in IE. There are several browser differences, however, with values returned for shortcut properties (such as background), color RGB values, lengths and even font-weight (see this useful test page). Test carefully.

function computedStyle(el) {
    return el.currentStyle || window.getComputedStyle(el, null);
}

alert(computedStyle(document.body).color);
Tim Down
  • 318,141
  • 75
  • 454
  • 536
4

You can use something like this for script:-

<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.js"></script>
<script type="text/javascript">
$(function(){
    var styleVal = $('#testDiv').attr('style');
    console.warn("styleVal >>>   " + styleVal);
})
</script>

and simple html would be like this

<div style="border:1px solid red;" id="testDiv">cfwcvb</div>
Álvaro González
  • 142,137
  • 41
  • 261
  • 360
Mahima
  • 489
  • 1
  • 5
  • 17
3

if you want to save all of the style of an element i think this will be more complicated as you think first of all my first ide was the firebug css console. this shows all fo the style of an element and i thought how? so i searched for the source code of the firebug and i found this:

http://fbug.googlecode.com/svn/branches/firebug1.7/content/firebug/css.js

this code working only on the css part.

const styleGroups =
{
    text: [
        "font-family",
        "font-size",
        "font-weight",
        "font-style",
        "color",
        "text-transform",
        "text-decoration",
        "letter-spacing",
        "word-spacing",
        "line-height",
        "text-align",
        "vertical-align",
        "direction",
        "column-count",
        "column-gap",
        "column-width"
    ],

    background: [
        "background-color",
        "background-image",
        "background-repeat",
        "background-position",
        "background-attachment",
        "opacity"
    ],

    box: [
        "width",
        "height",
        "top",
        "right",
        "bottom",
        "left",
        "margin-top",
        "margin-right",
        "margin-bottom",
        "margin-left",
        "padding-top",
        "padding-right",
        "padding-bottom",
        "padding-left",
        "border-top-width",
        "border-right-width",
        "border-bottom-width",
        "border-left-width",
        "border-top-color",
        "border-right-color",
        "border-bottom-color",
        "border-left-color",
        "border-top-style",
        "border-right-style",
        "border-bottom-style",
        "border-left-style",
        "-moz-border-top-radius",
        "-moz-border-right-radius",
        "-moz-border-bottom-radius",
        "-moz-border-left-radius",
        "outline-top-width",
        "outline-right-width",
        "outline-bottom-width",
        "outline-left-width",
        "outline-top-color",
        "outline-right-color",
        "outline-bottom-color",
        "outline-left-color",
        "outline-top-style",
        "outline-right-style",
        "outline-bottom-style",
        "outline-left-style"
    ],

    layout: [
        "position",
        "display",
        "visibility",
        "z-index",
        "overflow-x",  // http://www.w3.org/TR/2002/WD-css3-box-20021024/#overflow
        "overflow-y",
        "overflow-clip",
        "white-space",
        "clip",
        "float",
        "clear",
        "-moz-box-sizing"
    ],

    other: [
        "cursor",
        "list-style-image",
        "list-style-position",
        "list-style-type",
        "marker-offset",
        "user-focus",
        "user-select",
        "user-modify",
        "user-input"
    ]
};

the function which gets all of the styles.

updateComputedView: function(element)
{
    var win = element.ownerDocument.defaultView;
    var style = win.getComputedStyle(element, "");

    var groups = [];

    for (var groupName in styleGroups)
    {
        var title = $STR("StyleGroup-" + groupName);
        var group = {title: title, props: []};
        groups.push(group);

        var props = styleGroups[groupName];
        for (var i = 0; i < props.length; ++i)
        {
            var propName = props[i];
            var propValue = stripUnits(rgbToHex(style.getPropertyValue(propName)));
            if (propValue)
                group.props.push({name: propName, value: propValue});
        }
    }

    var result = this.template.computedTag.replace({groups: groups}, this.panelNode);
    dispatch(this.fbListeners, 'onCSSRulesAdded', [this, result]);
}

function stripUnits(value)
{
    // remove units from '0px', '0em' etc. leave non-zero units in-tact.
    return value.replace(/(url\(.*?\)|[^0]\S*\s*)|0(%|em|ex|px|in|cm|mm|pt|pc)(\s|$)/gi, function(_, skip, remove, whitespace) {
    return skip || ('0' + whitespace);
    });
}

in this code i figured out that the

win.getComputedStyle(element, "")

to get all of the styles of an element, and then with a for loop gets all of the style and prints out. so i think the getComputedSTyle is the main function to use, and after this you can get the props one by one with:

style.getPropertyValue(propName)
Gergely Fehérvári
  • 7,811
  • 6
  • 47
  • 74
1

Based on kirilloid's answer, I've created a developer tools extension for Chrome that incorporates that code for capturing styles and markup for a page fragment. The extension is in the Chrome Web Store and is on Github. All of the "Author Styles" output options use that method for iterating over the stylesheets.

enter image description here

ifugu
  • 648
  • 7
  • 11
0

The .css() method gets a particular style of the element... I don't know if you can retrieve all styles:

http://api.jquery.com/css/

Víctor B.
  • 1,630
  • 2
  • 14
  • 21
0

Generally you can access style parameter using .attr('style'). If you want to access computed style you can use window.getComputedStyle(element) in Opera, Firefox, Chrome and other sane browsers. For IE you'd do the same with element.currentStyle.

Also if you wish to access individual CSS style you can do so with jQuery .css method. Like so $("#divId").css('font-size').

MeanEYE
  • 967
  • 8
  • 24
0

You can get the stylesheet defined inside style tags under document.styleSheets. You can read the rules into a map, and find them by selectorText. So by id: "#id", by classes: ".className". By safari or chrome you can use getMatchedCSSRules.

Community
  • 1
  • 1
inf3rno
  • 24,976
  • 11
  • 115
  • 197