# PostCSS and Sass

> CSS preprocessing with PostCSS and Sass integration in WordPressify.

Source: https://wordpressify.co/postcss-sass

> For the complete documentation index, see [llms.txt](https://wordpressify.co/llms.txt).

# PostCSS and Sass

<Tabs>
  <TabContent title="PostCSS">
    WordPressify uses PostCSS by default. You can add, remove, or swap plugins to build the exact CSS feature set you need.

    The plugin lists are defined in `gulpfile.js`:

    **Development plugins** (`pluginsListDev`):
    - partialimport
    - postcssPresetEnv
    - postCSSMixins
    - autoprefixer

    **Production plugins** (`pluginsListProd`):
    - partialimport
    - postcssPresetEnv
    - postCSSMixins
    - autoprefixer
    - cssnano (minification)

    ## Writing CSS

    The main CSS entry point is:

    ```bash
    src/assets/css/style.css
    ```

    This file contains the WordPress template header comment and imports for your stylesheets.
  </TabContent>
  <TabContent title="Sass">
    To use Sass instead of PostCSS, install the required packages:

    ```bash
    npm install sass gulp-sass
    ```

    Rename the entry point `src/assets/css/style.css` to `style.scss`, keeping the WordPress template header comment.

    Then update `gulpfile.js`. Add the imports and create the Sass compiler:

    ```diff
    import zip from "gulp-vinyl-zip";
    import cssnano from "cssnano";
    +import dartSass from "sass";
    +import gulpSass from "gulp-sass";

    const { series, dest, src, watch } = pkg;
    +const sass = gulpSass(dartSass);
    ```

    Update the `stylesDev` task:

    ```diff
    function stylesDev() {
    -  return src("./src/assets/css/style.css")
    +  return src("./src/assets/css/style.scss")
        .pipe(plumber({ errorHandler: onError }))
        .pipe(sourcemaps.init())
    -    .pipe(postcss(pluginsListDev))
    +    .pipe(sass({ includePaths: "node_modules" }).on("error", sass.logError))
        .pipe(sourcemaps.write("."))
        .pipe(dest("./build/wordpress/wp-content/themes/" + themeName))
        .pipe(browserSync.stream({ match: "**/*.css" }));
    }
    ```

    Update the CSS watcher to monitor `.scss` files:

    ```diff
      const watcherCSS = watch(
    -    ["./src/assets/css/**/*.css", "!./**/.DS_Store"],
    +    ["./src/assets/css/**/*.scss", "!./**/.DS_Store"],
        watchOptions,
      );
    ```

    <Callout type="info">
    `gulpfile.js` is baked into the Node.js Docker image, so after these changes run `npm run build` before starting the server. See [Build Changes](/build-changes).
    </Callout>

    Update the `stylesProd` task:

    ```diff
    function stylesProd() {
    -  return src("./src/assets/css/style.css")
    +  return src("./src/assets/css/style.scss")
        .pipe(plumber({ errorHandler: onError }))
    -    .pipe(postcss(pluginsListProd))
    +    .pipe(sass({ includePaths: "node_modules" }).on("error", sass.logError))
        .pipe(dest("./dist/themes/" + themeName));
    }
    ```
  </TabContent>
</Tabs>

## Linting

CSS is linted with [Stylelint](https://stylelint.io/), configured in `.stylelintrc` in the project root. Run it with:

```bash
npm run lintcss
```

This runs Stylelint against all CSS files in `src/` inside the Node.js container.
