11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.1k stars 494 forks source link

Access global data variables within SASS/SCSS #1726

Closed patrulea closed 1 year ago

patrulea commented 3 years ago

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?

pdehaan commented 3 years ago

@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 commented 3 years ago

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 ```css 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 commented 3 years ago

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",
    },
  };
};
patrulea commented 3 years ago

@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.

patrulea commented 3 years ago

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

DTTerastar commented 3 years ago

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

pdehaan commented 3 years ago

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

DTTerastar commented 3 years ago

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

pdehaan commented 3 years ago

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

DTTerastar commented 3 years ago

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

Cool, thanks!

bbugh commented 2 years ago

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!

pdehaan commented 2 years ago

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"
  }
}
patrulea commented 2 years ago

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?

patrulea commented 1 year ago

I don’t think this is relevant anymore.