Tailwind class bg-no-repeat and base64 background image url conflict
- Maizzle Version: 4.8.2
- Node.js Version: 18.11.0
When I use a base64 image in the url plus the bg-no-repeat class, the url is not rendered well. I think there is a conflict trying to merge everything in the style attribute.
style="background-repeat: no-repeat; background-image: url('data:image/jpeg }}">
The url is trunc afeter jpeg and }} remains.
Note: If I do not use the main layout then the class are not inlined as style (that is expected) and the url is correctly rendered .
My template (x-main is the one that is installed when I create the project):
---
image: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQY..."
---
<x-main>
<div class="bg-no-repeat" style="background-image: url('{{{ page.image }}}');">
</div>
</x-main>
Result:
<!DOCTYPE html>
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta charset="utf-8">
<meta name="x-apple-disable-message-reformatting">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no, url=no">
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings xmlns:o="urn:schemas-microsoft-com:office:office">
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<style>
td,th,div,p,a,h1,h2,h3,h4,h5,h6 {font-family: "Segoe UI", sans-serif; mso-line-height-rule: exactly;}
</style>
<![endif]-->
<style>
img {
max-width: 100%;
vertical-align: middle;
line-height: 1
}
</style>
</head>
<body style="margin: 0; width: 100%; padding: 0; -webkit-font-smoothing: antialiased; word-break: break-word">
<div role="article" aria-roledescription="email" aria-label lang="en">
<div style="background-repeat: no-repeat; background-image: url('data:image/jpeg }}">
</div>
</div>
</body>
</html>
Ugh, tough one to track down! Looks like it's coming from a dependency in our removeInlinedSelectors code, which tries to remove possibly-inlined CSS selectors.
The issue occurs in posthtml-attrs-parser, which we use to parse HTML element attributes in order to handle said removal. This library currently trips on the ; in the base64 string and produces a broken property value.
I tested with this custom Tailwind CSS utility, just in case expressions in Maizzle had anything to do (they don't):
@layer utilities {
.bg-base64-px {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkAAIAAAoAAv/lxKUAAAAASUVORK5CYII=');
}
}
Then used it in the template:
<x-main>
<div class="bg-base64-px">
test
</div>
</x-main>
This is what posthtml-attrs-parser produces for that node:
{
class: [ 'bg-base64-px' ],
style: { 'background-image': "url('data:image/png" },
compose: [Function (anonymous)]
}
For now one way to deal with it is to disable it:
// config.production.js
module.exports = {
// ...
removeUnusedCSS: {
removeInlinedSelectors: false,
},
}
Though keep in mind that will increase your HTML size, since unused CSS won't be purged anymore.
/cc @maltsev I'll try to add a failing test for this but think I'll need your help to fix it; we'll also need to backport it to v0.1.x
Opened a PR, once we get it fixed I'll work on backporting it to v0.1.2 so we can use it in Maizzle 4.x 👍
https://github.com/posthtml/posthtml-attrs-parser/pull/17
By the way, if you're using base64 in HTML emails:
https://www.caniemail.com/features/image-base64/
Opened a PR, once we get it fixed I'll work on backporting it to v0.1.2 so we can use it in Maizzle 4.x 👍
Thanks! I'll release both versions (1.x and 0.1.x) after the 2nd PR will get merged.
@sebastianblesgen sorry this took a while, published v4.8.3 now that should fix it 👍