Project setup: Sass, Motion UI and the build pipeline
Install Foundation from npm, compile Sass yourself, decide between the CDN and a custom build, and understand what Motion UI and What-Input add.
Installing from npm
# the framework itself
npm install foundation-sites
# the two optional companions
npm install motion-ui what-input
# Sass tooling: any of these works, pick one
npm install --save-dev sass # dart-sass, the modern choice
npm install --save-dev gulp sass gulp-sass # if you already run GulpFoundation ships Sass sources, not a single ready stylesheet, so something in your project has to compile them. That is the real setup decision: where the compile step lives and which files it reads.
/* src/scss/app.scss — the entry point */
@import "settings"; // your overrides FIRST
@import "foundation"; // everything, using your settings
/* Selective import: smaller output, more maintenance.
@import "foundation";
@include foundation-global-styles;
@include foundation-xy-grid-classes;
@include foundation-typography;
@include foundation-button;
@include foundation-forms;
@include foundation-menu;
@include foundation-top-bar;
@include foundation-reveal;
@include foundation-accordion;
@include foundation-tabs;
@include foundation-tooltip;
@include foundation-utility-classes;
@include foundation-flex-classes;
*/| Method | Effort | Output size | Fits |
|---|---|---|---|
| CDN stylesheet | None | Largest — every component | Prototypes, a single static page |
npm + full @import "foundation" | One build step | Still large, but tunable via settings | Most projects |
npm + component @includes | Ongoing discipline | Smallest | Performance-sensitive sites with a stable component set |
| Precompiled download from the site | None until you need a change | Fixed | Legacy projects with no build pipeline |
A minimal Dart Sass pipeline
{
"name": "my-foundation-site",
"private": true,
"scripts": {
"build:css": "sass src/scss/app.scss public/css/app.css --style=compressed --load-path=node_modules",
"watch:css": "sass --watch src/scss/app.scss public/css/app.css --load-path=node_modules",
"build:js": "esbuild src/js/app.js --bundle --minify --outfile=public/js/app.js",
"watch": "npm-run-all --parallel watch:css watch:js"
},
"dependencies": { "foundation-sites": "^6.9.0", "motion-ui": "^2.0.5", "what-input": "^5.2.12" }
}// src/js/app.js — one place that knows about every plugin you use
import 'what-input'; // records the active input method on <html>
import $ from 'jquery';
import 'foundation-sites';
$(document).foundation({
// options are merged into the defaults for the plugins you select below
reveal: { animationIn: 'fade-in', animationOut: 'fade-out' },
accordion: { slideSpeed: 250, multiExpand: false },
tabs: { autoFocus: false }
});
// Registering once at the document level is idiomatic for Foundation:
// it finds every [data-*-] element and initialises the matching plugin.--load-path=node_modulesis what lets@import "foundation"resolve without a relative path into the package folder.- Parse order matters: your
settingspartial must be imported before Foundation, or the defaults are already emitted. - What-Input writes
data-whatinputonto<html>, which Foundation's dropdowns and off-canvas use to decide whether focus behaviour should be mouse-like or keyboard-like. $(document).foundation()is a one-shot initialiser. Calling it again after injecting markup re-runs it across the document and can double-bind plugins.
Motion UI and the starter templates
/* Motion UI must be imported before you use its mixins. */
@import "motion-ui";
@include motion-ui-transitions;
@include motion-ui-animations;
/* then any component that accepts animation names can use them */
<div class="reveal" id="dialog" data-reveal data-animation-in="slide-in-down" data-animation-out="slide-out-up">
<h2>Confirm</h2>
<p>This applies to every project in the workspace.</p>
<button class="button" data-close aria-label="Close dialog">Cancel</button>
</div>
<button class="button" data-open="dialog">Open dialog</button>| Motion UI category | Example classes | Applied to |
|---|---|---|
| Transitions | slide-in-down, fade-in | Reveal, off-canvas, orphan components |
| Animations | spin-cw, wiggle, shake | Any element you add the class to |
| Timing helpers | slow, fast, linear | Appended to the transition class |
| Mixins | @include mui-animation(...) | Custom keyframes in your own Sass |
The starter templates Foundation publishes (basic, marketing, email) give you a working Gulp pipeline and a settings file, which is faster than assembling one. Take the pipeline, replace the demo markup, and keep the template's foundation-sites version pinned so the first upgrade is a deliberate step rather than a surprise.
FAQ
Do I have to use jQuery with Foundation?
Why is my compiled CSS so large?
@import "foundation" emits every component. Switch to component-level @includes and drop the ones you do not use. On a typical site this removes 40-60% of the file.Related
Theming with Sass: settings, partials and selective imports Choosing Foundation
Last refreshed 2026-09-18.