The goal is to take CSS rules from a regular CSS file and apply them to their respective targets in an HTML file, but by placing the rules in the style="" attribute (using the <style> tag would be too simple) and removing the class="" and id="" attributes.


  • Only ids #id and classes .class selectors must be supported, without more complex rules (parent selector #a #b or multiple classes .a.b, etc.)
  • Reducing rules is not required, for example the rules #a{color:red} .b{color:blue} applied to <div id="a" class="b"></div> can output <div style="color:blue;color:red;"></div> and the browser will only use the last rule (hereby red)
  • The paths to input files can be transmitted by command line arguments or hard-coded in the script/program
  • You can't call an external library, you can only include classes or functions built in the language (or from another language if needed)
  • Standard “loopholes” are forbidden
  • You program must produce the expected result but also works with other input files (to avoid hard-coded solution)
  • The output does not need to be saved to any file
  • Shortest code wins


CSS file

#h1 {color:Red;}
#bigger {font-size:1.1em;}
.code {font-family:Monospace;}
.golf {background-color:LightGreen;}

Only ids and classes are used in order to keep it simple.

HTML file

<!DOCTYPE html>
<head><title>Hello World!</title></head>
<h1 id="h1">Hello World!</h1>
    <li class="code">Code</li>
    <li id="bigger" class="golf">Golf</li>
    <li class="code golf">Code golf</li>

Expected output:

<!DOCTYPE html>
<head><title>Hello World!</title></head>
<h1 style="color:Red">Hello World!</h1>
    <li style="font-family:Monospace;">Code</li>
    <li style="font-size:1.1em;background-color:LightGreen;">Golf</li>
    <li style="font-family:Monospace;background-color:LightGreen;">Code golf</li>

Example on jsfiddle.


4 Answers 4


JavaScript - 589 (573)

It's 573 when processed by a minifier.

Not smaller then the Python version, but processes CSS using DOM objects instead of text strings. This should be able to process more complex CSS selectors also. But then the id and class attributes are not handled at the moment.

x.write('<link rel="stylesheet" href="'+c+'"/>')
var s,p,n,t,i,j,r=x.styleSheets[0].cssRules,d=x.getElementById('i').contentWindow.document
n[j].setAttribute('style',(t+p[1]).replace(': ',':'))
}}alert(new XMLSerializer().serializeToString(d))}
x.write('<iframe src="'+h+'" id="i"></iframe>')

Runs in Firefox if you put the script, the files to process and this web page in the same folder:

<script type="text/javascript">
var c='css2inline.css',
<script type="text/javascript" src="a.js"></script>

Replace c and h with CSS and HTML files, open this page and an alert shows the HTML.

Note The resulting HTML is a serialization of the DOM tree. That causes the result to be not exactly formatted as requested, but it represents the same HTML. Your call to say if you find it correct or not.


// Add CSS to current document.
x = document
x.write('<link rel="stylesheet" href="'+c+'"/>')

window.onload = function(){
    var s,p,n,t,i,j,
        r = x.styleSheets[0].cssRules,

        // Get the HTML to process.
        d = x.getElementById('i').contentWindow.document

    // Loop through CSS rules.    
    for(i = 0; i < r.length; i++){

        // Get CSS selector from rule.
        s = r[i].selectorText

        // Get text with CSS properties.
        p = r[i].cssText.match(/\{\s*(.*?)\s*\}/)

        // Get DOM nodes matching the CSS selector.
        n = d.querySelectorAll(s)

        // Add CSS properties to style of selected nodes.
        for(j = 0; j < n.length; j++){

            // Preserve current value.
            t = n[j].getAttribute('style') == null ? '' : n[j].getAttribute('style')

            // Add rule properties.         
            n[j].setAttribute('style',(t + p[1]).replace(': ',':'))

            // Remove id/class attribute from element.
            n[j].removeAttribute(s.charAt(0) == '#' ? 'id' : 'class')
    // Output serialized document.
    alert(new XMLSerializer().serializeToString(d))

// Create document with input HTML.
x.write('<iframe src="'+h+'" id="i"></iframe>')
  • \$\begingroup\$ I started thinking about a jQuery solution yesterday but I didn't find an easy way to modify the HTML page inplace. I like the idea of the </iframe>. I don't see any problem with the serialization if it's only differences in tabulation. \$\endgroup\$ Commented May 15, 2014 at 13:56
  • \$\begingroup\$ With jQuery it might be possible to reduce code size. But that can't work without the jQuery library. And I liked investigating the DOM manipulation for CSS. \$\endgroup\$
    – Kwebble
    Commented May 15, 2014 at 14:00
  • 1
    \$\begingroup\$ Oops, in fact the rules don't allow jQuery because it's not a part of the Javascript language. I started to think about a pure JS solution. \$\endgroup\$ Commented May 15, 2014 at 14:02
  • \$\begingroup\$ Buggy. If a node has an id and a class, it should get the rules of both, where they don't conflict. Where they do conflict, #id should have priority over .class regardless of the order of the rules in the CSS. \$\endgroup\$ Commented May 15, 2014 at 14:22
  • \$\begingroup\$ @Peter_Taylor: true, the script doesn't do that. But that's not how I read the requirements. And from my limited Python knowledge I don't see it handled in the Python version either. But I may very well be wrong about that. \$\endgroup\$
    – Kwebble
    Commented May 15, 2014 at 20:42

Python - 508, 501, 483

The idea is to read all the rules then apply them by using xpath functions, too bad it can't select nodes with multiple classes (I didn't find own to target class="code golf").


import sys,xml.etree.ElementTree as E
def a(e,f):e.set('style',(e.attrib.get('style')or'')+f)
for l in open(sys.argv[1]):
 s=l.replace("\n",'').split(' ');b=s[0];c=s[1][1:-1]
  for e in r.findall('.//*[@id=\''+b[1:]+'\']'):a(e,c);e.attrib.pop('id')
  for e in r.findall('.//*[@class]'):
   d=e.attrib.get('class').split(' ')
   if b[1:]in d:
    a(e,c);e.set('class',' '.join(d[1:]))
    if len(d) == 1: e.attrib.pop('class')


python script.py input.css input.html

Ungolfed code

import sys, xml.etree.ElementTree as ET
root = ET.parse(sys.argv[2])

# append rules to style="" attribute
def a(e,f):
    e.set('style',(e.attrib.get('style')or'') + f)

# CSS file
for l in open(sys.argv[1]):
    split = l.replace("\n", '').split(' ')
    selector = split[0]
    rules = split[1][1:-1]

    # #id
    if (b[0:1]) == '#':
        for e in root.findall('.//*[@id=\''+selector[1:]+'\']'):
            # remove id
    # .class
        for e in root.findall('.//*[@class]'):
            d=e.attrib.get('class').split(' ')
            if selector[1:] in d:
                e.set('class', ' '.join(d[1:]))
                # remove class
                if len(d) == 1:

  • 2
    \$\begingroup\$ You can get it down to 475 by indenting with only one space and also in your first for loop use ; to remove line breaks and also the indenting, you also had a space in a(e,c);e.set('class',' '.join(d[1:])). \$\endgroup\$ Commented May 15, 2014 at 10:23
  • 1
    \$\begingroup\$ You can also replace b[0:1] with b[:1] \$\endgroup\$ Commented May 15, 2014 at 10:32
  • \$\begingroup\$ @BritishColour : thanks, I will update my answer in the next days. \$\endgroup\$ Commented May 17, 2014 at 1:23
  • \$\begingroup\$ @BritishColour : I replaced the tabs with spaces, but I'm not sure it saves space to use one space or one tab since both are characters. How should I use ; to remove line breaks? Thanks. \$\endgroup\$ Commented May 19, 2014 at 19:33
  • \$\begingroup\$ In the first for loop instead of having each line with a \n and four spaces change it so that it is line1;line2;line3 ect \$\endgroup\$ Commented May 19, 2014 at 20:20

bash + sed 133 185 179

sed -re 's/ass="([^"]*) ([^"]*)"/ass="\1" class="\2"/g;'"$(
    sed -re 's/^#/id§/;s/^\./class§/;
        s/(.*)§(\S*) \{(.*)\}/s@\1="\2"@style="\3"@g/' $CSS
      )"';s/yle="(.*)" style="/yle="\1/g' $HTML

sed -re 's/class="([^"]*) ([^"]*)"/class="\1" class="\2"/g;
    '"$(sed -re 's/^#/id /;s/^\./class /;
        s/(\S*) (\S*) \{(.*)\}/s@\1="\2"@style="\3"@g/' $CSS
    )"';s/style="(.*)" style="/style="\1/g' $HTML

In this (specific) case, this will render:

<!DOCTYPE html>
<head><title>Hello World!</title></head>
<h1 style="color:Red;">Hello World!</h1>
    <li style="font-family:Monospace;">Code</li>
    <li style="font-size:1.1em;background-color:LightGreen;">Golf</li>
    <li style="font-family:Monospace;background-color:LightGreen;">Code golf</li>
  • \$\begingroup\$ The classes are ignored? \$\endgroup\$ Commented May 21, 2014 at 11:37
  • \$\begingroup\$ Oops, multi-class support add 52 bytes... \$\endgroup\$ Commented May 21, 2014 at 11:54

Lua - 340 335

f='(%w+)'a={}b={}for l in io.lines(arg[2])do i=l:sub(1,1)t=i=='#'and a or b
k,v=l:match(f..' {(.-)}')t[k]=v end
for l in io.lines(arg[1])do
c=''g='class="(.-)"'h='style="'l=l:gsub('id='..f,function(v)l:gsub(g,function(e)c=e:gsub(f,b)end)return h..a[v]..c..'"'end)l=l:gsub(g,function(e)return #c<1 and h..e:gsub(f,b)..'"'end)print(l)end

Usage: execute from the command line lua script.lua input.html input.css


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.