sass-best-practices

安装量: 127
排名: #6766

安装

npx skills add https://github.com/mindrally/skills --skill sass-best-practices

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 (indented syntax) .button display: inline-flex padding: 8px 16px background: #3498db

&:hover background: darken(#3498db, 10%)

// 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 // 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 // _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 // 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 // _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 =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 =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 =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 =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 // 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 // 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 .component // Pseudo-elements &::before, &::after content: ''

// States &:hover, &:focus, &:active // State styles

// Modifiers &--variant // Modifier styles

// Media queries +respond-to("md") // Responsive styles

Functions // _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 // 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 // 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 $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 =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 // _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 .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

返回排行榜