Skip to main content
skill CX Codex

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.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add Mindrally/skills --skill sass-best-practices -a claude-code
Open on GitHub

What 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 @use manifest
  • 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.sass following the skill rules
  • rewrite this block in indented Sass with a BEM modifier
  • create a mixin for the md breakpoint 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-code

2Manually: put the files in place

~/.claude/skills/sass-best-practices/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/sass-best-practices/

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

Similar skills

Everything for Frontend and UI →

From the same set168

ruby-rails This skill hands your agent Rails conventions: generators over boilerplate, ActiveRecord patterns, Hotwire, background jobs and tests. Useful on a fresh app or an existing one. CX Codex +1 862installs seo-best-practices Provides search optimization guidelines for web apps. Helps configure metadata, JSON-LD schemas, rendering modes, and Core Web Vitals. CX Codex +1 858installs fastify-typescript Gives the agent a rulebook for Fastify and TypeScript: validation schemas, plugins, Prisma access and Jest tests. Useful when you build a typed REST API. CX Codex +1 856installs performance-optimization A rule set for web performance: server-side rendering, CSS, JavaScript, assets and caching. Useful when your agent writes frontend code and you want a bar to hold it to. CX Codex +1 848installs elixir A skill that tells your coding agent how to write Elixir and Phoenix: functional patterns, Ecto, LiveView, OTP. Useful when the project actually runs on BEAM. CX Codex +1 836installs spring-boot A skill that gives your agent Spring Boot conventions: REST controllers, JUnit tests, security, build and deploy. Useful when the project is Java. CX Codex +1 832installs responsive-design A skill that hands your coding agent a set of responsive design rules: mobile-first CSS, flexible layouts, media queries, adaptive images and type. CX Codex +1 830installs ghost Gives your agent working knowledge of Ghost CMS theme development: Handlebars templates, partials, Tailwind CSS and Alpine.js wiring, image and SEO work. CX Codex +1 828installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor