mcpField
S
sass-best-practices

sass-best-practices

github.com/mindrallyデザイン・UI287850 回インストール3 週間前に更新
リポジトリ

sass-best-practices について

インデント構文の Sass と保守しやすいスタイルシート開発の実践ガイドです。モジュール構成、命名、ネスト、パフォーマンス、コードスタイルを扱います。

主な機能

  1. 01インデント構文の規則
  2. 02スタイルシート構成の指針
  3. 03変数、ミックスイン、関数の活用
  4. 04BEM 命名とネストの指針
  5. 05モジュールシステムと性能のヒント

活用シーン

  1. 01Sass プロジェクトの構成作成
  2. 02チームのスタイル規約の統一
  3. 03再利用可能なレスポンシブミックスインの作成
  4. 04Sass のネストとモジュール構成の確認

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/sass-best-practicesを入力して読み込まれたか確認します。

詳細

Sass のベストプラクティス

Sass(インデント構文)、CSS アーキテクチャ、保守しやすいスタイルシート開発の専門家です。

主な原則

  • インデント構文(空白に依存する構文)を使って、クリーンで読みやすい Sass を記述します
  • Sass の機能を活用して、DRY でモジュール化されたスタイルシートを作成します
  • コードの構造を定義するため、インデントを一貫させます
  • スタイルの整理では、シンプルさとわかりやすさを優先します

Sass と SCSS

Sass は従来のインデント構文を使用します。

  • 波括弧 {}
  • セミコロン ;
  • インデントでネストを定義
  • ファイル拡張子:.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%);
  }
}

ファイル構成

プロジェクト構成
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.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.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)
マップの使用
// 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.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 ユーティリティ
=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
タイポグラフィ
=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)
アクセシビリティ
=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-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 命名規則

// 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

ネストのガイドライン

ネストは浅く保つ
// 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
許容されるネスト
.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

// 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)

プレースホルダーと 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

ループと反復処理

ユーティリティクラスを生成する
// 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-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)

条件分岐

=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")

最新のモジュールシステム

@use と @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

パフォーマンスのヒント

  • セレクターの詳細度を低く保ちます(単一クラスセレクターを優先します)
  • ユーティリティでの上書きを除き、!important は避けます
  • 非推奨の @import ではなく、@use を使用します
  • ファイル間での @extend の使用を制限します
  • 本番環境ではソースマップなしでコンパイルします
  • ベンダープレフィックスの処理は autoprefixer に任せます

コードスタイルのガイドライン

  • インデントには 2 つのスペースを使用します(Sass では特に重要です)
  • 文字列にはシングルクォートを使用します
  • ルールセットの間には空行を 1 行入れます
  • 関連するプロパティをまとめます
  • 一目でわからないコードにはコメントを付けます
  • 意味のある変数名を使用します
  • 可能であれば、行の長さを 80 文字未満に保ちます

プロパティの順序

.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

コメント