Front-End npm Setup: Sass, Bootstrap 5, Font Awesome 7 and Autoprefixer

Quick Summary
- Run npm init -y, install bootstrap and @fortawesome/fontawesome-free as dependencies, and sass, postcss, postcss-cli and autoprefixer with --save-dev.
- npm scripts copy Font Awesome's webfonts, compile the SCSS with Dart Sass and run Autoprefixer, so npm run build and npm run watch do the work.
- Load Bootstrap and Font Awesome with @use: Sass deprecated @import in Dart Sass 1.80.0 and plans to remove it in Dart Sass 3.0.0.
For a front-end npm setup with Sass, Bootstrap, Font Awesome and Autoprefixer, run npm init -y, install Bootstrap and Font Awesome as dependencies, and install sass, postcss, postcss-cli and autoprefixer as devDependencies. Then add npm scripts that compile your SCSS and run Autoprefixer, so npm run build and npm run watch do the work. In September 2026 the current versions are Bootstrap 5.3.8, Font Awesome Free 7.3.1, Sass 1.105.0, PostCSS 8.5.28, postcss-cli 12.0.0 and Autoprefixer 10.6.1.
The install commands
npm init -y
npm install bootstrap @fortawesome/fontawesome-free
npm install --save-dev sass postcss postcss-cli autoprefixernpm init -ycreates apackage.jsonwith default values. Without-y, npm asks for each value first.- Bootstrap and Font Awesome go in
dependencies, because their code ends up in the CSS you ship. Since npm 5,npm installsaves todependenciesby default, so--saveis no longer needed. npm also installed@popperjs/core, Bootstrap’s peer dependency, without being asked. - The build tools go in
devDependencieswith--save-dev.sassis Dart Sass, the current Sass compiler; the oldnode-sasspackage is deprecated, and npm shows “Node Sass is no longer supported”.postcssis listed next topostcss-clibecause the CLI needs it as a peer dependency, and that’s how the postcss-cli README installs it.
The difference between –save and –save-dev explains the two groups in more detail.
npm scripts to build and watch
Add a scripts section and a browserslist line to package.json. This is the whole file after the commands above:
{
"name": "my-theme",
"version": "1.0.0",
"private": true,
"scripts": {
"copy:fonts": "node -e \"require('fs').cpSync('node_modules/@fortawesome/fontawesome-free/webfonts', 'webfonts', { recursive: true })\"",
"build:css": "sass --load-path=node_modules --quiet-deps --style=compressed --no-source-map scss/style.scss css/style.css",
"prefix:css": "postcss css/style.css --use autoprefixer --replace --no-map",
"build": "npm run copy:fonts && npm run build:css && npm run prefix:css",
"watch": "sass --load-path=node_modules --quiet-deps --watch scss/style.scss css/style.css"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^7.3.1",
"bootstrap": "^5.3.8"
},
"devDependencies": {
"autoprefixer": "^10.6.1",
"postcss": "^8.5.28",
"postcss-cli": "^12.0.0",
"sass": "^1.105.0"
},
"browserslist": [
"defaults"
]
}copy:fontscopies Font Awesome’s font files to awebfontsfolder next tocss, where its CSS looks for them. It uses Node’s ownfs.cpSync(), so it works in the Windows command prompt as well as on macOS and Linux.build:csscompilesscss/style.scsstocss/style.css.--load-path=node_moduleslets you write@use "bootstrap/scss/bootstrap"instead of a../node_modules/…path, and--quiet-depshides warnings from files found through that load path.--style=compressedminifies the output.prefix:cssruns Autoprefixer on the compiled file and overwrites it. Autoprefixer is a PostCSS plugin that adds the vendor prefixes, like-webkit-and-moz-, that your target browsers still need, using data from Can I Use, and removes prefixes they no longer need.browserslistsets those target browsers.defaultsmeans> 0.5%, last 2 versions, Firefox ESR, not dead, according to the Browserslist docs.npm run watchrecompiles the CSS each time you save an SCSS file. It skips Autoprefixer, so runnpm run buildbefore you deploy.
Tested with npm 11.16 and npm 12.1 on Windows: npm run build copied the four Font Awesome .woff2 files and wrote a 331 KB css/style.css. A user-select: none rule came out with -webkit-user-select and -moz-user-select added, and in a separate check Autoprefixer removed an old -webkit-border-radius. With npm run watch running, saving a change to the SCSS file recompiled the CSS.
The SCSS file: @use instead of @import
Put this in scss/style.scss:
// Bootstrap, with one of its variables changed
@use "bootstrap/scss/bootstrap" with (
$primary: #7952b3
);
// Font Awesome Free: the core, then the icon styles you use
@use "@fortawesome/fontawesome-free/scss/fontawesome";
@use "@fortawesome/fontawesome-free/scss/solid";
@use "@fortawesome/fontawesome-free/scss/brands";
@use "@fortawesome/fontawesome-free/scss/regular";
// Your own styles
.site-header {
display: flex;
gap: 1rem;
user-select: none;
}@useloads a file as a module. Sass deprecated@importin Dart Sass 1.80.0, released in October 2024, and plans to remove it in Dart Sass 3.0.0, “no sooner than two years after” 1.80.0. The current release is 1.105.0; Dart Sass 2.0 hasn’t come out yet. Every@importin your own files prints a deprecation warning now.- Bootstrap 5.3 still uses
@importin its own source, and its Sass documentation still shows@import. You can load it with@useanyway, andwith ( … )sets its variables: in the test,.btn-primaryrendered with the#7952b3background. Without--quiet-deps, the compile printed 20 deprecation warnings from Bootstrap’s files plus a note that 310 more were left out. Bootstrap says these warnings don’t prevent compilation or use. - Font Awesome 7’s SCSS already uses
@use. Loadfontawesome, the core, plus the styles you use:solid,regularandbrandsin the free version. Its CSS expects the fonts in../webfonts, relative to the compiled file. To keep them elsewhere, configure the path before the other lines with@use "@fortawesome/fontawesome-free/scss/variables" with ($font-path: "../fonts/fontawesome");.
An icon then takes one tag, for example <i class="fa-solid fa-house"></i>. In headless Chrome 153, the solid, regular and brands icons loaded their three font files from webfonts/.
The earlier version of this post loaded Font Awesome with paths like @use '../node_modules/@fortawesome/fontawesome-free/scss/solid.scss';. That still compiles with Font Awesome 7.3.1; the load path just makes it shorter. To convert your own @import rules, the Sass team’s migrator does it for you: npx sass-migrator module --migrate-deps scss/style.scss changed an @import "variables"; to @use "variables"; and its $brand to variables.$brand in a test. For more on splitting SCSS into files, see SCSS partials.
Problems you may run into
- “sass is not recognized” or “sass: command not found”. If the
NODE_ENVenvironment variable is set toproduction,npm installskipsdevDependencieswithout any warning. On a machine with that setting,npm installinstalled only Bootstrap, Popper and Font Awesome, andnpm run buildfailed with'sass' is not recognized as an internal or external command. Install withnpm install --include=dev, or unset the variable. - A warning about blocked install scripts. npm 12 doesn’t run install scripts you haven’t approved. With npm 12.1, the install reported that the script of
@parcel/watcher, which Sass uses for watching, was blocked;npm run buildandnpm run watchstill worked. - Icons don’t appear. The browser can’t find the font files. Check that
webfonts/sits next tocss/on the server, or that$font-pathpoints to where you put them.
In a WordPress theme, enqueue css/style.css with wp_enqueue_style() and upload the css and webfonts folders; node_modules doesn’t need to be on the server.
Related articles
- npm –save vs –save-dev: which packages go in dependencies and which in devDependencies
- SCSS partials: how to split your styles and load them with @use
- the 7-1 Sass folder structure: one way to organize the files in the scss folder
