File Organization and Import Strategies
1. Partial Files and Underscore Naming Convention
| Pattern | Naming | Description | Purpose |
|---|---|---|---|
| Partial file | _filename.scss |
Underscore prefix | Not compiled standalone |
| Main file | main.scss |
No underscore | Entry point, compiled |
| @use partial | @use 'filename' |
Omit underscore and .scss | Modern import |
| @import partial | @import 'filename' |
Legacy import (deprecated) | Avoid in new code |
| Variables partial | _variables.scss |
Global variables | Shared configuration |
| Mixins partial | _mixins.scss |
Reusable mixins | Shared utilities |
Example: Partial files organization
// File structure
scss/
├── main.scss // Entry point (compiled)
├── _variables.scss // Partial (not compiled)
├── _mixins.scss // Partial
├── _functions.scss // Partial
└── _reset.scss // Partial
// _variables.scss (partial)
// This file won't be compiled to CSS on its own
$primary-color: #007bff;
$secondary-color: #6c757d;
$font-stack: 'Helvetica', Arial, sans-serif;
$spacing-unit: 8px;
// _mixins.scss (partial)
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
@mixin responsive-font($min, $max) {
font-size: clamp(#{$min}, 2.5vw, #{$max});
}
// _functions.scss (partial)
@use 'sass:math';
@function spacing($multiplier) {
@return $spacing-unit * $multiplier;
}
// main.scss (entry point - will be compiled)
// Modern approach with @use
@use 'variables' as vars;
@use 'mixins' as mx;
@use 'functions' as fn;
@use 'reset';
// Now use the imported modules
.container {
color: vars.$primary-color;
padding: fn.spacing(2); // 16px
@include mx.flex-center;
}
// Legacy approach with @import (DEPRECATED)
// @import 'variables';
// @import 'mixins';
// @import 'functions';
// @import 'reset';
// Naming conventions
scss/
├── _btn-primary.scss // Component partial
├── _btn-secondary.scss
├── _card-default.scss
├── _card-featured.scss
└── buttons.scss // Compiled: imports all btn-* partials
// buttons.scss
@use 'btn-primary';
@use 'btn-secondary';
// Partial with configuration
// _button.scss
$-default-padding: 10px 20px !default; // Private variable
$button-radius: 4px !default; // Public variable
.button {
padding: $-default-padding;
border-radius: $button-radius;
}
// Using configured partial
@use 'button' with (
$button-radius: 8px
);
// Multiple partials in subdirectories
scss/
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _variables.scss
├── components/
│ ├── _buttons.scss
│ ├── _cards.scss
│ └── _forms.scss
└── main.scss
// main.scss
@use 'base/variables';
@use 'base/reset';
@use 'base/typography';
@use 'components/buttons';
@use 'components/cards';
@use 'components/forms';
Note: Partials (files starting with
_) are not
compiled to CSS files directly. They must be imported into a main file that doesn't have an underscore.
2. Import Order and Dependency Management
| Order | Category | Files | Reason |
|---|---|---|---|
| 1st | Configuration | Variables, functions | Used by everything |
| 2nd | Utilities | Mixins, helpers | Reusable tools |
| 3rd | Base/Reset | Normalize, reset, typography | Foundation styles |
| 4th | Layout | Grid, containers | Page structure |
| 5th | Components | Buttons, cards, forms | UI elements |
| 6th | Pages | Page-specific styles | Specific overrides |
| 7th | Themes | Dark mode, variants | Theme overrides |
| 8th | Utilities | Helper classes | Highest specificity |
Example: Proper import order
// main.scss - Correct import order
// 1. Configuration (variables must come first)
@use 'config/variables' as vars;
@use 'config/functions' as fn;
// 2. Utilities (mixins use variables)
@use 'utilities/mixins' as mx;
@use 'utilities/helpers';
// 3. Vendors/Third-party (before base styles)
@use 'vendors/normalize';
@use 'vendors/bootstrap-grid';
// 4. Base styles (foundation)
@use 'base/reset';
@use 'base/typography';
@use 'base/forms';
// 5. Layout (structural elements)
@use 'layout/grid';
@use 'layout/header';
@use 'layout/footer';
@use 'layout/sidebar';
// 6. Components (UI elements)
@use 'components/buttons';
@use 'components/cards';
@use 'components/modals';
@use 'components/navigation';
@use 'components/forms';
// 7. Pages (page-specific styles)
@use 'pages/home';
@use 'pages/about';
@use 'pages/contact';
// 8. Themes (variants and modes)
@use 'themes/dark';
@use 'themes/high-contrast';
// 9. Utilities (override everything)
@use 'utilities/spacing';
@use 'utilities/text';
@use 'utilities/display';
// Dependency example - WRONG order
// @use 'components/buttons'; // Uses variables
// @use 'config/variables'; // Defined after use - ERROR!
// Dependency example - CORRECT order
@use 'config/variables';
@use 'components/buttons'; // Now variables are available
// Namespace management
@use 'config/variables' as v;
@use 'utilities/mixins' as m;
@use 'utilities/functions' as f;
.container {
color: v.$primary;
padding: f.spacing(2);
@include m.flex-center;
}
// Avoiding namespace with *
@use 'config/variables' as *;
.button {
// No prefix needed
background: $primary-color;
padding: $spacing-unit * 2;
}
// Dependency tree example
// _variables.scss (no dependencies)
$primary: blue;
// _functions.scss (depends on variables)
@use 'variables' as vars;
@function get-primary() {
@return vars.$primary;
}
// _mixins.scss (depends on functions and variables)
@use 'variables' as vars;
@use 'functions' as fn;
@mixin primary-button {
background: fn.get-primary();
padding: vars.$spacing-unit;
}
// _buttons.scss (depends on mixins)
@use 'mixins' as mx;
.button {
@include mx.primary-button;
}
// Conditional imports based on environment
$environment: 'production' !default;
@if $environment == 'development' {
@use 'dev/debug';
@use 'dev/grid-overlay';
} @else if $environment == 'production' {
@use 'prod/optimized';
}
// Import with configuration
@use 'config/variables' with (
$primary-color: #ff0000,
$font-size: 18px
);
// Forward for re-exporting (create API)
// _index.scss in utilities/
@forward 'mixins';
@forward 'functions';
@forward 'helpers';
// main.scss
@use 'utilities'; // Gets all forwarded items
3. File Structure Patterns (7-1 Architecture)
| Folder | Purpose | Example Files | Description |
|---|---|---|---|
| abstracts/ | Variables, mixins, functions | _variables.scss, _mixins.scss | No CSS output |
| base/ | Resets, typography, base | _reset.scss, _typography.scss | Foundation styles |
| components/ | UI components | _button.scss, _card.scss | Reusable components |
| layout/ | Page structure | _header.scss, _grid.scss | Major sections |
| pages/ | Page-specific styles | _home.scss, _about.scss | Per-page overrides |
| themes/ | Theme variations | _dark.scss, _admin.scss | Theme switches |
| vendors/ | Third-party CSS | _normalize.scss, _bootstrap.scss | External libraries |
Example: 7-1 Architecture pattern
// Complete 7-1 folder structure
scss/
├── abstracts/
│ ├── _variables.scss // Global variables
│ ├── _functions.scss // Sass functions
│ ├── _mixins.scss // Sass mixins
│ └── _placeholders.scss // Sass placeholders
├── base/
│ ├── _reset.scss // Reset/normalize
│ ├── _typography.scss // Typography rules
│ ├── _animations.scss // Keyframes
│ └── _utilities.scss // Utility classes
├── components/
│ ├── _buttons.scss // Button styles
│ ├── _cards.scss // Card component
│ ├── _carousel.scss // Carousel
│ ├── _dropdown.scss // Dropdown
│ ├── _forms.scss // Form elements
│ ├── _modal.scss // Modal dialog
│ ├── _navigation.scss // Navigation
│ └── _table.scss // Tables
├── layout/
│ ├── _grid.scss // Grid system
│ ├── _header.scss // Header
│ ├── _footer.scss // Footer
│ ├── _sidebar.scss // Sidebar
│ └── _containers.scss // Containers
├── pages/
│ ├── _home.scss // Home page
│ ├── _about.scss // About page
│ ├── _contact.scss // Contact page
│ └── _dashboard.scss // Dashboard
├── themes/
│ ├── _dark.scss // Dark theme
│ ├── _light.scss // Light theme
│ └── _admin.scss // Admin theme
├── vendors/
│ ├── _normalize.scss // Normalize.css
│ └── _bootstrap.scss // Bootstrap subset
└── main.scss // Main entry file
// main.scss - The "1" file in 7-1
@charset 'utf-8';
// 1. Abstracts
@use 'abstracts/variables' as vars;
@use 'abstracts/functions' as fn;
@use 'abstracts/mixins' as mx;
@use 'abstracts/placeholders';
// 2. Vendors
@use 'vendors/normalize';
// 3. Base
@use 'base/reset';
@use 'base/typography';
@use 'base/animations';
@use 'base/utilities';
// 4. Layout
@use 'layout/grid';
@use 'layout/header';
@use 'layout/footer';
@use 'layout/sidebar';
@use 'layout/containers';
// 5. Components
@use 'components/buttons';
@use 'components/cards';
@use 'components/carousel';
@use 'components/dropdown';
@use 'components/forms';
@use 'components/modal';
@use 'components/navigation';
@use 'components/table';
// 6. Pages
@use 'pages/home';
@use 'pages/about';
@use 'pages/contact';
@use 'pages/dashboard';
// 7. Themes
@use 'themes/dark';
@use 'themes/light';
// Alternative: Atomic Design structure
scss/
├── 00-settings/
│ └── _variables.scss
├── 01-tools/
│ ├── _functions.scss
│ └── _mixins.scss
├── 02-generic/
│ └── _normalize.scss
├── 03-elements/
│ ├── _headings.scss
│ └── _links.scss
├── 04-objects/
│ ├── _container.scss
│ └── _grid.scss
├── 05-components/
│ ├── _button.scss
│ └── _card.scss
├── 06-utilities/
│ └── _spacing.scss
└── main.scss
// Alternative: Component-based structure (React/Vue)
src/
├── components/
│ ├── Button/
│ │ ├── Button.tsx
│ │ ├── Button.scss
│ │ └── index.ts
│ ├── Card/
│ │ ├── Card.tsx
│ │ ├── Card.scss
│ │ └── index.ts
│ └── ...
├── styles/
│ ├── abstracts/
│ ├── base/
│ └── global.scss
└── App.scss
// Alternative: Feature-based structure
scss/
├── core/ // Shared across features
│ ├── _variables.scss
│ ├── _mixins.scss
│ └── _base.scss
├── features/
│ ├── auth/
│ │ ├── _login.scss
│ │ └── _register.scss
│ ├── dashboard/
│ │ ├── _widgets.scss
│ │ └── _charts.scss
│ └── products/
│ ├── _list.scss
│ └── _detail.scss
└── main.scss
// Minimal structure (small projects)
scss/
├── _variables.scss
├── _mixins.scss
├── _base.scss
├── _layout.scss
├── _components.scss
└── main.scss
4. Index Files and Barrel Exports
| Pattern | Syntax | Purpose | Benefit |
|---|---|---|---|
| Index file | _index.scss |
Folder entry point | Clean imports |
| @forward | @forward 'file' |
Re-export module | Create public API |
| @use 'folder' | Import index | Auto-loads _index.scss | Shorter paths |
| Prefix stripping | @forward ... hide $-private |
Hide private members | Encapsulation |
| Namespace | @forward ... as name-* |
Add prefix | Avoid conflicts |
Example: Index files and barrel patterns
// Folder structure with index files
components/
├── _index.scss // Barrel export
├── _button.scss
├── _card.scss
└── _modal.scss
// components/_index.scss
// Forward all components from this folder
@forward 'button';
@forward 'card';
@forward 'modal';
// main.scss
// Instead of importing each component:
// @use 'components/button';
// @use 'components/card';
// @use 'components/modal';
// Just import the index:
@use 'components';
// Advanced: Selective forwarding
// components/_index.scss
@forward 'button';
@forward 'card';
// Don't forward modal (keep it private to components)
// Advanced: Forward with prefix
// components/_index.scss
@forward 'button' as btn-*;
@forward 'card' as card-*;
// Usage
@use 'components' as c;
.element {
@include c.btn-primary;
@include c.card-layout;
}
// Advanced: Forward with hiding
// abstracts/_variables.scss
$primary: blue;
$-internal-spacing: 8px; // Private (starts with -)
// abstracts/_index.scss
@forward 'variables' hide $-internal-spacing;
// main.scss
@use 'abstracts' as abs;
.button {
color: abs.$primary; // ✓ Works
// padding: abs.$-internal-spacing; // ✗ Error: private
}
// Nested index files
scss/
├── base/
│ ├── _index.scss
│ ├── _reset.scss
│ └── _typography.scss
├── components/
│ ├── _index.scss
│ ├── buttons/
│ │ ├── _index.scss
│ │ ├── _primary.scss
│ │ └── _secondary.scss
│ └── cards/
│ ├── _index.scss
│ ├── _default.scss
│ └── _featured.scss
└── main.scss
// components/buttons/_index.scss
@forward 'primary';
@forward 'secondary';
// components/cards/_index.scss
@forward 'default';
@forward 'featured';
// components/_index.scss
@forward 'buttons';
@forward 'cards';
// main.scss
@use 'components'; // Gets everything!
// Practical: Theme API with index
themes/
├── _index.scss
├── _dark.scss
├── _light.scss
└── _high-contrast.scss
// themes/_index.scss
@forward 'dark' as dark-*;
@forward 'light' as light-*;
@forward 'high-contrast' as hc-*;
// Or selective theme forwarding
$active-theme: 'dark' !default;
@if $active-theme == 'dark' {
@forward 'dark';
} @else if $active-theme == 'light' {
@forward 'light';
} @else {
@forward 'high-contrast';
}
// Practical: Utilities barrel
utilities/
├── _index.scss
├── _spacing.scss
├── _text.scss
├── _colors.scss
└── _display.scss
// utilities/_index.scss
@forward 'spacing';
@forward 'text';
@forward 'colors';
@forward 'display';
// Configuration through index
// config/_index.scss
@forward 'variables' with (
$primary: #007bff !default,
$spacing: 8px !default
);
@forward 'functions';
@forward 'mixins';
// main.scss
@use 'config' with (
$primary: #ff0000 // Override default
);
// Multi-level barrel
scss/
├── core/
│ ├── _index.scss
│ ├── abstracts/
│ │ ├── _index.scss
│ │ ├── _variables.scss
│ │ └── _mixins.scss
│ └── base/
│ ├── _index.scss
│ └── _reset.scss
└── main.scss
// core/abstracts/_index.scss
@forward 'variables';
@forward 'mixins';
// core/base/_index.scss
@forward 'reset';
// core/_index.scss
@forward 'abstracts';
@forward 'base';
// main.scss
@use 'core'; // Everything in one import!
5. Dynamic Imports and Conditional Loading
| Pattern | Use Case | Example | Benefit |
|---|---|---|---|
| @if import | Environment-based | Dev vs production | Conditional loading |
| Feature flags | Toggle features | A/B testing | Flexible builds |
| Theme selection | Multi-theme apps | Dark/light modes | Single build |
| Loop imports | Similar files | Icon sets, colors | DRY imports |
Example: Conditional and dynamic imports
// Environment-based imports
$env: 'production' !default;
@if $env == 'development' {
@use 'dev/debug-grid';
@use 'dev/component-outline';
@use 'dev/performance-overlay';
} @else if $env == 'production' {
@use 'prod/optimized-styles';
}
// Feature flags
$features: (
animations: true,
dark-mode: true,
experimental-grid: false
);
@use 'sass:map';
@if map.get($features, animations) {
@use 'animations/transitions';
@use 'animations/keyframes';
}
@if map.get($features, dark-mode) {
@use 'themes/dark';
}
@if map.get($features, experimental-grid) {
@use 'experimental/subgrid';
}
// Dynamic theme loading
$active-theme: 'dark' !default;
// Only load the active theme
@if $active-theme == 'dark' {
@use 'themes/dark';
} @else if $active-theme == 'light' {
@use 'themes/light';
} @else if $active-theme == 'high-contrast' {
@use 'themes/high-contrast';
} @else {
@use 'themes/default';
}
// Browser-specific imports
$target-browser: 'modern' !default;
@if $target-browser == 'legacy' {
@use 'vendors/normalize';
@use 'polyfills/flexbox';
@use 'polyfills/grid';
} @else {
@use 'modern/reset';
}
// Responsive strategy selection
$responsive-strategy: 'mobile-first' !default;
@if $responsive-strategy == 'mobile-first' {
@use 'responsive/mobile-first';
} @else if $responsive-strategy == 'desktop-first' {
@use 'responsive/desktop-first';
} @else {
@use 'responsive/adaptive';
}
// Import based on configuration
$enable-rtl: false !default;
$enable-print: true !default;
@if $enable-rtl {
@use 'i18n/rtl';
}
@if $enable-print {
@use 'print/styles';
}
// Loop-based imports (components)
$component-list: (
'button',
'card',
'modal',
'dropdown',
'table'
);
@each $component in $component-list {
@use 'components/#{$component}';
}
// Conditional utility imports
$utilities: (
spacing: true,
text: true,
colors: false,
display: true
);
@each $util, $enabled in $utilities {
@if $enabled {
@use 'utilities/#{$util}';
}
}
// Breakpoint-based imports
$breakpoints: (
sm: 576px,
md: 768px,
lg: 992px
);
$active-breakpoints: (sm, md, lg);
@each $bp in $active-breakpoints {
@use 'responsive/#{$bp}';
}
// Platform-specific imports
$platform: 'web' !default; // 'web', 'mobile', 'desktop'
@if $platform == 'mobile' {
@use 'platforms/mobile/touch-optimized';
@use 'platforms/mobile/gestures';
} @else if $platform == 'desktop' {
@use 'platforms/desktop/hover-states';
@use 'platforms/desktop/keyboard-nav';
} @else {
@use 'platforms/web/standard';
}
// Conditional vendor imports
$include-vendors: (
normalize: true,
bootstrap-grid: false,
animate-css: true
);
@if map.get($include-vendors, normalize) {
@use 'vendors/normalize';
}
@if map.get($include-vendors, bootstrap-grid) {
@use 'vendors/bootstrap-grid';
}
@if map.get($include-vendors, animate-css) {
@use 'vendors/animate';
}
// Build configuration
$build-config: (
minify: true,
sourcemaps: true,
rtl: false,
themes: (dark, light),
components: (button, card, modal)
);
// Load themes
@each $theme in map.get($build-config, themes) {
@use 'themes/#{$theme}';
}
// Load components
@each $component in map.get($build-config, components) {
@use 'components/#{$component}';
}
6. Glob Patterns and Bulk Imports
| Tool | Pattern | Example | Limitation |
|---|---|---|---|
| sass-loader | Webpack glob | @import '**/*.scss' |
Build tool required |
| node-sass | includePaths | Config option | Node.js only |
| Dart Sass | No native glob | Manual imports | Must use index files |
| gulp-sass | Task runner glob | src/**/*.scss |
External tool |
Example: Bulk import strategies
// Note: Sass doesn't support native glob imports
// Must use build tools or index files
// Webpack sass-loader with glob (NOT standard Sass)
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}]
}
};
// Then in SCSS (with plugins):
// @import 'components/**/*.scss'; // Not standard!
// STANDARD approach: Use index files
// components/_index.scss
@forward 'button';
@forward 'card';
@forward 'modal';
@forward 'dropdown';
// ... etc
// Or generate index programmatically (build script)
// generate-index.js
const fs = require('fs');
const path = require('path');
const componentsDir = './scss/components';
const files = fs.readdirSync(componentsDir)
.filter(f => f.endsWith('.scss') && !f.startsWith('_index'))
.map(f => f.replace('.scss', ''));
const indexContent = files
.map(f => `@forward '${f}';`)
.join('\n');
fs.writeFileSync(
path.join(componentsDir, '_index.scss'),
indexContent
);
// Gulp task for automatic index generation
// gulpfile.js
const gulp = require('gulp');
const concat = require('gulp-concat');
gulp.task('generate-imports', () => {
return gulp.src('scss/components/_*.scss')
.pipe(/* generate @forward statements */)
.pipe(concat('_index.scss'))
.pipe(gulp.dest('scss/components/'));
});
// Manual bulk import pattern (repetitive but clear)
// components/_index.scss
@forward 'button';
@forward 'button-group';
@forward 'button-toolbar';
@forward 'card';
@forward 'card-header';
@forward 'card-body';
@forward 'card-footer';
@forward 'modal';
@forward 'modal-dialog';
@forward 'dropdown';
@forward 'dropdown-menu';
@forward 'tooltip';
@forward 'popover';
// Alternative: Programmatic import helper
// _import-helper.scss
@use 'sass:meta';
@use 'sass:list';
@mixin import-all($folder, $files...) {
@each $file in $files {
// This doesn't actually work in Sass
// Just showing the concept
// @use '#{$folder}/#{$file}';
}
}
// Vite glob imports (JavaScript side)
// main.ts
const modules = import.meta.glob('./styles/**/*.scss');
// Parcel glob (automatic)
// Just import the folder
@use 'components'; // Parcel handles the rest
// Best practice: Organized manual imports
// _all.scss (common pattern)
// Base
@forward 'base/reset';
@forward 'base/typography';
@forward 'base/forms';
// Layout
@forward 'layout/grid';
@forward 'layout/container';
@forward 'layout/header';
@forward 'layout/footer';
// Components (alphabetical for easy maintenance)
@forward 'components/alert';
@forward 'components/badge';
@forward 'components/breadcrumb';
@forward 'components/button';
@forward 'components/card';
@forward 'components/carousel';
@forward 'components/dropdown';
@forward 'components/modal';
@forward 'components/navbar';
@forward 'components/pagination';
@forward 'components/progress';
@forward 'components/spinner';
@forward 'components/table';
@forward 'components/tabs';
@forward 'components/tooltip';
// Node script to generate imports
// scripts/generate-sass-index.mjs
import { readdirSync, writeFileSync } from 'fs';
import { join, basename } from 'path';
function generateIndex(dir) {
const files = readdirSync(dir)
.filter(f => f.endsWith('.scss') && f !== '_index.scss')
.map(f => basename(f, '.scss'))
.filter(f => !f.startsWith('_index'));
const imports = files
.map(f => `@forward '${f}';`)
.join('\n');
writeFileSync(
join(dir, '_index.scss'),
`// Auto-generated - do not edit\n${imports}\n`
);
}
generateIndex('./scss/components');
generateIndex('./scss/utilities');
// Package.json script
{
"scripts": {
"sass:index": "node scripts/generate-sass-index.mjs",
"sass:build": "npm run sass:index && sass src/main.scss dist/styles.css"
}
}
File Organization Summary
- Partials: Use
_filename.scssfor files that shouldn't compile standalone - Import order: Config → Utils → Base → Layout → Components → Pages → Themes → Utilities
- 7-1 Pattern: 7 folders + 1 main file for large projects
- Index files: Use
_index.scsswith@forwardfor barrel exports - Conditional: Use
@iffor environment/feature-based imports - No glob: Sass has no native glob; use index files or build scripts
- Modern approach:
@useand@forwardover deprecated@import
Warning:
@import is deprecated. Use
@use for importing and @forward for re-exporting. Migration is essential for Dart Sass
2.0.