Does it support custom property?
in css
:root{
--quote: #b1472d;
}
.quote{
background-color:var(--quote, #ececec)
}
i want to be get this text that after convert html
<div class="quote" style="background-color: #b1472d" >test</div>
Hi @kaaaaaaaaaaai,
Good question. (I was just looking at this recently and wondering if it would be preferable to SASS, etc.)
Emogrifier currently has no special processing of custom properties.
I have not tested, but the expected output from Emogrifier 5.x for your case should be
<style>
:root {
--quote: #b1472d;
}
</style>
<div class="quote" style="background-color: var(--quote, #ececec);">test</div>
So it would be up to the (email) client to apply the custom property through the inlined style attribute. I am not aware of any email clients that support this.
Thus I think this is something Emogrifier could (and perhaps should) be enhanced to support. It's not straightforward but I think do-able without any significant refactoring.
We would welcome any PRs working towards this 😉
@oliverklee @JakeQZ Thanks for the response.
Thus I think this is something Emogrifier could (and perhaps should) be enhanced to support. ithink so, too.
It's not straightforward but I think do-able without any significant refactoring.
I'll take a look at the code. and put out a PR if I can :(.
Thanks for the good OSS.
@JakeQZ I'm trying to read the code, but I can't think of any way to respond.
I'd like to know if you have any ideas on how to handle this.
I'm trying to read the code, but I can't think of any way to respond.
Yeah, I can appreciate not being familiar with the code and/or how Emogrifier works, it won't be at all clear how to tackle this.
It may help if I outline the procedure of Emogrifier:
- Sort the CSS rules in order of selector precedence, lowest first.
- For each of the sorted rules
- Identify the elements they apply to (by converting the CSS selector to an XPath expression);
- For each element
- Merge the property declarations from the CSS rule into the style attribute of the element, replacing any existing declarations for the same property, whilst respecting
!important.
- Merge the property declarations from the CSS rule into the style attribute of the element, replacing any existing declarations for the same property, whilst respecting
- Finally, remove
!importantfrom the declarations instyleattributes.
I am thinking that to solve this there are two independent changes needed - one small; one bigger two-parter:
- Support
:root; -
- Possibly cascade the
--vardeclarations through to all descendent elements at time of application; - Modify step 3 above to support
--varat the same time as removing!important- i.e. when finalizing thestyleattribute - possibly including traversing back up the tree looking for--vardeclarations (unless the cascading is done in 2i above).
- Possibly cascade the
If :root was supported, the given input should come out, with cascading (in 2i), as follows (instead of the what I posted previously above as current behaviour):
<div class="quote" style="--quote: #b1472d; background-color: var(--quote, #ececec);">test</div>
Without cascading (in 2i), we would have
<html style="--quote: #b1472d;">
<head></head>
<body>
<div class="quote" style="background-color: var(--quote, #ececec);">test</div>
</body>
</html>
The finalization 'step 3' I think already involves splitting the style attribute back into key-value pairs, and it should be clear from the above example(s) what additionally needs to be done here.
I am not sure whether traversing back up the tree looking for a --var declaration whenever var() is found is a better approach than applying the --var declaration to all descendents whenever it is found.
Anyway, step 3 is done by removeImportantAnnotationFromAllInlineStyles, so around that call in the procedure would be the place to insert a call to a new method to finalize the custom properties (i.e. assign the vars).
Regarding supporting :root, this may be very simple. We use symfony/css-selector to convert selectors to XPath expressions. This hopefully already supports :root. We only allow pseudo-classes known to be supported. If Symfony supports it, it should just require changing the regular expression PSEUDO_CLASS_MATCHER to allow it (and adding a few tests to confirm).
Hope this helps, and thanks for your continued interest. As I said, I think this would be an excellent enhancement to Emogrifier. Feel free to ask any more questions.
PS. I am assuming that --var and var() will be passed through as expected by the current code - this may of course not be the case (though I can't think of a reason why it wouldn't).
PPS. Regarding 'step 3', I think removeImportantAnnotationFromNodeInlineStyle should become a more generically-named method (like finalizeStyleAttribute) which does the splitting into key-value pairs, and re-assembling later, and in-between calls off to separate methods, one of which would be removeImportant..., and, with this proposal, a second would be to apply the vars. Though I am not sure if the order matters (or even if this is workable due to some nuance which means both steps can't be done together node-by-node but instead need to be done separately, one after the other each on the DOM tree as a whole), or whether !important can apply to a --var and if so what it means.