Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component...
npx skills add Mindrally/skills --skill "scss-best-practices"
Install specific skill from multi-skill repository
# Description
SCSS/Sassy CSS best practices and coding guidelines for maintainable, scalable stylesheets
# SKILL.md
name: scss-best-practices
description: SCSS/Sassy CSS best practices and coding guidelines for maintainable, scalable stylesheets
SCSS Best Practices
You are an expert in SCSS (Sassy CSS), CSS architecture, and maintainable stylesheet development.
Key Principles
- Write modular, reusable SCSS that scales with project complexity
- Follow the DRY (Don't Repeat Yourself) principle using variables, mixins, and functions
- Maintain clear separation between structure, skin, and state styles
- Prioritize readability and maintainability over clever abstractions
File Organization
Architecture Pattern (7-1 Pattern)
scss/
βββ abstracts/
β βββ _variables.scss # Global variables
β βββ _functions.scss # SCSS functions
β βββ _mixins.scss # Reusable mixins
β βββ _placeholders.scss # Extendable placeholders
βββ base/
β βββ _reset.scss # CSS reset/normalize
β βββ _typography.scss # Typography rules
β βββ _base.scss # Base element styles
βββ components/
β βββ _buttons.scss # Button components
β βββ _cards.scss # Card components
β βββ _forms.scss # Form components
βββ layout/
β βββ _header.scss # Header layout
β βββ _footer.scss # Footer layout
β βββ _grid.scss # Grid system
β βββ _navigation.scss # Navigation layout
βββ pages/
β βββ _home.scss # Home page specific
β βββ _contact.scss # Contact page specific
βββ themes/
β βββ _default.scss # Default theme
βββ vendors/
β βββ _bootstrap.scss # Third-party overrides
βββ main.scss # Main manifest file
Import Order
// main.scss
@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/navigation';
@use 'layout/footer';
@use 'components/buttons';
@use 'components/cards';
@use 'components/forms';
@use 'pages/home';
@use 'themes/default';
Variables
Naming Convention
// Use semantic, descriptive names
// Format: $category-property-variant
// 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 (use consistent scale)
$spacing-unit: 8px;
$spacing-xs: $spacing-unit * 0.5; // 4px
$spacing-sm: $spacing-unit; // 8px
$spacing-md: $spacing-unit * 2; // 16px
$spacing-lg: $spacing-unit * 3; // 24px
$spacing-xl: $spacing-unit * 4; // 32px
$spacing-xxl: $spacing-unit * 6; // 48px
// Breakpoints
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
$breakpoint-xl: 1200px;
$breakpoint-xxl: 1400px;
// Z-index scale
$z-index-dropdown: 1000;
$z-index-sticky: 1020;
$z-index-fixed: 1030;
$z-index-modal-backdrop: 1040;
$z-index-modal: 1050;
$z-index-popover: 1060;
$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;
$border-radius-circle: 50%;
// 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);
$shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15);
Maps for Related Values
// Use maps for grouped values
$colors: (
'primary': #3498db,
'secondary': #2ecc71,
'danger': #e74c3c,
'warning': #f39c12,
'info': #17a2b8,
'success': #27ae60
);
$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px,
'xxl': 1400px
);
// Access with map-get
.element {
color: map-get($colors, 'primary');
}
Mixins
Responsive Breakpoints
@mixin 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%;
@include respond-to('md') {
width: 50%;
}
@include respond-to('lg') {
width: 33.333%;
}
}
Flexbox Utilities
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
@mixin flex-between {
display: flex;
align-items: center;
justify-content: space-between;
}
@mixin flex-column {
display: flex;
flex-direction: column;
}
Typography
@mixin font-size($size, $line-height: null) {
font-size: $size;
@if $line-height {
line-height: $line-height;
}
}
@mixin 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;
}
}
Accessibility
@mixin 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;
}
@mixin focus-visible {
&:focus-visible {
outline: 2px solid $color-primary;
outline-offset: 2px;
}
}
BEM Naming Convention
Structure
// Block: Standalone component
// Element: Part of block (block__element)
// Modifier: Variant (block--modifier or block__element--modifier)
.card {
// Block styles
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 Rules
Maximum Nesting Depth
// BAD: Too deep nesting
.nav {
.nav-list {
.nav-item {
.nav-link {
.nav-icon {
// 5 levels deep - avoid this
}
}
}
}
}
// GOOD: Keep nesting to 3 levels maximum
.nav {
// Level 1
}
.nav__list {
// Level 1
}
.nav__item {
// Level 1
}
.nav__link {
color: $color-text;
&:hover,
&:focus {
// Level 2 - acceptable for states
color: $color-primary;
}
&--active {
// Level 2 - acceptable for modifiers
color: $color-primary;
font-weight: $font-weight-bold;
}
}
Acceptable Nesting
.component {
// Direct child pseudo-elements
&::before,
&::after {
content: '';
}
// State modifiers
&:hover,
&:focus,
&:active {
// State styles
}
// BEM modifiers
&--variant {
// Modifier styles
}
// Media queries
@include respond-to('md') {
// Responsive styles
}
}
Functions
Color Functions
@function tint($color, $percentage) {
@return mix(white, $color, $percentage);
}
@function shade($color, $percentage) {
@return mix(black, $color, $percentage);
}
// Usage
.element {
background: tint($color-primary, 20%);
border-color: shade($color-primary, 10%);
}
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;
}
// Usage
.element {
font-size: px-to-rem(18); // 1.125rem
padding: px-to-rem(24); // 1.5rem
}
Spacing Function
@function spacing($multiplier) {
@return $spacing-unit * $multiplier;
}
// Usage
.element {
margin-bottom: spacing(2); // 16px
padding: spacing(3); // 24px
}
Extend and Placeholders
Use Placeholders Over Classes
// Define placeholder
%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;
}
}
// Extend placeholder
.btn-primary {
@extend %button-base;
background: $color-primary;
color: white;
&:hover:not(:disabled) {
background: darken($color-primary, 10%);
}
}
.btn-secondary {
@extend %button-base;
background: transparent;
color: $color-primary;
border: 2px solid $color-primary;
&:hover:not(:disabled) {
background: $color-primary;
color: white;
}
}
Loops and Iteration
Generate Utility Classes
// Spacing utilities
$spacing-directions: (
'': '',
't': '-top',
'r': '-right',
'b': '-bottom',
'l': '-left',
'x': '-inline',
'y': '-block'
);
@each $abbr, $direction in $spacing-directions {
@for $i from 0 through 8 {
.m#{$abbr}-#{$i} {
margin#{$direction}: spacing($i);
}
.p#{$abbr}-#{$i} {
padding#{$direction}: spacing($i);
}
}
}
// Color utilities
@each $name, $color in $colors {
.text-#{$name} {
color: $color;
}
.bg-#{$name} {
background-color: $color;
}
.border-#{$name} {
border-color: $color;
}
}
Performance Best Practices
- Avoid overly specific selectors; aim for specificity of 0-1-0 (single class)
- Never use
!importantexcept for utility classes - Minimize use of
@extendacross files (can cause bloat) - Use
@useand@forwardinstead of@import(deprecated) - Compile with source maps in development, without in production
- Use autoprefixer for vendor prefixes instead of manual prefixes
Modern SCSS Features
Module System
// _variables.scss
$primary: #3498db;
// _mixins.scss
@use 'variables' as vars;
@mixin themed-button {
background: vars.$primary;
}
// main.scss
@use 'mixins';
.button {
@include mixins.themed-button;
}
Built-in Modules
@use 'sass:math';
@use 'sass:color';
@use 'sass:list';
@use 'sass:map';
@use 'sass:string';
.element {
width: math.div(100%, 3);
background: color.adjust($color-primary, $lightness: 10%);
}
Code Style
- Use 2 spaces for indentation
- Use single quotes for strings
- Add a space after colons in declarations
- Add a space before opening braces
- Put closing braces on new lines
- Separate rule sets with blank lines
- Order properties logically (positioning, box model, typography, visual, misc)
- Comment complex calculations and non-obvious code
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.