DEV Community

Cover image for Simple SCSS with 11ty
Adam K Dean
Adam K Dean

Posted on

Simple SCSS with 11ty

Since migrating my blog to DEV, I've been looking at rebuilding my website as a simple signpost to my various activities on the web, and with this I've been looking into static site generators, and focusing mostly on 11ty.

I've been looking through philhawksworth/eleventyone which for the most part gives a nice overview of the workings of 11ty. But one thing it didn't include was SCSS preprocessing. Instead, Phil opted for standard css preprocessing.

One thing I'm good at is searching the internet, but try as I might for almost 5 long minutes, I couldn't find a good solution out there for this. Phil created a gulp-powered SCSS preprocessor, but I didn't really want to add gulp into the mix. He wrote about how as you add in SCSS your complexity increases but I don't think this has to be the case. I carried on looking, and I found someone who was preprocessing SCSS and writing it to a file. I didn't want to generate files before I generate files either, that xzibits¹ too much recursion for my liking.

After looking at everything I'd seen so far, and deciding to do some thinking of my own, I came up with a way that you can easily add SCSS preprocessing to an 11ty project.

The Solution

As I understand it, by having a file with a .11ty.js suffix, you're able to introduce some functionality into an endpoint, the path of which you can define in the permalink field of the data() method in the class you return. You can then define the output of that endpoint by returning a string from the render() methods of that class.

Well, once you realise this, it's quite simple really. Assuming we have a directory structure like so, with the scss files within the includes directory and a JavaScript file within the css directory.

site/
site/_includes/
site/_includes/scss/
site/_includes/scss/main.scss
site/css/
site/css/style.11ty.js
site/index.md
Enter fullscreen mode Exit fullscreen mode

All we need to do is use a scss-to-css module (in this case node-sass-promise), render the scss files into css, and then for good measure, clean it before we send it out.

const path = require('path')
const sass = require('node-sass-promise')
const CleanCSS = require('clean-css')

const inputFile = path.join(__dirname, '../_includes/scss/main.scss')
const outputFile = path.join(__dirname, '../css/style.css')

const comment = `/* This is an example comment */`

module.exports = class {
  data() {
    return {
      permalink: 'css/style.css',
      eleventyExcludeFromCollections: true
    }
  }

  async render() {
    const { css } = await sass.render({ file: inputFile })
    const output = new CleanCSS({}).minify(css.toString()).styles

    return `${comment}\n\n${output}`
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, I'm notorious for adding comments to the beginning of every source file. I'm old school, and also, I feel old. But when I work with a file that doesn't have a banner comment I don't feel right. With this in mind, I've also added the ability to place a header comment in while removing all other chaff from the scss and placing the clean, processed css afterwards.

This all results in the endpoint css/style.css being generated via the render() method and outputting something like this:

/* This is an example comment */

*{margin:0;padding:0}body{padding:1rem;}h1{font-size:3rem;}
Enter fullscreen mode Exit fullscreen mode

So to summarise, you create a file site/css/style.11ty.js in which you read from an input file ../_includes/scss/main.scss, run it through some npm packages (sass, clean-css etc) and then return it as a string so that the 11ty generator can store it somewhere useful.


On the subject of banner comments, I much prefer fancier versions that a simple line of text, such as catsofinternet.org...

            _              __ _       _                       _                    
           | |            / _(_)     | |                     | |                   
   ___ __ _| |_ ___  ___ | |_ _ _ __ | |_ ___ _ __ _ __   ___| |_   ___  _ __ __ _ 
  / __/ _` | __/ __|/ _ \|  _| | '_ \| __/ _ \ '__| '_ \ / _ \ __| / _ \| '__/ _` |
 | (_| (_| | |_\__ \ (_) | | | | | | | ||  __/ |  | | | |  __/ |_ | (_) | | | (_| |
  \___\__,_|\__|___/\___/|_| |_|_| |_|\__\___|_|  |_| |_|\___|\__(_)___/|_|  \__, |
                                                                              __/ |
                                                                             |___/ 
Enter fullscreen mode Exit fullscreen mode

Or internetdogs.com...



      .-.          /                            /   
      `-'.  .-.---/---.-.  ).--..  .-.   .-.---/--- 
     /    )/   ) /  ./.-'_/      )/   )./.-'_ /     
  _.(__. '/   ( /   (__.'/      '/   ( (__.' /      
          .    `-                     `-            
         /                                          
    .-../ .-._..-.    .      .-.  .-._..  .-. .-.   
   (   / (   )(   )  / \ .-.(    (   )  )/   )   )  
    `-'-..`-'  `-/-'/ ._)`-' `---'`-'  '/   /   (   
             -._/  /                             `-'

Enter fullscreen mode Exit fullscreen mode

Or httprefs.org...


 __ __  ______  ______  ____  ____     ___  _____  _____      ___   ____    ____ 
|  |  ||      ||      ||    \|    \   /  _]|     |/ ___/     /   \ |    \  /    |
|  |  ||      ||      ||  o  )  D  ) /  [_ |   __(   \_     |     ||  D  )|   __|
|  _  ||_|  |_||_|  |_||   _/|    / |    _]|  |_  \__  |    |  O  ||    / |  |  |
|  |  |  |  |    |  |  |  |  |    \ |   [_ |   _] /  \ | __ |     ||    \ |  |_ |
|  |  |  |  |    |  |  |  |  |  .  \|     ||  |   \    ||  ||     ||  .  \|     |
|__|__|  |__|    |__|  |__|  |__|\_||_____||__|    \___||__| \___/ |__|\_||___,_|

Enter fullscreen mode Exit fullscreen mode

But I mean, that's not really important is it? If you do like banner comments like this, the patorjk taag site is super useful and has been for many years.

Check it out.


¹ xzibit joke not typo

Oldest comments (2)

Collapse
 
aldo_ea profile image
Aldo

Hi @adamkdean! Thank you very much for this post.

I'm new with 11ty and I can't find more info about this part:

"As I understand it, by having a file with a .11ty.js suffix, you're able to introduce some functionality into an endpoint, the path of which you can define in the permalink field of the data() method in the class you return. You can then define the output of that endpoint by returning a string from the render() methods of that class."

Could you tell me where I could find more info about that?
Thank you in advance!

Collapse
 
patricknelson profile image
Patrick Nelson

I was confused about this too, check out: 11ty.dev/docs/languages/javascript/

Basically: It's 11ty's way of finding a way to treat a JavaScript file the way it would a template like *.njk, *.md or whatever. Since they're JS, they just need to follow a certain structure so that they export some kind of content. In this case, CSS. 😄