inline-css icon indicating copy to clipboard operation
inline-css copied to clipboard

Move media quesries inside a CSS file to a <style> element

Open TELUS-Alexander opened this issue 3 years ago • 4 comments

My request is as follows:

When you have an HTML file that uses <link />, to a CSS file, and it has @media queries, have an option to move the media queries to a <style> element.

The reason for this request is that now if you have a media query inside the style.css file, it will either:

  • remain in the <link /> file, which is mostly not supported in email clients
  • be removed entirely

For example:

style.css

body {
  background-color: #FFFFFF;
}

@media all and (max-width: 600px) {
  background-color: #E5F0FF;
}

email.html

...
<head>
...
<link rel="stylesheet" href="style.css" />
...
</head>
<body>
...
</body>

After processing the file, via inline-css, with the option preserveMediaQueries: true the file would be as such:

email-inline-css.html

...
<head>
...
<style type="text/css">
@media all and (max-width: 600px) {
  background-color: #E5F0FF;
}
</head>
<body>
...
</body>

All the inline CSS rules would apply and the media queries would be moved to a <style> element.

Thank you for the great package.

TELUS-Alexander avatar Mar 10 '22 18:03 TELUS-Alexander

Any solutions?

MishaChernov avatar Dec 01 '22 22:12 MishaChernov

Because of this issue I don't use linked style files. But it would be great if I can use. A workaround might be preprocessing the file to replace style links with style content. This should be a simple task but I could not find a ready-made solution for it.

bkilinc avatar Jan 28 '23 08:01 bkilinc

This is what I did

  1. create an extracMediaQueriesCSS using the built-in packages (there are all already dependencies of this package) :
import * as getHrefContent from "href-content";
import * as getStylesheetList from "list-stylesheets";
import * as mediaQueryText from "mediaquery-text";
import { promisify } from "util";
const getHrefContentAsync = promisify(getHrefContent);

export async function extractMediaQueriesCss(html: string, options) {
  const data = getStylesheetList(html, options);
  let mediaCss = [];
  for (const href of data.hrefs) {
    const linkedStyle = await getHrefContentAsync(href, options.url);
    mediaCss.push(mediaQueryText(linkedStyle));
  }

  return mediaCss.join("\n");
}
  1. use that method to get the css then shamelessly inject it inside your html before calling inlineCSS
  const inlineCssOptions = {
      url: `file://${templateFile}`,
     preserveMediaQueries: true,
     applyLinkTags: true,
  };
  const extraCss = await extractMediaQueriesCss(templateContent, inlineCssOptions);
  // inline the linked CSS mediaquery rules inside the html itself
  templateContent = templateContent.replace("</head>", `<style type="text/css">${extraCss}</style></head>`);
  templateContent = await inlineCss(templateContent, inlineCssOptions);

r1m avatar Apr 18 '23 11:04 r1m