sass-best-practices — Claude Code skill: Sass guidelines
A skill that hands your agent a rulebook for indented-syntax Sass: file layout, variables, mixins, BEM. Useful when the project stylesheets are .sass, not SCSS.
npx skills add Mindrally/skills --skill sass-best-practices -a claude-codeWhat sass-best-practices does
The skill tells the agent how to write Sass in the indented syntax. No curly braces, no semicolons, nesting defined by indentation, .sass extension. Those rules land in the agent's context, so generated styles match the file style instead of drifting into SCSS.
What's inside: a sass/ folder layout split into abstracts, base, components, layout, pages, themes and vendors, plus a main.sass manifest built on @use. Variables cover colors, typography, a spacing scale, breakpoints and z-index. Mixins handle responsive breakpoints, flexbox helpers, text truncation and button variants. Naming follows BEM, with modifiers written as &--. A nesting section asks you to keep selectors shallow rather than five levels deep.
It fits projects already on indented Sass. On an SCSS codebase the indentation and brace rules will just confuse the agent, so check which syntax your repository actually uses before installing.
What it helps with
- write styles in indented Sass without braces or semicolons
- lay out a
sass/tree by layer and wire a@usemanifest - define variables for colors, spacing and breakpoints
- build mixins for responsive breakpoints and flexbox
- keep selector nesting from growing too deep
Example prompts for the agent
- add a product card to
components/_cards.sassfollowing the skill rules - rewrite this block in indented Sass with a BEM modifier
- create a mixin for the
mdbreakpoint and apply it to the grid
How to install sass-best-practices
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill sass-best-practices -a claude-code2Manually: put the files in place
~/.claude/skills/sass-best-practices/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/sass-best-practices/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill sass-best-practices -a codex2Manually: put the files in place
.agents/skills/sass-best-practices/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill sass-best-practices -a cursor2Manually: put the files in place
.cursor/skills/sass-best-practices/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Mindrally/skills sass-best-practices2Manually: put the files in place
.github/skills/sass-best-practices/SKILL.md1Skills CLI (Vercel)
npx skills add Mindrally/skills --skill sass-best-practices -a gemini-cli2Platform CLI
gemini skills install https://github.com/Mindrally/skills --path sass-best-practicesManually: put the files in place
.devin/skills/sass-best-practices/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Mindrally/skills --skill sass-best-practices -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about sass-best-practices
How do I install sass-best-practices in Claude?
Run npx skills add Mindrally/skills --skill sass-best-practices -a claude-code. The skill file lands at ~/.claude/skills/sass-best-practices/SKILL.md.
What does sass-best-practices do?
It gives the agent coding rules for indented-syntax Sass: project structure, variables, mixins, BEM naming and a limit on nesting depth.
How is Sass different from SCSS here?
The skill targets the indented syntax: no {}, no ;, nesting by indentation, .sass extension. Its rules do not apply to SCSS.
Source text
SKILL.md · Apache-2.0
---
name: sass-best-practices
description: Sass (indented syntax) best practices and coding guidelines for clean, maintainable stylesheets
metadata:
maintainer: Mindrally
source: https://github.com/Mindrally/skills
---
# Sass Best Practices
You are an expert in Sass (the indented syntax), CSS architecture, and maintainable stylesheet development.
## Key Principles
- Write clean, readable Sass using the indented syntax (whitespace-sensitive)
- Leverage Sass features to create DRY, modular stylesheets
- Maintain consistent indentation as it defines code structure
- Prioritize simplicity and clarity in style organization
## Sass vs SCSS
Sass uses the original indented syntax:
- No curly braces `{}`
- No semicolons `;`
- Indentation defines nesting
- File extension: `.sass`
```sass
// Sass (indented syntax)
.button
display: inline-flex
padding: 8px 16px
background: #3498db
&:hover
background: darken(#3498db, 10%)
```
```scss
// SCSS syntax (for comparison)
.button {
display: inline-flex;
padding: 8px 16px;
background: #3498db;
&:hover {
background: darken(#3498db, 10%);
}
}
```
## File Organization
### Project Structure
```
sass/
├── abstracts/
│ ├── _variables.sass
│ ├── _functions.sass
│ ├── _mixins.sass
│ └── _placeholders.sass
├── base/
│ ├── _reset.sass
│ ├── _typography.sass
│ └── _base.sass
├── components/
│ ├── _buttons.sass
│ ├── _cards.sass
│ └── _forms.sass
├── layout/
│ ├── _header.sass
│ ├── _footer.sass
│ └── _grid.sass
├── pages/
│ └── _home.sass
├── themes/
│ └── _default.sass
├── vendors/
│ └── _normalize.sass
└── main.sass
```
### Main Manifest
```sass
// main.sass
@use 'abstracts/variables'
@use 'abstracts/functions'
@use 'abstracts/mixins'
@use 'abstracts/placeholders'
@use 'vendors/normalize'
@use 'base/reset'
@use 'base/typography'
@use 'base/base'
@use 'layout/grid'
@use 'layout/header'
@use 'layout/footer'
@use 'components/buttons'
@use 'components/cards'
@use 'components/forms'
@use 'pages/home'
@use 'themes/default'
```
## Variables
### Naming and Organization
```sass
// _variables.sass
// Colors
$color-primary: #3498db
$color-primary-light: lighten($color-primary, 15%)
$color-primary-dark: darken($color-primary, 15%)
$color-secondary: #2ecc71
$color-text: #333333
$color-text-muted: #666666
$color-background: #ffffff
$color-border: #e0e0e0
$color-error: #e74c3c
$color-success: #27ae60
$color-warning: #f39c12
// Typography
$font-family-base: 'Helvetica Neue', Arial, sans-serif
$font-family-heading: 'Georgia', serif
$font-size-base: 1rem
$font-size-small: 0.875rem
$font-size-large: 1.25rem
$font-weight-normal: 400
$font-weight-bold: 700
$line-height-base: 1.5
// Spacing Scale
$spacing-unit: 8px
$spacing-xs: $spacing-unit * 0.5
$spacing-sm: $spacing-unit
$spacing-md: $spacing-unit * 2
$spacing-lg: $spacing-unit * 3
$spacing-xl: $spacing-unit * 4
$spacing-xxl: $spacing-unit * 6
// Breakpoints
$breakpoint-sm: 576px
$breakpoint-md: 768px
$breakpoint-lg: 992px
$breakpoint-xl: 1200px
// Z-index Scale
$z-index-dropdown: 1000
$z-index-sticky: 1020
$z-index-fixed: 1030
$z-index-modal: 1050
$z-index-tooltip: 1070
// Transitions
$transition-base: 0.3s ease
$transition-fast: 0.15s ease
$transition-slow: 0.5s ease
// Border Radius
$border-radius-sm: 2px
$border-radius-md: 4px
$border-radius-lg: 8px
$border-radius-pill: 50px
// Shadows
$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05)
$shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1)
$shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1)
```
### Using Maps
```sass
// Define maps for grouped values
$colors: ("primary": #3498db, "secondary": #2ecc71, "danger": #e74c3c, "warning": #f39c12, "success": #27ae60)
$breakpoints: ("sm": 576px, "md": 768px, "lg": 992px, "xl": 1200px)
// Access values
.element
color: map-get($colors, "primary")
```
## Mixins
### Responsive Design
```sass
// _mixins.sass
=respond-to($breakpoint)
@if map-has-key($breakpoints, $breakpoint)
@media (min-width: map-get($breakpoints, $breakpoint))
@content
@else
@warn "Unknown breakpoint: #{$breakpoint}"
// Usage
.element
width: 100%
+respond-to("md")
width: 50%
+respond-to("lg")
width: 33.333%
```
### Flexbox Utilities
```sass
=flex-center
display: flex
align-items: center
justify-content: center
=flex-between
display: flex
align-items: center
justify-content: space-between
=flex-column
display: flex
flex-direction: column
// Usage
.container
+flex-center
min-height: 100vh
```
### Typography
```sass
=font-size($size, $line-height: null)
font-size: $size
@if $line-height
line-height: $line-height
=truncate($lines: 1)
@if $lines == 1
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
@else
display: -webkit-box
-webkit-line-clamp: $lines
-webkit-box-orient: vertical
overflow: hidden
// Usage
.title
+font-size(2rem, 1.2)
.description
+truncate(3)
```
### Accessibility
```sass
=visually-hidden
position: absolute
width: 1px
height: 1px
padding: 0
margin: -1px
overflow: hidden
clip: rect(0, 0, 0, 0)
white-space: nowrap
border: 0
=focus-visible
&:focus-visible
outline: 2px solid $color-primary
outline-offset: 2px
// Usage
.sr-only
+visually-hidden
.interactive
+focus-visible
```
### Button Styles
```sass
=button-base
display: inline-flex
align-items: center
justify-content: center
padding: $spacing-sm $spacing-md
border: none
border-radius: $border-radius-md
font-family: inherit
font-size: $font-size-base
font-weight: $font-weight-bold
text-decoration: none
cursor: pointer
transition: all $transition-base
&:disabled
opacity: 0.5
cursor: not-allowed
=button-variant($bg-color, $text-color: white)
+button-base
background: $bg-color
color: $text-color
&:hover:not(:disabled)
background: darken($bg-color, 10%)
&:active:not(:disabled)
background: darken($bg-color, 15%)
// Usage
.btn-primary
+button-variant($color-primary)
.btn-secondary
+button-variant($color-secondary)
.btn-danger
+button-variant($color-error)
```
## BEM Naming Convention
```sass
// Block
.card
background: $color-background
border-radius: $border-radius-md
box-shadow: $shadow-md
// Element
&__header
padding: $spacing-md
border-bottom: 1px solid $color-border
&__title
margin: 0
font-size: $font-size-large
font-weight: $font-weight-bold
&__body
padding: $spacing-md
&__footer
padding: $spacing-md
border-top: 1px solid $color-border
// Modifier
&--featured
border: 2px solid $color-primary
&--compact
.card__header,
.card__body,
.card__footer
padding: $spacing-sm
```
## Nesting Guidelines
### Keep Nesting Shallow
```sass
// BAD: Too deep
.nav
.nav-list
.nav-item
.nav-link
.nav-icon
// 5 levels - avoid this
// GOOD: Flat BEM structure
.nav
display: flex
.nav__list
display: flex
list-style: none
margin: 0
padding: 0
.nav__item
margin: 0 $spacing-sm
.nav__link
color: $color-text
text-decoration: none
&:hover,
&:focus
color: $color-primary
&--active
color: $color-primary
font-weight: $font-weight-bold
```
### Acceptable Nesting
```sass
.component
// Pseudo-elements
&::before,
&::after
content: ''
// States
&:hover,
&:focus,
&:active
// State styles
// Modifiers
&--variant
// Modifier styles
// Media queries
+respond-to("md")
// Responsive styles
```
## Functions
```sass
// _functions.sass
// Color functions
@function tint($color, $percentage)
@return mix(white, $color, $percentage)
@function shade($color, $percentage)
@return mix(black, $color, $percentage)
// Unit conversion
@function px-to-rem($px, $base: 16)
@return ($px / $base) * 1rem
@function rem-to-px($rem, $base: 16)
@return ($rem / 1rem) * $base * 1px
// Spacing helper
@function spacing($multiplier)
@return $spacing-unit * $multiplier
// Usage
.element
background: tint($color-primary, 20%)
border-color: shade($color-primary, 10%)
font-size: px-to-rem(18)
padding: spacing(3)
```
## Placeholders and Extend
```sass
// Define placeholders
%clearfix
&::after
content: ''
display: table
clear: both
%list-reset
list-style: none
margin: 0
padding: 0
%button-reset
appearance: none
background: none
border: none
padding: 0
font: inherit
cursor: pointer
// Usage
.container
@extend %clearfix
.nav-list
@extend %list-reset
.icon-button
@extend %button-reset
```
## Loops and Iteration
### Generate Utility Classes
```sass
// Spacing utilities
$directions: ("": "", "t": "-top", "r": "-right", "b": "-bottom", "l": "-left")
@each $abbr, $dir in $directions
@for $i from 0 through 8
.m#{$abbr}-#{$i}
margin#{$dir}: spacing($i)
.p#{$abbr}-#{$i}
padding#{$dir}: spacing($i)
// Color utilities
@each $name, $color in $colors
.text-#{$name}
color: $color
.bg-#{$name}
background-color: $color
```
### Grid Generation
```sass
$grid-columns: 12
@for $i from 1 through $grid-columns
.col-#{$i}
width: percentage($i / $grid-columns)
// Responsive columns
@each $bp, $width in $breakpoints
@media (min-width: $width)
@for $i from 1 through $grid-columns
.col-#{$bp}-#{$i}
width: percentage($i / $grid-columns)
```
## Conditionals
```sass
=theme-button($variant)
@if $variant == "primary"
background: $color-primary
color: white
@else if $variant == "secondary"
background: transparent
color: $color-primary
border: 2px solid $color-primary
@else if $variant == "danger"
background: $color-error
color: white
@else
background: $color-text-muted
color: white
.btn-primary
+theme-button("primary")
.btn-secondary
+theme-button("secondary")
```
## Modern Module System
### Using @use and @forward
```sass
// _variables.sass
$primary: #3498db
// _mixins.sass
@use 'variables' as vars
=themed-element
color: vars.$primary
// _index.sass (barrel file)
@forward 'variables'
@forward 'mixins'
// main.sass
@use 'abstracts'
.element
+abstracts.themed-element
```
## Performance Tips
- Keep selector specificity low (prefer single class selectors)
- Avoid `!important` except for utility overrides
- Use `@use` instead of deprecated `@import`
- Limit `@extend` usage across files
- Compile without source maps in production
- Let autoprefixer handle vendor prefixes
## Code Style Guidelines
- Use 2 spaces for indentation (critical in Sass)
- Use single quotes for strings
- One blank line between rule sets
- Group related properties together
- Comment non-obvious code
- Use meaningful variable names
- Keep lines under 80 characters when possible
## Property Order
```sass
.element
// Positioning
position: relative
top: 0
right: 0
z-index: 10
// Display & Box Model
display: flex
width: 100%
padding: $spacing-md
margin: $spacing-sm 0
// Typography
font-family: $font-family-base
font-size: $font-size-base
line-height: $line-height-base
color: $color-text
// Visual
background: $color-background
border: 1px solid $color-border
border-radius: $border-radius-md
box-shadow: $shadow-sm
// Animation
transition: all $transition-base
// Misc
cursor: pointer
```
© Mindrally · Apache-2.0 · Mindrally/skills