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 Gulp

Foundation 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;
*/
MethodEffortOutput sizeFits
CDN stylesheetNoneLargest — every componentPrototypes, a single static page
npm + full @import "foundation"One build stepStill large, but tunable via settingsMost projects
npm + component @includesOngoing disciplineSmallestPerformance-sensitive sites with a stable component set
Precompiled download from the siteNone until you need a changeFixedLegacy projects with no build pipeline
💡
Foundation's breakpoints live in Sass maps and generate media queries at build time. That is why a CSS-variable-only workflow cannot change them: there is no runtime value to override, only a compiled one.

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_modules is what lets @import "foundation" resolve without a relative path into the package folder.
  • Parse order matters: your settings partial must be imported before Foundation, or the defaults are already emitted.
  • What-Input writes data-whatinput onto <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 categoryExample classesApplied to
Transitionsslide-in-down, fade-inReveal, off-canvas, orphan components
Animationsspin-cw, wiggle, shakeAny element you add the class to
Timing helpersslow, fast, linearAppended 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?
For Foundation 6, yes — the plugins are jQuery plugins and the official initialiser expects it. There is no supported jQuery-free path in the 6.x line, which is the single biggest reason teams pick a different framework today.
Why is my compiled CSS so large?
Because @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.

Theming with Sass: settings, partials and selective imports Choosing Foundation

Last refreshed 2026-09-18.