eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Access global data variables within SASS/SCSS

Open ed-ponce opened this issue 4 years ago • 13 comments

I’m trying to access custom color values (i.e. {{ site.custom.text_color }}) in my style.sass that are stored under _data/site.json but dart-sass wouldn’t process it since that’s Liquid/Nunjucks syntax.

I’ve read this issue but it doesn’t entirely solve my problem since it conditions me to use vanilla CSS.

How can I reference such variables in SASS/SCSS files?

ed-ponce avatar Apr 02 '21 23:04 ed-ponce

@patrulea Do you have a public repo somewhere?

From the looks of the referenced #605 issue, you'd need to:

  1. Create a style.sass.liquid file with your LiquidJS or Nunjucks variables (from ./_data/site.json)
  2. Set your style.sass.liquid file's permalink front-matter to "/style.sass" (or whatever) and then Eleventy will interpolate the variables and output the specified Sass file at build time.
  3. Have dart-sass process the generated ./_site/style.sass file (after it's been built by Eleventy) and compile it into vanilla CSS and save it as ./_site/style.css so it can be used with your site.

pdehaan avatar Apr 02 '21 23:04 pdehaan

Actually, probably a cleaner solution is maybe using a transform in your .eleventy.js config file, and just convert the Sass => CSS there:

const sass = require("sass");

module.exports = (eleventyConfig) => {
  eleventyConfig.addTransform("sass", function (content, outputPath) {
    if (outputPath?.endsWith(".css")) {
      const res = sass.renderSync({
        data: content
      });
      return res.css.toString();
    }
    return content;
  });

  return {
    dir: {
      input: "src",
      output: "www"
    }
  };
};
---
permalink: /styles.css
---

body {
  main {
    font-family: "{{ site.theme.fontFamily }}";

    h1 {
      color: {{ site.theme.h1 }};
    }
    h2 {
      color: darken({{ site.theme.themeColor }}, 10%);
    }
    h3 { 
      color: darken({{ site.theme.themeColor }}, 20%);
    }
    h4 {
      color: darken({{ site.theme.themeColor }}, 30%);
    }
    p {
      color: rgba(purple, 0.5);
    }
  }
}

And my super classy ./src/_data/site.json looks like this:

{
  "theme": {
    "h1": "salmon",
    "themeColor": "gold",
    "fontFamily": "Comic Sans MS"
  }
}

Now when you build your Eleventy site, it will postprocess the styles using the custom 11ty transformer which only transforms our .css files, runs them through the dart-sass processor, and writes out the generated vanilla CSS code.

Generated CSS code
body main {
  font-family: "Comic Sans MS";
}
body main h1 {
  color: salmon;
}
body main h2 {
  color: #ccac00;
}
body main h3 {
  color: #998100;
}
body main h4 {
  color: #665600;
}
body main p {
  color: rgba(128, 0, 128, 0.5);
}
HOMEPAGE

pdehaan avatar Apr 03 '21 02:04 pdehaan

Doesn't look like dart-sass supports callback (only sync and callback syntax). If you want to use async transforms for reasons, this seems to work [using util.promisify]:

const { promisify } = require("util");
const sass = require("sass");

const sassRender = promisify(sass.render);

module.exports = (eleventyConfig) => {
  eleventyConfig.addTransform("sass", async function sassTransform(content, outputPath) {
    if (outputPath?.endsWith(".css")) {
      const { css } = await sassRender({
        data: content,
        outputStyle: "compressed",
        precision: 3,
      });
      return css;
    }
    return content;
  });

  return {
    dir: {
      input: "src",
      output: "www",
    },
  };
};

pdehaan avatar Apr 03 '21 02:04 pdehaan

@patrulea Do you have a public repo somewhere?

From the looks of the referenced #605 issue, you'd need to:

  1. Create a style.sass.liquid file with your LiquidJS or Nunjucks variables (from ./_data/site.json)
  2. Set your style.sass.liquid file's permalink front-matter to "/style.sass" (or whatever) and then Eleventy will interpolate the variables and output the specified Sass file at build time.
  3. Have dart-sass process the generated ./_site/style.sass file (after it's been built by Eleventy) and compile it into vanilla CSS and save it as ./_site/style.css so it can be used with your site.

I just implemented this solution and it’s working fine for me. I haven’t tried the other two solutions you wrote because I’m not too used to working with Node and JavaScript. The stylesheet even reloads after being updated when serving. The only problem is that it leaves an additional style.sass file within the output folder, but that’s a minor issue.

Thank you for helping me solve this. Maybe if SASS ever gets implemented as a template language, it could start being treated like Jekyll, where you can use Liquid tagging within SASS files; just like you can within Markdown on Eleventy.

ed-ponce avatar Apr 03 '21 20:04 ed-ponce

Also, I made my repository public so you can see my implementation or iterate on it: https://github.com/patrulea/siempre-ucr

ed-ponce avatar Apr 03 '21 20:04 ed-ponce

Not supporting .scss out of the box is a major pain point when moving from Jekyll...

DTTerastar avatar Sep 09 '21 16:09 DTTerastar

There is also eleventy-plugin-sass which might help.

pdehaan avatar Sep 09 '21 19:09 pdehaan

There is also eleventy-plugin-sass which might help.

I tried that but it has an issue in big sur and the PR to fix isn't progressing: https://github.com/Sonaryr/eleventy-plugin-sass/pull/27

DTTerastar avatar Sep 09 '21 20:09 DTTerastar

I haven't tried it yet, but there is also https://www.npmjs.com/package/eleventy-plugin-styles

pdehaan avatar Sep 09 '21 20:09 pdehaan

I haven't tried it yet, but there is also https://www.npmjs.com/package/eleventy-plugin-styles

Cool, thanks!

DTTerastar avatar Sep 10 '21 19:09 DTTerastar

FYI the repositories for eleventy-plugin-sass and eleventy-plugin-styles have both been deprecated. Not sure how hard it is but it would be cool to have data access built in, or easier to do!

bbugh avatar Sep 21 '22 02:09 bbugh

As of Eleventy v1, you can add custom template languages; see https://www.11ty.dev/docs/languages/custom/#example-add-sass-support-to-eleventy

I wasn't able to get templateEngineOverride working to try and preprocess .scss files w/ LiquidJS or Nunjucks, but I was able to get this quick example, https://github.com/pdehaan/11ty-1726, working with using CSS variables (and then a similar solution to above where you have a src/style.vars.njk file w/ permalink: style.vars.css in the front matter):

---
permalink: style.vars.css
---

:root {
  --text-color: {{ site.custom.text_color }};
}

Then my src/styles.css file looks like this:

@import url("style.vars.css");

body {
  color: var(--text-color);
}

Finally, my Super Fancy(tm) src/_data/site.json file looks like this:

{
  "custom": {
    "text_color": "salmon"
  }
}

pdehaan avatar Sep 21 '22 05:09 pdehaan

Thank you Peter!

I’ve been resorting to a similar solution since I opened the issue. Different plugins and packages have come and gone; I might try them out until there’s official support.

Eleventy 2.0, maybe?

ed-ponce avatar Sep 23 '22 03:09 ed-ponce

I don’t think this is relevant anymore.

ed-ponce avatar Sep 07 '23 16:09 ed-ponce