🍑

個人的によく使うSassのmixinとfunctionのまとめ

2025/03/06に公開

近年はだいたいの何かしらがSassに依存せずともCSSのみで完結できるようになりましたが、mixinやfunctionからはまだ抜け出せずにいます。
プロダクトによって増えたり減ったりしますが、だいたいいつもいるレギュラーメンバーを集めました。
レギュラーが増えたり改善したくなったら更新します。

function: 数値から単位を除外する

@use 'sass:meta';
@use 'sass:math';

/// 数値から単位を除外する
/// @param {number} $number - 単位を除外したい値
/// @example
///  strip-unit(16px) => 16
///  strip-unit(1rem) => 1
/// @return {number} - 単位を除外した値
@function strip-unit($number) {
  @if meta.type-of($number) != 'number' {
    @error '引数には数値を指定してください';
  }

  @if meta.type-of($number) == 'number' and not math.is-unitless($number) {
    @return math.div($number, $number * 0 + 1) or
      calc($number / ($number * 0 + 1));
  }

  @return $number;
}

function: pxからremに変換する

@use 'sass:math';
@use '@styles/functions/strip-unit' as *;

/// pxをremに変換する
/// @param {number} pixelSize - pxの値
/// @return {number} - remの値
/// @example
///  rem-calc(16) => 1rem
@function calc-rem($pixelSize: 16) {
  $value: strip-unit($pixelSize);
  // 基準となるpx値
  $baseSize: 16;
  @return math.div($value, $baseSize) + rem;
}

最近はビューポートベースでのサイズの指定もしてみているんですが、まだ個人的レギュラーではないのと需要があるかもわからないので記載しないです。
https://css-tricks.com/simplified-fluid-typography/

mixin: Line Clamp

省略させるのが1行だったり複数行だったり、配置される箇所によって異なったりするので一貫性を保つためにmixinにして使うことが多いです。
https://codepen.io/p-n-pochizo/pen/GgRrKQv

@use '@styles/functions/strip-unit' as *; // 前述のstrip-unit関数を読み込む

/// 指定した行数でテキストを省略する
/// @param {number} $length - 行数
@mixin line-clamp($length: 1) {
  $rowLength: strip-unit($length);

  display: -webkit-box;
  -webkit-line-clamp: $rowLength;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

mixin: Visually Hidden

表示の要件にはないけれど情報の構造的には必要そうな見出しなどを配置する際によく使います。
https://codepen.io/p-n-pochizo/pen/xxopVPV

/// 非表示の要素をアクセス可能にする
@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-width: 0;
}

mixin: メディア特性(width)

世の中には古の時代からsass-mqとかがあるけれど、少し面倒で認知負荷が高く記法もちょっと古いので簡潔にしています。
ブレークポイントが少なめの実装で済む場合はこれくらいでよいかなと思ってます。
https://codepen.io/p-n-pochizo/pen/gbOWwdN?editors=1100

/// PC、タブレット、モバイル端末向けの場合
$pc-min-width: 1280px;
$tablet-min-width: 768px;

@mixin mobile {
  @media (width < $tablet-min-width) {
    @content;
  }
}

@mixin tablet {
  @media ($tablet-min-width <= width < $pc-min-width) {
    @content;
  }
}

@mixin pc {
  @media ($pc-min-width <= width) {
    @content;
  }
}
/// PCとモバイル端末向けのみの場合
$pc-min-width: 1280px;

@mixin pc {
  @media ($pc-min-width <= width) {
    @content;
  }
}

@mixin mobile {
  @media (width < $pc-min-width) {
    @content;
  }
}

mixin: メディア特性(any-hover)

単純ですが一貫性を保つためにmixinにしています。
https://codepen.io/p-n-pochizo/pen/gbOWwqV

/// hoverをサポートしている環境でスタイルを適用する
@mixin any-hover {
  @media (any-hover: hover) {
    @content;
  }
}

mixin: 箇条書きリスト

余白の値などはプロダクトによって適宜変更します。
https://codepen.io/p-n-pochizo/pen/OPJmRqJ

/// 箇条書きリスト
@mixin bullet-list {
  display: grid;
  grid-auto-flow: row;
  padding-left: 1.5em;

  > li {
    &:not(:last-child) {
      margin-bottom: 0.5em;
    }
  }
}
/// ul、ol要素をカスタマイズした箇条書きリストに変更する。
/// @parameter {string} $content - 箇条書きリストの接頭辞に表示する文字列
/// @parameter {string} $counter-name - 箇条書きリストのカウンター名
/// @example
///  @include custom-bullet-list('※', 'list');
///  @include custom-bullet-list(counter(nested-list) ')', nested-list);

@mixin custom-bullet-list($content: '', $counter-name: list) {
  @if $counter-name {
    counter-reset: #{$counter-name};
  }

  display: grid;
  position: relative;
  grid-auto-flow: row;
  margin-left: 0;
  padding-left: 1.5em;
  list-style: none;
  row-gap: 0.5em;

  > li {
    @include custom-bullet-list-item($content, #{$counter-name});
  }
}

@mixin custom-bullet-list-item($content: '', $counter-name: list) {
  @if $counter-name {
    counter-increment: #{$counter-name};
  }

  &::before {
    position: absolute;
    left: 0;
    @if $content {
      content: $content;
    }
  }
}
株式会社ソニックムーブ

Discussion