Last Updated: August 19, 2016
· killme2008

Inline CSS style to elements for HTML email in Java

It's from http://stackoverflow.com/questions/4521557/automatically-convert-style-sheets-to-inline-style, added a little code to process selector such as "a:hover".

import java.io.IOException;
import java.util.StringTokenizer;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.google.common.base.Strings;

 * Css inliner for email,from
 * http://stackoverflow.com/questions/4521557/automatically-convert-style-sheets-to-inline-style
 * @author dennis<xzhuang@avos.com>
 * @date 2013-1-9
public class AutomaticCssInliner {
     * Hecho por Grekz, http://grekz.wordpress.com
    public static Document inlineStyles(String html) throws IOException {
        // Document doc = Jsoup.connect("http://mypage.com/inlineme.php").get();
        Document doc = Jsoup.parse(html);
        String style = "style";
        Elements els = doc.select(style);// to get all the style elements
        for (Element e : els) {
            String styleRules = e.getAllElements().get(0).data().replaceAll("\n", "").trim(), delims =
            StringTokenizer st = new StringTokenizer(styleRules, delims);
            while (st.countTokens() > 1) {
                String selector = st.nextToken(), properties = st.nextToken();
                // Process selectors such as "a:hover"
                if (selector.indexOf(":") > 0) {
                    selector = selector.substring(0, selector.indexOf(":"));
                if (Strings.isNullOrEmpty(selector)) {
                Elements selectedElements = doc.select(selector);
                for (Element selElem : selectedElements) {
                    String oldProperties = selElem.attr(style);
                        oldProperties.length() > 0 ? concatenateProperties(oldProperties,
                            properties) : properties);
        return doc;

    private static String concatenateProperties(String oldProp, String newProp) {
        oldProp = oldProp.trim();
        if (!newProp.endsWith(";")) {
            newProp += ";";
        return newProp + oldProp; // The existing (old) properties should take precedence.

2 Responses
Add your response


Hi, sorry to comment on an old post, but when trying to inline css for emailing, I found your code and try it. unfortunatelly it fails on media queries because there is embedded {} inside the style element : ex :
.appleLinks, .appleLinksWhite { text-decoration: none !important; }

@media (max-width: 640px) { body[yahoo] .inner { width:100% !important; padding:0; }

Have you produced any new developpement or alternative ? regards

over 1 year ago ·

After hours of trying different manual java code solutions and not being satisfied with results (responsive media query handling issues mostly), I stumbled upon https://github.com/mdedetrich/java-premailer-wrapper which works great as a java solution. But you might be better off running your own "premailer" server. While there is a public api to premailer, I wanted to have my own instance running that I can hit as hard as I want:

Easy to run on ec2 with just a few clicks: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_Ruby_sinatra.html

git clone https://github.com/TrackIF/premailer-server.git
cd premailer-server
eb init  (choose latest ruby)
eb create premailer-server --sample
eb deploy
curl --data "html=<your html>" http://your.eb.url
over 1 year ago ·