CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very usefull when you're sending emails.

Overview

CssToInlineStyles class

Build Status Scrutinizer Code Quality Code Coverage SensioLabsInsight

Installation

CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.

About

PHP CssToInlineStyles is a class to convert HTML into HTML with inline styles.

Installation

The recommended installation way is through Composer.

$ composer require tijsverkoyen/css-to-inline-styles

Example

use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;

// create instance
$cssToInlineStyles = new CssToInlineStyles();

$html = file_get_contents(__DIR__ . '/examples/sumo/index.htm');
$css = file_get_contents(__DIR__ . '/examples/sumo/style.css');

// output
echo $cssToInlineStyles->convert(
    $html,
    $css
);

Known issues

  • no support for pseudo selectors
  • no support for css-escapes
  • UTF-8 charset is not always detected correctly. Make sure you set the charset to UTF-8 using the following meta-tag in the head: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />. (Note: using <meta charset="UTF-8"> does NOT work!)

Sites using this class

Comments
  • 2.0 (WIP)

    2.0 (WIP)

    The 2.0 version is a major overhaul, which is not backwards compatible.

    • From now on you can re-use the class for multiple mails.
    • A lot less complicated options, as in: no more options at all.
    • More separate classes which handle their own (tested) methods.
    • A lot more tests

    The reason why I did this was to make the class more usable.

    opened by tijsverkoyen 19
  • excludeMediaQueries regexp not works on some servers

    excludeMediaQueries regexp not works on some servers

    https://github.com/tijsverkoyen/CssToInlineStyles/blob/master/src/CssToInlineStyles.php#L436

    $css = preg_replace('/@media [^{]*{([^{}]|{[^{}]*})*}/', '', $css);
    var_dump($css); // is NULL in some servers
    

    I don't know because of what it, but i modify regexp to

    $css = preg_replace('/@media [^{]*{([^{}]|{.*})*}/', '', $css);
    

    and it works fine

    Server config

    mbstring.func_overload = 0
    mbstring.internal_encoding = utf-8
    Multibyte (japanese) regex support  = enabled
    Multibyte regex (oniguruma) version =   5.9.1 
    
    opened by Londeren 18
  • Replaced the regex-based transformation of CSS to XPath

    Replaced the regex-based transformation of CSS to XPath

    The library now uses the Symfony CssSelector component, which supports more cases than the custom logic used previously. Closes #34

    I updated the doc to mention composer as the recommended installation way, as this takes care of including the CssSelector component automatically. Btw, don't forget to update the composer.json again when bumping the version after this change :)

    opened by stof 12
  • Always have CSS styles overwrite inline styles

    Always have CSS styles overwrite inline styles

    We might have different use cases but for us it is important that already existing inline styles are always overwritten when the same property is in the CSS. Right now (looking at version 2.0) they are only overwritten, if you add !important to your CSS property.

    Let's say you have a button as a standard component that comes with a default look defined as inline styles and you want to give it a different background color as well as font-size. With this you'd have to write:

    .my-button { 
    background-color: #f00 !important;
    font-size: 16px !important;
    }
    

    So basically you need !important everywhere. I know that this is how CSS specificity works, but for us, doing our mails, it's not so useful.

    So if there are no objections, I would love to have the "isImportant" check removed.

    But maybe you have a use case for that so perhaps it should be an option instead.

    opened by mdio 11
  • Problem on load HTML UTF-8 file

    Problem on load HTML UTF-8 file

    Hello, I fixed a problem to load HTML replacing:

            // create new DOMDocument
            $document = new \DOMDocument('1.0', $this->getEncoding());
    
            // set error level
            libxml_use_internal_errors(true);
    
            // load HTML
            $document->loadHTML($this->html);
    

    With:

            // create new DOMDocument
            $document = new \DOMDocument();
            $document->encoding = 'UTF-8';
    
            // set error level
            libxml_use_internal_errors(true);
    
            // load HTML with hack
            $document->loadHTML('<?xml encoding="UTF-8">' . $this->html);
    
            // dirty fix
            foreach ($document->childNodes as $item) {
                if ($item->nodeType == XML_PI_NODE) {
                    // remove hack
                    $document->removeChild($item);
                }
            }
    
    opened by netinhoteixeira 11
  • Refactor specificity

    Refactor specificity

    Don't use a value, but compare the 3 values in a seperate class. And don't add the order to the specificity, only use it when the specificity is equal. This will prevent cases where the specificity is increased too much because many rules. This replaces #56

    This is following the spec better, so that 2,0,1 > 1,12,1 (vs 201 < 221, which is incorrect)

    /cc @stof What do you think, something like this compare also for the CssSelector component?

    opened by barryvdh 10
  • reset css rules when new css is set

    reset css rules when new css is set

    Hello,

    This PR fixes issue when reusing same instance of CssToInlineStyles class for inlining, e.g. in bulk emails option. Also it speeds up inlining css a bit for bulk emails by parsing css only once.

    Regards, Alex

    opened by mente 8
  • Not properly parsing out comments.

    Not properly parsing out comments.

    Hi, I found that this plugin wasn't properly parsing out HTML comments which may exist in some inline <style> blocks, such as this one for example:

    <style type="text/css">
    <!--
    .bwalignc {text-align: center}
    // ...more classes...
    -->
    </style>
    

    As a result, ->processCSS() will end up thinking that the first class above is <!--.bwalignc instead of .bwalignc. I'll submit a quick PR in a moment to patch this up!

    opened by patricknelson 7
  • Give workaround example for known issue: not supporting pseudo-selectors or fix it

    Give workaround example for known issue: not supporting pseudo-selectors or fix it

    Hello Tijs,

    thanks for the good work on CssToInlineStyles. You mention the known issue "no support for pseudo selectors" in README.md

    From my point of view, this is no big deal, even if styles are stripped out, because CssToInlineStyles will keep media queries in the style block. So you could give an example for the workaround in README.md just where the known issue gets mentioned:

    If you need pseudo selectors, wrap them in @media all{ }
    

    On the other hand: Why not support it? If there's no conceptional reason for not supporting it, I'd offer you to help. Let me know if you're interested.

    opened by tpraxl 7
  • Tweak tests

    Tweak tests

    Require phpunit for --dev, use the vendor bin, remove the composer.lock file. Also composer update before running tests and use travis_retry, in case it fails.

    BTW, I don't know if you have setup your Travis webhook for Git? That can be added easily and will make the tests run on every PR/commit.

    opened by barryvdh 7
  • Add support for symfony/css-selector:6.0

    Add support for symfony/css-selector:6.0

    First of all, thank you for this great library ♥

    Symfony 6.0 has been released recently, but any projects that depend on tijsverkoyen/css-to-inline-styles can't be upgraded because the dependency on symfony/css-selector is limited to ^2.7 || ^3.0 || ^4.0 || ^5.0.

    opened by victorstanciu 6
  • Еmoji icons break after processing by the convert() function

    Еmoji icons break after processing by the convert() function

    Hello. Happy New Year! I have an html string text = "<p> 😊 😂 😭 😘 😁 😉 😍 🤔 🤔 😪 😻 👩 🙏 👨 👋 👌 👉 👍 👈 ✋ 👇 👍 👆 👎 ☝ 🤘 🤳 ✌ 🖐 👐 ✊ ✍ 🎤 🎙 🎹 🎸 🎻 📻 🎶 🎵 ❤️ 🎧 📵 👪 </ p>" when using the function with such parameters: tijsverkoyen\css-to-inline-styles\src\CssToInlineStyles.php

    $text = $cssToInlineStyles->convert(
       '<div class="ck-content">' . $model->text . '</div>%FOTTER%' ,
        file_get_contents(YiiBase::getPathOfAlias('ext') . '/ckeditor5-classic/build/styles.css',
    )
    

    The output is broken the emoji that are now the letter ð (one letter replaced by a single emoji): 😊 😂 😭 😘 😁 😉 😍 🤔 🤔 😪 😻 👩 🙏 👨 👋 👌 👉 👍 👈 ✋ 👇 👍 👆 👎 ☝ 🤘 🤳 ✌ 🖐 👐 ✊ ✍ 🎤 🎙 🎹 🎸 🎻 📻 🎶 🎵 ❤️ 🎧 📵 👪

    There is a strange thing: not all emoji icons break. It seems to me that not all sets of standard emoji are embedded in this function. And because of this, an erroneous conversion occurs.

    opened by kva4991 0
  • Recent change in #234 munges utf8mb4 bytes (like 🧮)

    Recent change in #234 munges utf8mb4 bytes (like 🧮)

    This commit in #234 changing from mb_convert_encoding() to mb_encode_numericentity() introduces an issue that munges utf8mb4 bytes in a string.

    This appears to affect any 4-byte character, like 🧮, but not fewer bytes like ✈️.

    The output from $cssToInlineStyles->convert() ends up looking like ð§.

    We had to pin back to 2.2.4 in Composer to resolve an issue with outgoing mail that runs through this function.

    opened by jstanden 7
  • Undefined property: DOMDocument::$documentElement

    Undefined property: DOMDocument::$documentElement

    Hi, i have a problem with this package on shared-hosting while i haven't this problem on localhost

    gives me the error:

    { "message": "Undefined property: DOMDocument::$documentElement", "exception": "ErrorException", "file": "/home/h189025/public_html/system/vendor/tijsverkoyen/css-to-inline-styles/src/CssToInlineStyles.php", "line": 132, "trace": [ { "file": "/home/h189025/public_html/system/vendor/tijsverkoyen/css-to-inline-styles/src/CssToInlineStyles.php", "line": 132, "function": "handleError", "class": "Illuminate\Foundation\Bootstrap\HandleExceptions", "type": "->" }, { "file": "/home/h189025/public_html/system/vendor/tijsverkoyen/css-to-inline-styles/src/CssToInlineStyles.php", "line": 50, "function": "getHtmlFromDocument", "class": "TijsVerkoyen\CssToInlineStyles\CssToInlineStyles", "type": "->" }, { "file": "/home/h189025/public_html/system/vendor/laravel/framework/src/Illuminate/Mail/Markdown.php", "line": 74, "function": "convert", "class": "TijsVerkoyen\CssToInlineStyles\CssToInlineStyles", "type": "->" }, .... ] }

    Screenshot (391)

    please help...

    opened by m-shariatzadeh 0
  • DL and DT-tags workaround for HTML e-mail viewing?

    DL and DT-tags workaround for HTML e-mail viewing?

    I'm trying to use a certain CSS on my HTML markup with dl and dt tags, and I want to convert it in to inline styles for showing the dl-list correctly in a e-mail message.

    HTML:

    <dl id="summary_description_list"><dt>Aantal</dt><dd>50</dd><dt>Formaat</dt><dd>A5 (148mm x 210mm)</dd><dt>Beprinting</dt><dd>Dubbelzijdig full color</dd><dt>Papiersoort</dt><dd>Mat xerox 120 grs</dd><dt>Betaling</dt><dd>Tikkie (iDeal/Revolut)</dd><dt>Aflevering</dt><dd>Ophalen in studio</dd><dt>Indicatief gewicht</dt><dd class="mb-15">186,48 gram</dd></dl>

    CSS: dl{display:grid;grid-template-columns:max-content auto}dt{grid-column-start:1;font-weight:bold}dt:after{content:":"}dd{grid-column-start:2}/*# sourceMappingURL=lists.css.map */

    PHP:

    $cssToInlineStyles = new CssToInlineStyles();
    $summary = $cssToInlineStyles->convert(
        $summary,
        file_get_contents('https://fonts.googleapis.com/css?family=Nova+Square').' '.
        file_get_contents('https://fonts.googleapis.com/css?family=Noto+Sans:400,400i,700,700i').' '.
        file_get_contents('../css/main.css')
    );
    

    The CssToInlineStyles code works by applying the styles, but my mail client doesn't show the styles correctly. Is their a workaround possible, since the list is showing correctly in the webversion.

    opened by JeroenSteen 1
  • Disable inlinling of certail style tags

    Disable inlinling of certail style tags

    Hi!

    I'm working on a problem with certain versions of Outlook email client, and came to a solution where I need to apply styles to every email client, except Microsoft Outlook.

    There's a conditional comment that can do that:

    <!--[if !mso]><!-->
    <style>...</style>
    <!--<![endif]-->
    

    But the problem is that it's being inlined, as it's a valid non-commented <style> attribute.

    I've been thinking that having a way to disable inlining of styles from a specific style attribute could solve this. For example, the regular expression in Processor::getCssFromStyleTags() could ignore style tags that have do-not-inline attribute:

    https://github.com/tijsverkoyen/CssToInlineStyles/blob/master/src/Css/Processor.php#L38-L39

            $htmlNoComments = preg_replace('|<!--.*?-->|s', '', $html);
    +       $htmlNoComments = preg_replace('|<style(?:.*\sdo-not-inline\s?.*)?>(.*)</style>|s', '', $htmlNoComments);
            preg_match_all('|<style(?:\s.*)?>(.*)</style>|isU', $htmlNoComments, $matches);
    

    I can file a PR if you agree it's a good addition.

    Anyway, thank you for your great work! This package is helping us a lot with rendering emails :+1:

    opened by e1himself 0
Releases(2.2.5)
Owner
Tijs Verkoyen
Tijs Verkoyen
This application (class) does the sending of emails used in the phpmailer library

emailsender - PHP Notification library via email using phpMailer This library has the function of sending email using the phpmailer library. Doing thi

Lucas Alcantara Rodrigues Volpati 1 Feb 9, 2022
The Mailer component helps sending emails

Mailer Component The Mailer component helps sending emails. Getting Started $ composer require symfony/mailer use Symfony\Component\Mailer\Transport;

Symfony 1.1k Jan 7, 2023
Send beautiful HTML emails with Laravel

Beautymail for Laravel Beautymail makes it super easy to send beautiful responsive HTML emails. It's made for things like: Welcome emails Password rem

null 1.1k Jan 2, 2023
Allows you to archive old emails from one Gmail mailbox to another Gmail mailbox

Gmail Archiver L'application Gmail archiver permet de déplacer automatiquement tous les vieux mails d'une boite Gmail vers une autre boite Gmail (ou é

Arnaud Lemercier 19 Jan 27, 2022
Provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice

WP PHPMailer provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

Itineris Limited 61 Dec 6, 2022
Manage mailboxes, filter/get/delete emails in PHP (supports IMAP/POP3/NNTP)

PHP IMAP Initially released in December 2012, the PHP IMAP Mailbox is a powerful and open source library to connect to a mailbox by POP3, IMAP and NNT

Sergey 1.5k Jan 3, 2023
Queue, preview and and send emails stored in the database.

Codeigniter4 email queue Queue, preview and and send emails stored in the database. This package provides an interface for creating emails on the fly

null 3 Apr 12, 2022
Offer an online version of your Laravel emails to users.

This is was a collaborative project with Ryan Chandler. Please consider supporting him for the hard work he put into this package! Help support the ma

Sam Carré 251 Dec 25, 2022
An AngularJS / Laravel app - Keyword Based Email forwarder | read/write emails through IMAP

@MailTree Simple mail forwarder. Based on the specific email body/subject keywords forward mails to the list of predefined users. Install Imap Install

Dren Kajmakchi 4 Aug 21, 2018
Store outgoing emails in Laravel

Record and view all sent emails Watch a video walkthrough https://www.youtube.com/watch?v=Oj_OF5n4l4k&feature=youtu.be Documentation and install instr

David Carr 203 Dec 15, 2022
Mail Web is a Laravel package which catches emails locally for debugging

Mail Web is a Laravel package which catches emails locally for debugging Installation Use the package manager composer to install Mail Web. composer r

Appoly 64 Dec 24, 2022
Laravel mailer which will catch all the sent emails and show them on an application view.

Laravel Web Mailer This package contains a web mailer which will catch all the sent emails. Then, you can view it visiting the route /web-inbox. The e

Creagia 54 Dec 16, 2022
The classic email sending library for PHP

PHPMailer – A full-featured email creation and transfer class for PHP Features Probably the world's most popular code for sending email from PHP! Used

PHPMailer 19k Jan 1, 2023
Mail sending module for Mezzio and Laminas MVC with support for file attachment and template email composition

This module provides an easy and flexible way to send emails from Mezzio and Laminas MVC applications (formerly known as Zend Expressive and Zend MVC). It allows you to pre-configure emails and transports, and then send those emails at runtime.

null 82 Jan 16, 2022
Sending Email via Microsoft Exchange Web Services made Easy!

Send Mail via Exchange Web Services! Sending Email via Microsoft Exchange Web Services (EWS) made easy! Installation Install via Composer composer req

Raju Rayhan 19 Jul 19, 2022
Simple mail sending by PHPMailer and Create your local system.

Simple mail sending by PHPMailer and Create your local system. Send mail zero of cost and also send Attachment like Photo, pdf and multiple files. You should be create a login and verify two steps authentication like OTP, verifications ?? link. PHPMailer make your dreams project eassy and simple also free of cost.

SUSHIL KUMBHAR 2 Dec 8, 2021
A simplified SMPP client lib for sending or receiving smses through SMPP v3.4.

PHP-based SMPP client lib This is a simplified SMPP client lib for sending or receiving smses through SMPP v3.4. In addition to the client, this lib a

Qranio.com 2 Jul 26, 2022
PHPMailer – A full-featured email creation and transfer class for PHP

PHPMailer – A full-featured email creation and transfer class for PHP Features Probably the world's most popular code for sending email from PHP! Used

PHPMailer 19.1k Jan 2, 2023
Laravel IMAP is an easy way to integrate both the native php-imap module and an extended custom imap protocol into your Laravel app.

Laravel IMAP is an easy way to integrate both the native php-imap module and an extended custom imap protocol into your Laravel app. This enables your app to not only respond to new emails but also allows it to read and parse existing mails and much more.

null 530 Jan 6, 2023