19

I could probably muddle through the code for this, but before I do I thought I'd ask if there's a quick and/or built-in way or plugin for this...

Given a table with a css class applied to it, the class definition being in an external style sheet (with styles applied to th, tr, and td) I want to move OR copy that css to the style attribute of the tags themselves. In other words I want to make the CSS inline.

Reason: People who use these pages sometimes copy and paste the tables into emails. If they do this on a table with externally-sourced CSS the pasted table has lost all formatting. If the css is inline the formatting is retained.

I have already done this in a rough-and-ready way by simply applying duplicated css to the table using $().css(); function, but this is not ideal. If I ever changed the css in the style sheet I'd also have to change the CSS in this part on every single page that has this style of table

Something like $('.mytable').makeCSSInline(); would be an ideal function - if it existed :)

edit: Just for clarification: I don't think the copy/paste will retain the css if it's in an internal style sheet (copied using the .load function).. It has to be fully inline (in the style attribute of each tag that has a style associated with it).

Also, I'm copying from firefox to outlook (so from non-microsoft to microsoft)

MrVimes
  • 3,212
  • 10
  • 39
  • 57

6 Answers6

18

This isn't exactly perfect but I think it's pretty close to what you're looking for.

(function($) {
    $.extend($.fn, {
        makeCssInline: function() {
            this.each(function(idx, el) {
                var style = el.style;
                var properties = [];
                for(var property in style) { 
                    if($(this).css(property)) {
                        properties.push(property + ':' + $(this).css(property));
                    }
                }
                this.style.cssText = properties.join(';');
                $(this).children().makeCssInline();
            });
        }
    });
}(jQuery));

Then you'd just call it with:

$('.selector').makeCssInline();
illvm
  • 1,336
  • 13
  • 28
  • awwww I was so hopeful for this :) but it copies every conceivable css property, not just the custom ones. for example, here's just one opening tr tag after the function ... but thanks for trying. :) – MrVimes Nov 29 '10 at 20:55
  • ran out of comment room.... It causes the page performance to take a massive hit. I have some quite large tables to show. I guess I'll have to abandon this idea. – MrVimes Nov 29 '10 at 20:56
  • The performance hit seems to be because this is a recursive function.....still, this is an interesting concept, definitely worth coming back to. –  Aug 14 '13 at 03:59
  • this is great but there's a large amount of styles made inline. How could this be modified to grab an elements class and only apply those styles? – v3nt Dec 08 '14 at 17:08
  • This is good for extending the JQuery object and allow for isolated element "inlining". Performance hit is only realized if you have an archaically nested element structure and apply this from the `body`, or similar super element. – GoldBishop Mar 22 '17 at 19:12
5

Mailchimp has an online tool for this:

http://templates.mailchimp.com/resources/inline-css/

Just paste in your HTML with CSS in the head and it will spit it out with inline styles.

Felix Eve
  • 3,811
  • 3
  • 40
  • 50
4

I had the same problem, I wanted to get all css inline for email compatibility, I found a great jQuery plugin

https://github.com/Karl33to/jquery.inlineStyler

I know it's a bit late for this question, but it's a very easy solution.

$('.mytable').inlineStyler();

Hope it might help

Romain
  • 51
  • 4
  • Will this plugin support table css like ** table { border: 1px solid blue; } tr:nth-last-child(-n+3) { /* the last 3 siblings */ background-color: lime; }** – vignesh Aug 13 '15 at 08:07
  • @vignesh I didn't tried but here is the process : the method get all the rules currently defined for each element and set the "attribute: value" in the "style" attribute. So, as long as the browser you are using supports this rules, there is no problem. Needs some tests – Romain Oct 19 '15 at 17:09
  • Good effort, thanks. Seems to have more improvements. – Vaishak Jan 08 '16 at 06:25
3

I would do a jquery load() and dump it into a style tag

$("style").load("css/site.css", function() {
    alert('Load was performed.');
});

or if you don't want to have to have an empty style tag to populate you can do this:

$("head").append("<style></style>");
$("head style:last").load("<%=ResolveUrl("~/") %>_res/c/site.css", function() {
   alert('Load was performed.');
});
hunter
  • 62,308
  • 19
  • 113
  • 113
  • I'll try this. But will this cause style to be retained when copying and pasting tables? , since I am literally placing the html of the table into the clipboard, and in that case the css would only be included if it is WITH the html – MrVimes Nov 29 '10 at 19:55
  • I'm not certain, but if it works like you're saying it does then I believe that the styles should carry over. If it's strictly using the HTML then it might not – hunter Nov 29 '10 at 20:00
  • It doesn't acheive the desired effect. The copy/paste operation still leaves behind the css. But it is a useful trick to know for other things :) – MrVimes Nov 29 '10 at 20:04
  • I tried this with emails. One worked and the other, gmail, did not. Gmail stripped the style elements and contents. It even stripped ID attributes from elements. I guess a web based has to do that. – Valamas Nov 30 '15 at 05:52
0

Use plain JavaScript for this :

$('.mytable').style.cssText;

Your welcome ;]

ps. same for adding inline css:

$('.mytable').style.cssText = "border:1px solid red;";
fearis
  • 424
  • 3
  • 15
0

All solutions, that I've found, was not good enough for me. Here's my own one. When using this, please keep in mind the following:

  1. this presumes, that we have all our css styles in an external file, that has an id "#main-css-file".
  2. declaration !important has no effect: such rules are processed in the same way with ordinary ones.
  3. the algorithm is the following: a) save existing inline styles, if they exist; b) apply external css rules; c) restore saved inline styles.

Here we go:

var content = $('#selector');

// preserve existing inline styles
content.find('[style]').each( function() {
    var that = $(this);
    that.attr( 'data-inline-css', that.attr('style') );
});

// get external css rules and iterate over all of them
var extCssFile  = $('#main-css-file')[0].sheet,
    extCssRules = extCssFile.cssRules;
for ( var i = 0; i < extCssRules.length; i++ ) {
    var extCssRule     = extCssRules[i].cssText,
        extCssSelector = $.trim( extCssRule.substring( 0, extCssRule.indexOf('{') ) ),
        extCssProps    = $.trim( extCssRule.substring( extCssRule.indexOf('{') + 1, extCssRule.indexOf('}') ) );

    // we omit all rules, containing useless/unsupported pseudo classes
    // and also make sure,that we have at least 1 element, matching current selector
    if ( extCssSelector.indexOf(':after') == -1 &&
        extCssSelector.indexOf(':before') == -1 &&
        content.find( extCssSelector ).length
    ) {

        // create array of css properties
        extCssProps = extCssProps.split(';');
        // remove the last array item, if it's empty
        if ( $.trim( extCssProps[ extCssProps.length - 1 ] ) == '' ) {
            extCssProps.pop();
        }

        // iterate over each tag withing content
        content.find( extCssSelector ).each( function() {
            var that = $(this);
            // add css from file
            for ( var a = 0; a < extCssProps.length; a++ ) {
                // split rule on ":", but not on "://", that is a part of url protocol
                var style = extCssProps[a].split(/:(?!\/\/)/),
                    prop  = $.trim( style[0] ),
                    val   = $.trim( style[1] );
                // jQuery doesn't understand css "!important" - remove it
                if ( val.indexOf('important') != -1 ) {
                    val = $.trim( val.replace( '!', '' ).replace( 'important', '' ) );
                }
                that.css( prop, val );
            }
        });
    }
}

// restore inline css, that already existed before applying external css
content.find('[data-inline-css]').each( function() {
    var that = $(this),
        inlCssProps = that.attr('data-inline-css').split(';');
    if ( $.trim( inlCssProps[ inlCssProps.length - 1 ] ) == '' ) {
        inlCssProps.pop();
    }
    for ( var i = 0; i < inlCssProps.length; i++ ) {
        var style = inlCssProps[i].split(/:(?!\/\/)/),
            prop  = $.trim( style[0] ),
            val   = $.trim( style[1] );
        that.css( prop, val );
    }
    that.removeAttr('data-inline-css');
});
Arsen K.
  • 5,494
  • 7
  • 38
  • 51