Das meistgenutzte Responsive-Mixin von Bootstrap. Es hält die Breakpoints an einem Ort und macht umfangreiches Komponenten-SCSS deutlich übersichtlicher.

@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($name, $breakpoints);

  @if $min {
    @media (min-width: $min) {
      @content;
    }
  } @else {
    @content;
  }
}

// Usage
.card-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;

  @include media-breakpoint-up(lg) {
    grid-template-columns: repeat(3, 1fr);
  }
}
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints)
  $min: breakpoint-min($name, $breakpoints)

  @if $min
    @media (min-width: $min)
      @content
  @else
    @content

// Usage
.card-grid
  display: grid
  gap: 16px
  grid-template-columns: 1fr

  +media-breakpoint-up(lg)
    grid-template-columns: repeat(3, 1fr)
// Equivalent output
.card-grid {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
}

@media (min-width: 992px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

Praktisch, wenn ein Layout eine Korrektur nur für Tablets braucht, ohne kleine oder große Bildschirme zu beeinflussen.

@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
  $min: breakpoint-min($lower, $breakpoints);
  $max: breakpoint-max($upper, $breakpoints);

  @media (min-width: $min) and (max-width: $max) {
    @content;
  }
}

// Usage
.toolbar {
  @include media-breakpoint-between(md, lg) {
    gap: 8px;
    flex-wrap: wrap;
  }
}
@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints)
  $min: breakpoint-min($lower, $breakpoints)
  $max: breakpoint-max($upper, $breakpoints)

  @media (min-width: $min) and (max-width: $max)
    @content

// Usage
.toolbar
  +media-breakpoint-between(md, lg)
    gap: 8px
    flex-wrap: wrap
@media (min-width: 768px) and (max-width: 991.98px) {
  .toolbar {
    gap: 8px;
    flex-wrap: wrap;
  }
}

Zusammen mit make-row() und make-col-ready() ist das der schnellste Weg, eigene Grid-Bausteine auf Basis des Bootstrap-Systems zu bauen.

@mixin make-col($size: false, $columns: $grid-columns) {
  @if $size {
    flex: 0 0 auto;
    width: percentage(divide($size, $columns));
  } @else {
    flex: 1 1 0;
    max-width: 100%;
  }
}

// Usage
.feature-row {
  @include make-row();
}

.feature-card {
  @include make-col-ready();
  @include make-col(6);

  @include media-breakpoint-up(xl) {
    @include make-col(3);
  }
}
@mixin make-col($size: false, $columns: $grid-columns)
  @if $size
    flex: 0 0 auto
    width: percentage(divide($size, $columns))
  @else
    flex: 1 1 0
    max-width: 100%

// Usage
.feature-row
  +make-row()

.feature-card
  +make-col-ready()
  +make-col(6)

  +media-breakpoint-up(xl)
    +make-col(3)
.feature-row {
  display: flex;
  flex-wrap: wrap;
  margin-inline: -12px;
}

.feature-card {
  width: 50%;
  padding-inline: 12px;
}

@media (min-width: 1200px) {
  .feature-card {
    width: 25%;
  }
}
6/12
6/12
3/12
3/12

Einer der wenigen Barrierefreiheits-Helfer, die in keiner Komponentenbibliothek fehlen sollten.

@mixin visually-hidden() {
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

// Usage
.icon-button__label {
  @include visually-hidden();
}
@mixin visually-hidden()
  width: 1px !important
  height: 1px !important
  padding: 0 !important
  margin: -1px !important
  overflow: hidden !important
  clip: rect(0, 0, 0, 0) !important
  white-space: nowrap !important
  border: 0 !important

// Usage
.icon-button__label
  +visually-hidden()
.icon-button__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

Die Beschriftung für Screenreader bleibt zugänglich, während die sichtbare UI nur ein Icon zeigt.

Ein praktisches Utility, wenn ein Badge, Punkt, Ziehpunkt oder Overlay exakt in der visuellen Mitte fixiert werden soll.

@mixin centerer($horizontal: true, $vertical: true) {
  position: absolute;

  @if ($horizontal and $vertical) {
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}

// Usage
.badge-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: $accent;

  @include centerer;
}
@mixin centerer($horizontal: true, $vertical: true)
  position: absolute

  @if ($horizontal and $vertical)
    top: 50%
    left: 50%
    transform: translate(-50%, -50%)

// Usage
.badge-dot
  width: 18px
  height: 18px
  border-radius: 50%
  background: $accent
  +centerer
.badge-dot {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Gut geeignet für dekorative Wörter im Hero-Bereich, Poster-Typografie und Beschriftungen mit transparenter Füllung.

@mixin text-outline($color: black, $stroke: 1px) {
  color: transparent;
  -webkit-text-stroke-width: $stroke;
  -webkit-text-stroke-color: $color;
}

// Usage
.hero-word {
  font-size: 72px;
  font-weight: 700;

  @include text-outline(#111827, 1.5px);
}
@mixin text-outline($color: black, $stroke: 1px)
  color: transparent
  -webkit-text-stroke-width: $stroke
  -webkit-text-stroke-color: $color

// Usage
.hero-word
  font-size: 72px
  font-weight: 700
  +text-outline(#111827, 1.5px)
.hero-word {
  font-size: 72px;
  font-weight: 700;
  color: transparent;
  -webkit-text-stroke: 1.5px #111827;
}
KONTUR

Praktisch für Ladebalken, Fortschrittsanzeigen, Akzente in Skeleton-Screens oder jede Fläche, die Bewegung ohne Bilder braucht.

@mixin stripes($opacity, $color, $size: 25px, $deg: -135deg) {
  background-size: $size $size;
  background-image: linear-gradient($deg, rgba($color, $opacity) 25%, transparent 25%, transparent 50%, rgba($color, $opacity) 50%, rgba($color, $opacity) 75%, transparent 75%, transparent);
}

// Usage
.loader-track {
  @include stripes(.22, #2563eb, 20px, -45deg);
}
@mixin stripes($opacity, $color, $size: 25px, $deg: -135deg)
  background-size: $size $size
  background-image: linear-gradient($deg, rgba($color, $opacity) 25%, transparent 25%, transparent 50%, rgba($color, $opacity) 50%, rgba($color, $opacity) 75%, transparent 75%, transparent)

// Usage
.loader-track
  +stripes(.22, #2563eb, 20px, -45deg)
.loader-track {
  background-size: 20px 20px;
  background-image: linear-gradient(
    -45deg,
    rgba(37, 99, 235, .22) 25%,
    transparent 25%,
    transparent 50%,
    rgba(37, 99, 235, .22) 50%,
    rgba(37, 99, 235, .22) 75%,
    transparent 75%,
    transparent
  );
}

Einer der stärkeren eigenen Helfer. Durch den Masking-Ansatz eignet er sich besonders für Premium-Karten und Hinweisboxen.

@mixin border-gradient($color1: #fff, $color2: #fff, $deg: 45deg, $border: 1px) {
  background: linear-gradient($deg, $color1, $color2) border-box;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  border: $border solid transparent;
}

// Usage
.promo-card {
  border-radius: 16px;
  @include border-gradient(#22c55e, #0ea5e9, 135deg, 1px);
}
@mixin border-gradient($color1: #fff, $color2: #fff, $deg: 45deg, $border: 1px)
  background: linear-gradient($deg, $color1, $color2) border-box
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)
  -webkit-mask-composite: xor
  mask-composite: exclude
  border: $border solid transparent

// Usage
.promo-card
  border-radius: 16px
  +border-gradient(#22c55e, #0ea5e9, 135deg, 1px)
.promo-card {
  border: 1px solid transparent;
  border-radius: 16px;
  background:
    linear-gradient(135deg, #22c55e, #0ea5e9) border-box;
  -webkit-mask:
    linear-gradient(#fff 0 0) padding-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
}
Rahmen für Premium-Karte

Einer der vielseitigsten Helfer überhaupt. Er gehört in jeder internen Sass-Bibliothek ganz nach oben.

Erstelle eine eigene Version mit allen nötigen Parametern im clamp()-Generator

@function to-clamp($min-size, $max-size, $min-screen: 375px, $max-screen: 1920px) {
  $min-size-rem: math.div($min-size, 16px) * 1rem;
  $max-size-rem: math.div($max-size, 16px) * 1rem;
  // preferred(vw) = (min-size - slope * min-screen) + slope * 100vw
  $slope: math.div($max-size - $min-size, $max-screen - $min-screen);
  $intercept-rem: math.div($min-size - $slope * $min-screen, 16px) * 1rem;
  $slope-vw: $slope * 100 * 1vw;
  @return clamp(#{$min-size-rem}, calc(#{$intercept-rem} + #{$slope-vw}), #{$max-size-rem});
}

// Usage
.headline {
  font-size: to-clamp(28px, 72px);
  margin-bottom: to-rem(24px);
}
@function to-clamp($min-size, $max-size, $min-screen: 375px, $max-screen: 1920px)
  $min-size-rem: math.div($min-size, 16px) * 1rem
  $max-size-rem: math.div($max-size, 16px) * 1rem
  // preferred(vw) = (min-size - slope * min-screen) + slope * 100vw
  $slope: math.div($max-size - $min-size, $max-screen - $min-screen)
  $intercept-rem: math.div($min-size - $slope * $min-screen, 16px) * 1rem
  $slope-vw: $slope * 100 * 1vw
  @return clamp(#{$min-size-rem}, calc(#{$intercept-rem} + #{$slope-vw}), #{$max-size-rem})

// Usage
.headline
  font-size: to-clamp(28px, 72px)
  margin-bottom: to-rem(24px)
.headline {
  font-size: clamp(1.75rem, calc(1.0825rem + 2.85vw), 4.5rem);
  margin-bottom: 1.5rem;
}
Fluide Überschrift

Ein wiederverwendbares Slider-Mixin, das die Styles für Track, Thumb, hover, focus und disabled bündelt – jeder Produktbereich kann Farben und Maße dabei selbst anpassen.

@mixin c-range-styles(
  $track-height: 4px,
  $track-color: $dark-200,
  $thumb-size: 14px,
  $thumb-color: $primary,
  $thumb-border-width: 0,
  $thumb-border-color: transparent,
  $thumb-shadow: none,
  $hover-scale: 1.15,
  $focus-shadow: 0 2px 6px rgba(0, 0, 0, 0.18)
) {
  appearance: none;
  background: transparent;
  cursor: pointer;

  &::-webkit-slider-runnable-track {
    height: $track-height;
    background: $track-color;
    border-radius: 999px;
  }

  &::-webkit-slider-thumb {
    appearance: none;
    width: $thumb-size;
    height: $thumb-size;
    margin-top: math.div($track-height - $thumb-size, 2);
    border-radius: 50%;
    background: $thumb-color;
    border: $thumb-border-width solid $thumb-border-color;
    box-shadow: $thumb-shadow;
  }
}

// Usage
.c-range {
  @include c-range-styles(
    $track-height: 6px,
    $track-color: #dbe3ef,
    $thumb-size: 18px,
    $thumb-color: #111827
  );
}
@mixin c-range-styles(
  $track-height: 4px,
  $track-color: $dark-200,
  $thumb-size: 14px,
  $thumb-color: $primary,
  $thumb-border-width: 0,
  $thumb-border-color: transparent,
  $thumb-shadow: none,
  $hover-scale: 1.15,
  $focus-shadow: 0 2px 6px rgba(0, 0, 0, 0.18)
)
  appearance: none
  background: transparent
  cursor: pointer

  &::-webkit-slider-runnable-track
    height: $track-height
    background: $track-color
    border-radius: 999px

  &::-webkit-slider-thumb
    appearance: none
    width: $thumb-size
    height: $thumb-size
    margin-top: math.div($track-height - $thumb-size, 2)
    border-radius: 50%
    background: $thumb-color
    border: $thumb-border-width solid $thumb-border-color
    box-shadow: $thumb-shadow

// Usage
.c-range
  +c-range-styles(
    $track-height: 6px,
    $track-color: #dbe3ef,
    $thumb-size: 18px,
    $thumb-color: #111827
  )
.c-range {
  appearance: none;
  background: transparent;
}

.c-range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: #dbe3ef;
}

.c-range::-webkit-slider-thumb {
  width: 18px;
  height: 18px;
  margin-top: -6px;
  border-radius: 50%;
  background: #111827;
}

Ein Mixin legt die Positionierung auf Haupt- und Querachse gemeinsam fest – statt Ausrichtungsdeklarationen über alle Komponenten zu verstreuen.

@mixin flex-align($align: center, $justify: center) {
  align-items: $align;
  justify-content: $justify;
}
// $align: flex-start | center | flex-end | stretch | baseline
// $justify: flex-start | center | flex-end | space-between | space-around | space-evenly

// Usage
.toolbar {
  display: flex;
  @include flex-align(center, space-between);
}
@mixin flex-align($align: center, $justify: center)
  align-items: $align
  justify-content: $justify
// $align: flex-start | center | flex-end | stretch | baseline
// $justify: flex-start | center | flex-end | space-between | space-around | space-evenly

// Usage
.toolbar
  display: flex
  +flex-align(center, space-between)
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
Filter Sortieren Export Teilen

Praktisch, wenn Farbe und Strichstärke von Icons über die Elternkomponente gesteuert werden sollen statt im Markup jedes einzelnen Icons.

@mixin svg($color, $width) {
  svg {
    path,
    line,
    polyline {
      stroke: $color;
      stroke-width: $width;
    }

    path {
      fill: transparent;
    }
  }
}

// Usage
.icon-wrap {
  @include svg(#111827, 1.5px);
}
@mixin svg($color, $width)
  svg
    path,
    line,
    polyline
      stroke: $color
      stroke-width: $width

    path
      fill: transparent

// Usage
.icon-wrap
  +svg(#111827, 1.5px)
.icon-wrap svg path,
.icon-wrap svg line,
.icon-wrap svg polyline {
  stroke: #111827;
  stroke-width: 1.5px;
}

Ein praktischer Asset-Helfer für Projekte, die noch Raster-Hintergründe in mehreren Auflösungen ausliefern.

@mixin background-image($img, $type: png, $x: 0, $y: 0, $repeat: no-repeat) {
  background-image: url("../images/#{$img}.#{$type}");
  background-image: image-set(
    url("../images/#{$img}.#{$type}") 1x,
    url("../images/#{$img}@2x.#{$type}") 2x,
    url("../images/#{$img}@3x.#{$type}") 3x
  );
  background-repeat: #{$repeat};
  background-position: #{$x}px #{$y}px;
}

// Usage
.hero {
  @include background-image("noise", png, 0, 0, repeat);
}
@mixin background-image($img, $type: png, $x: 0, $y: 0, $repeat: no-repeat)
  background-image: url("../images/#{$img}.#{$type}")
  background-image: image-set(url("../images/#{$img}.#{$type}") 1x, url("../images/#{$img}@2x.#{$type}") 2x, url("../images/#{$img}@3x.#{$type}") 3x)
  background-repeat: #{$repeat}
  background-position: #{$x}px #{$y}px

// Usage
.hero
  +background-image("noise", png, 0, 0, repeat)
.hero {
  background-image: url("../images/noise.png");
  background-repeat: repeat;
  background-position: 0 0;
}
Retina-taugliche Hintergrundfläche

Immer noch nützlich, wenn du herstellerspezifische placeholder-Selektoren aus Formularkomponenten heraushalten willst.

@mixin placeholder {
  &::-webkit-input-placeholder { @content; }
  &:-moz-placeholder { @content; }
  &::-moz-placeholder { @content; }
  &:-ms-input-placeholder { @content; }
}

// Usage
.input {
  @include placeholder {
    color: rgba($text, .45);
  }
}
@mixin placeholder
  &::-webkit-input-placeholder
    @content
  &:-moz-placeholder
    @content
  &::-moz-placeholder
    @content
  &:-ms-input-placeholder
    @content

// Usage
.input
  +placeholder
    color: rgba($text, .45)
.input::placeholder {
  color: rgba(17, 24, 39, .45);
}

Praktisch für Utility-Animationsstapel, wenn du mehrere Animationsfragmente als Argumente übergeben willst.

@mixin anim($animate...) {
  $max: length($animate);
  $animations: "";
  @for $i from 1 through $max {
    $animations: #{$animations + nth($animate, $i)};
  }
  animation: $animations;
}

// Usage
.pulse-chip {
  @include anim(fade-in .25s ease, float 2s linear infinite);
}
@mixin anim($animate...)
  $max: length($animate)
  $animations: ""
  @for $i from 1 through $max
    $animations: #{$animations + nth($animate, $i)}
  animation: $animations

// Usage
.pulse-chip
  +anim(fade-in .25s ease, float 2s linear infinite)
.pulse-chip {
  animation: fade-in .25s ease, float 2s linear infinite;
}
Live-Status

Praktisch, wenn ein schlichter linearer Rahmen zu flach wirkt und du ein Leuchten an den Ecken möchtest.

@mixin border-radial-gradient($color1: #fff, $color2: #fff, $percent: 25%) {
  background: radial-gradient(circle at 0% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 100%, $color1 0%, $color2 $percent) border-box;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  border: 1px solid transparent;
}

@mixin border-radial-gradient-x2($color1: #fff, $color2: #fff, $percent: 25%) {
  background: radial-gradient(circle at 0% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 0% 100%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 100%, $color1 0%, $color2 $percent) border-box;
  border: 1px solid transparent;
}

// Usage
.panel {
  @include border-radial-gradient-x2(#7c3aed, #06b6d4, 32%);
}
@mixin border-radial-gradient($color1: #fff, $color2: #fff, $percent: 25%)
  background: radial-gradient(circle at 0% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 100%, $color1 0%, $color2 $percent) border-box
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)
  -webkit-mask-composite: xor
  border: 1px solid transparent

@mixin border-radial-gradient-x2($color1: #fff, $color2: #fff, $percent: 25%)
  background: radial-gradient(circle at 0% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 0%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 0% 100%, $color1 0%, $color2 $percent) border-box, radial-gradient(circle at 100% 100%, $color1 0%, $color2 $percent) border-box
  border: 1px solid transparent

// Usage
.panel
  +border-radial-gradient-x2(#7c3aed, #06b6d4, 32%)
.panel {
  border: 1px solid transparent;
  background: radial-gradient(circle at 0% 0%, #7c3aed 0%, #06b6d4 32%) border-box;
}
Rahmen für Premium-Karte

Die projekteigene Variante, die bereits in verschiedenen UI-Teilen genutzt wird; am besten neben deinen anderen wiederverwendbaren Oberflächen-Helfern aufbewahren.

@mixin scrollbars($size, $foreground-color, $background-color: mix($foreground-color, white, 50%)) {
  &::-webkit-scrollbar { width: $size; height: $size; }
  &::-webkit-scrollbar-thumb { background: $foreground-color; }
  &::-webkit-scrollbar-track { background: $background-color; }
}

// Usage
.panel {
  @include scrollbars(10px, #111827, #e5e7eb);
}
@mixin scrollbars($size, $foreground-color, $background-color: mix($foreground-color, white, 50%))
  &::-webkit-scrollbar
    width: $size
    height: $size
  &::-webkit-scrollbar-thumb
    background: $foreground-color
  &::-webkit-scrollbar-track
    background: $background-color

// Usage
.panel
  +scrollbars(10px, #111827, #e5e7eb)
.panel::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.panel::-webkit-scrollbar-thumb {
  background: #111827;
}

.panel::-webkit-scrollbar-track {
  background: #e5e7eb;
}
Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar.

Die projektspezifische Variante des font-face-Setups. Praktisch, um ein include pro Dateifamilie zu haben.

@mixin font($fname, $fstyle, $fweight, $furl, $fstrech: normal) {
  @font-face {
    font-family: $fname;
    font-style: $fstyle;
    font-weight: $fweight;
    font-stretch: $fstrech;
    src: url($furl) format("woff2");
    font-display: swap;
  }
}

// Usage
@include font("Manrope", normal, 500, "/fonts/manrope-500.woff2");
@mixin font($fname, $fstyle, $fweight, $furl, $fstrech: normal)
  @font-face
    font-family: $fname
    font-style: $fstyle
    font-weight: $fweight
    font-stretch: $fstrech
    src: url($furl) format("woff2")
    font-display: swap

// Usage
+font("Manrope", normal, 500, "/fonts/manrope-500.woff2")
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 500;
  src: url("/fonts/manrope-500.woff2") format("woff2");
  font-display: swap;
}
Aa
Überschrift für die Schriftvorschau

Praktisch für gestylte nummerierte Listen, ohne den Counter-Boilerplate in jeder Komponente zu wiederholen.

@mixin counter($var, $sep) {
  counter-reset: list + $var;
  > li {
    &:before {
      content: counter(list + $var) $sep;
      counter-increment: list + $var;
    }
  }
}

// Usage
.steps {
  @include counter(step, ". ");
}
@mixin counter($var, $sep)
  counter-reset: list + $var
  > li
    &:before
      content: counter(list + $var) $sep
      counter-increment: list + $var

// Usage
.steps
  +counter(step, ". ")
.steps {
  counter-reset: step;
}

.steps > li::before {
  counter-increment: step;
  content: counter(step) ". ";
}
  1. Quelldateien sammeln
  2. Benennung vereinheitlichen
  3. Finale Assets exportieren

Ein dekorativer Helfer für plastische Überschriften und stilisierten Markentext.

@mixin text3d($primary, $depth: 5, $shadowsteps: 5, $shadowincrementer: 3px, $shadowopacity: 0.4, $primaryshadowcolour: #000, $lighting: $LIGHTING_CEIL) {
  $predefinedShadows: (
    0 0 5px rgba($primaryshadowcolour, 0.05),
    0 -1px 3px rgba($primaryshadowcolour, 0.2),
    0 3px 5px rgba($primaryshadowcolour, 0.2)
  );
  $value: ();

  @for $i from 1 through $depth {
    $num: $i + px;
    $num1: $i * 1.3 + px;
    $hueadjust: $i * 0.2;

    @if ($lighting == $LIGHTING_FLOOR) {
      $hueadjust: ($i * 2 - $depth - 5) * 1%;
    } @else if ($lighting == $LIGHTING_CEIL) {
      $hueadjust: -($i * 2 + $depth - 10) * 1%;
    } @else if ($lighting == $LIGHTING_FLAT) {
      $hueadjust: -$depth * 1%;
    }

    $colour: adjust-color($primary, $lightness: $hueadjust);
    $theShadow: $num1 $num 1px $colour;
    $value: append($value, $theShadow, comma);
  }

  @for $i from 1 through $shadowsteps {
    @if ($i >= length($predefinedShadows)) {
      $dist: $i * $shadowincrementer;
      $value: append($value, 0 $dist $dist rgba($primaryshadowcolour, $shadowopacity));
    } @else {
      $value: append($value, nth($predefinedShadows, $i));
    }
  }

  text-shadow: $value;
}

// Usage
.logo-mark {
  @include text3d(#f97316, 6, 4, 3px, .18);
}
@mixin text3d($primary, $depth: 5, $shadowsteps: 5, $shadowincrementer: 3px, $shadowopacity: 0.4, $primaryshadowcolour: #000, $lighting: $LIGHTING_CEIL)
  $predefinedShadows: (0 0 5px rgba($primaryshadowcolour, 0.05), 0 -1px 3px rgba($primaryshadowcolour, 0.2), 0 3px 5px rgba($primaryshadowcolour, 0.2))
  $value: ()

  @for $i from 1 through $depth
    $num: $i + px
    $num1: $i * 1.3 + px
    $hueadjust: $i * 0.2

    @if ($lighting == $LIGHTING_FLOOR)
      $hueadjust: ($i * 2 - $depth - 5) * 1%
    @else if ($lighting == $LIGHTING_CEIL)
      $hueadjust: -($i * 2 + $depth - 10) * 1%
    @else if ($lighting == $LIGHTING_FLAT)
      $hueadjust: -$depth * 1%

    $colour: adjust-color($primary, $lightness: $hueadjust)
    $theShadow: $num1 $num 1px $colour
    $value: append($value, $theShadow, comma)

  @for $i from 1 through $shadowsteps
    @if ($i >= length($predefinedShadows))
      $dist: $i * $shadowincrementer
      $value: append($value, 0 $dist $dist rgba($primaryshadowcolour, $shadowopacity))
    @else
      $value: append($value, nth($predefinedShadows, $i))

  text-shadow: $value

// Usage
.logo-mark
  +text3d(#f97316, 6, 4, 3px, .18)
.logo-mark {
  text-shadow: 1px 1px 0 #f59e0b, 2px 2px 0 #ea580c, 0 8px 16px rgba(0,0,0,.12);
}
JINERO

Das Gegenstück zu text3d() für Boxen – praktisch für Chips, Buttons und verspielte, erhabene UI-Blöcke.

@mixin box3d($primary, $depth: 5, $shadowsteps: 5, $shadowincrementer: 3px, $shadowopacity: 0.4, $primaryshadowcolour: #000, $lighting: $LIGHTING_CEIL) {
  $predefinedShadows: (
    0 0 5px rgba($primaryshadowcolour, 0.05),
    0 -1px 3px rgba($primaryshadowcolour, 0.2),
    0 3px 5px rgba($primaryshadowcolour, 0.2)
  );
  $value: ();

  @for $i from 1 through $depth {
    $num: $i + px;
    $num1: $i * 1.5 + px;
    $hueadjust: $i * 0.2;

    @if ($lighting == $LIGHTING_FLOOR) {
      $hueadjust: ($i * 2 - $depth - 5) * 1%;
    } @else if ($lighting == $LIGHTING_CEIL) {
      $hueadjust: -($i * 2 + $depth - 10) * 1%;
    } @else if ($lighting == $LIGHTING_FLAT) {
      $hueadjust: -$depth * 1%;
    }

    $colour: adjust-color($primary, $lightness: $hueadjust);
    $theShadow: $num1 $num 1px $colour;
    $value: append($value, $theShadow, comma);
  }

  @for $i from 1 through $shadowsteps {
    @if ($i >= length($predefinedShadows)) {
      $dist: $i * $shadowincrementer;
      $value: append($value, 0 $dist $dist rgba($primaryshadowcolour, $shadowopacity));
    } @else {
      $value: append($value, nth($predefinedShadows, $i));
    }
  }

  box-shadow: $value;
}

// Usage
.chip {
  @include box3d(#8b5cf6, 5, 3, 3px, .16);
}
@mixin box3d($primary, $depth: 5, $shadowsteps: 5, $shadowincrementer: 3px, $shadowopacity: 0.4, $primaryshadowcolour: #000, $lighting: $LIGHTING_CEIL)
  $predefinedShadows: (0 0 5px rgba($primaryshadowcolour, 0.05), 0 -1px 3px rgba($primaryshadowcolour, 0.2), 0 3px 5px rgba($primaryshadowcolour, 0.2))
  $value: ()

  @for $i from 1 through $depth
    $num: $i + px
    $num1: $i * 1.5 + px
    $hueadjust: $i * 0.2

    @if ($lighting == $LIGHTING_FLOOR)
      $hueadjust: ($i * 2 - $depth - 5) * 1%
    @else if ($lighting == $LIGHTING_CEIL)
      $hueadjust: -($i * 2 + $depth - 10) * 1%
    @else if ($lighting == $LIGHTING_FLAT)
      $hueadjust: -$depth * 1%

    $colour: adjust-color($primary, $lightness: $hueadjust)
    $theShadow: $num1 $num 1px $colour
    $value: append($value, $theShadow, comma)

  @for $i from 1 through $shadowsteps
    @if ($i >= length($predefinedShadows))
      $dist: $i * $shadowincrementer
      $value: append($value, 0 $dist $dist rgba($primaryshadowcolour, $shadowopacity))
    @else
      $value: append($value, nth($predefinedShadows, $i))

  box-shadow: $value

// Usage
.chip
  +box3d(#8b5cf6, 5, 3, 3px, .16)
.chip {
  box-shadow: 1px 1px 0 #a78bfa, 2px 2px 0 #8b5cf6, 0 10px 18px rgba(0,0,0,.12);
}
Chip mit Tiefe

Winzig, aber dokumentationswürdig, weil sie Teil der Sprache des Designsystems wird.

@function to-rem($pixels) {
  @return math.div($pixels, 16px) * 1rem;
}

// Usage
.card {
  padding: to-rem(24px);
}
@function to-rem($pixels)
  @return math.div($pixels, 16px) * 1rem

// Usage
.card
  padding: to-rem(24px)
.card {
  padding: 1.5rem;
}
Fluide Überschrift

Praktisch für responsive Abstände oder Größen über einen Viewport-Bereich, ohne die calc()-Formel für jede Eigenschaft selbst zu schreiben.

@function stripUnit($value) {
  @return $value / ($value * 0 + 1);
}

@mixin fluid(
  $min-value,
  $max-value,
  $min-vw,
  $max-vw,
  $properties...
) {
  @each $property in $properties {
    #{$property}: $min-value;
  }

  @media only screen and (min-width: #{$min-vw}) {
    @each $property in $properties {
      #{$property}: calc(#{$min-value} + #{stripUnit($max-value - $min-value)} * (100vw - #{$min-vw}) / #{stripUnit($max-vw - $min-vw)});
    }
  }

  @media only screen and (min-width: #{$max-vw}) {
    @each $property in $properties {
      #{$property}: $max-value;
    }
  }
}

// Usage
.example {
  @include fluid(20px, 40px, 320px, 1200px, padding-top, margin-bottom);
}
@function stripUnit($value)
  @return $value / ($value * 0 + 1)

@mixin fluid(
  $min-value,
  $max-value,
  $min-vw,
  $max-vw,
  $properties...
)
  @each $property in $properties
    #{$property}: $min-value

  @media only screen and (min-width: #{$min-vw})
    @each $property in $properties
      #{$property}: calc(#{$min-value} + #{stripUnit($max-value - $min-value)} * (100vw - #{$min-vw}) / #{stripUnit($max-vw - $min-vw)})

  @media only screen and (min-width: #{$max-vw})
    @each $property in $properties
      #{$property}: $max-value

// Usage
.example
  +fluid(20px, 40px, 320px, 1200px, padding-top, margin-bottom)
.example {
  padding-top: 20px;
  margin-bottom: 20px;
}

@media only screen and (min-width: 320px) {
  .example {
    padding-top: calc(20px + 20 * (100vw - 320px) / 880);
    margin-bottom: calc(20px + 20 * (100vw - 320px) / 880);
  }
}

@media only screen and (min-width: 1200px) {
  .example {
    padding-top: 40px;
    margin-bottom: 40px;
  }
}
Vorschau fluider Abstände

Nach wie vor eines der meistkopierten Mikro-Mixins in Komponentenbibliotheken und Dashboards.

@mixin ellipsis($width: 100%) {
  display: inline-block;
  max-width: $width;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

// Usage
.card-title {
  @include ellipsis(240px);
}
@mixin ellipsis($width: 100%)
  display: inline-block
  max-width: $width
  overflow: hidden
  text-overflow: ellipsis
  white-space: nowrap

// Usage
.card-title
  +ellipsis(240px)
.card-title {
  display: inline-block;
  max-width: 240px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
Das ist ein sehr langer Kartentitel, der sauber mit Auslassungspunkten gekürzt werden sollte

Ein verbreitetes Utility-Muster, weil Selektoren für eigene Scrollbars unübersichtlich sind und sich in vielen Apps wiederholen.

@mixin scrollbars($size, $thumb, $track: rgba($thumb, .2)) {
  &::-webkit-scrollbar {
    width: $size;
    height: $size;
  }

  &::-webkit-scrollbar-thumb {
    background: $thumb;
  }

  &::-webkit-scrollbar-track {
    background: $track;
  }
}

// Usage
.panel {
  @include scrollbars(10px, #111827, #e5e7eb);
}
@mixin scrollbars($size, $thumb, $track: rgba($thumb, .2))
  &::-webkit-scrollbar
    width: $size
    height: $size

  &::-webkit-scrollbar-thumb
    background: $thumb

  &::-webkit-scrollbar-track
    background: $track

// Usage
.panel
  +scrollbars(10px, #111827, #e5e7eb)
.panel::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

.panel::-webkit-scrollbar-thumb {
  background: #111827;
}

.panel::-webkit-scrollbar-track {
  background: #e5e7eb;
}
Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar. Wiederverwendbare Scrollbar-Styles halten lange Panels gut lesbar.

Nutze diesen Platzhalter für Beschriftungen oder Hilfs-UI, bei denen das Markieren von Text per Ziehen unerwünscht ist.

%noselect {
  user-select: none;
}

// Usage
.drag-label {
  @extend %noselect;
}
%noselect
  user-select: none

// Usage
.drag-label
  @extend %noselect
.drag-label {
  user-select: none;
}
Dieser Text lässt sich nicht markieren

Ein gemeinsamer Platzhalter für Text mit Verlaufsfüllung statt doppelter clip- und fill-Deklarationen.

%text-gradient {
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

// Usage
.brand-word {
  @extend %text-gradient;
  background-image: linear-gradient(135deg, #0ea5e9, #8b5cf6);
}
%text-gradient
  background-clip: text
  -webkit-background-clip: text
  -webkit-text-fill-color: transparent

// Usage
.brand-word
  @extend %text-gradient
  background-image: linear-gradient(135deg, #0ea5e9, #8b5cf6)
.brand-word {
  background-image: linear-gradient(135deg, #0ea5e9, #8b5cf6);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
Verlaufstext

Über die SCSS-Mixins-Bibliothek

Stöbere in wiederverwendbaren Sass-Mixins und -Funktionen mit Quellcode, Anwendungsbeispielen und Live-Vorschau. Kopiere jeden Helfer in dein Projekt.

Nach Zweck gruppiert

Mixins und Funktionen sind in logische Gruppen sortiert – Layout, Typografie, Responsive, Farbe, Animation und mehr. So findest du den passenden Helfer sofort.

Live-Vorschau

Sieh dir an, was jedes Mixin erzeugt, bevor du es kopierst. Die Live-Vorschau zeigt die gerenderte Ausgabe, sodass du das visuelle Ergebnis sofort erkennst.

Code & Anwendung

Jeder Eintrag zeigt die SCSS-Definition zusammen mit Anwendungsbeispielen. Kopiere den Quellcode des Mixins oder nur die include-Anweisung – ganz wie es dein Workflow verlangt.

Kopieren mit einem Klick

Kopiere jede Mixin-Definition oder jedes Anwendungs-Snippet mit einem einzigen Klick. Füge es in deine SCSS-Dateien ein und nutze es sofort – ohne manuelles Abtippen.

Häufig gestellte Fragen

Ein Mixin ist ein wiederverwendbarer Block SCSS-Code, den du einmal definierst und per @include in mehrere Selektoren einbindest. Mixins können Parameter annehmen und eignen sich dadurch flexibel für wiederkehrende CSS-Muster wie Media Queries, Flexbox-Layouts oder Animationen.

Ein Mixin gibt CSS-Deklarationen aus und wird mit @include eingebunden. Eine Funktion berechnet einen Wert (etwa eine Farbe oder Zahl), gibt ihn zurück und wird direkt im Ausdruck aufgerufen. Nutze Mixins für CSS-Blöcke und Funktionen für berechnete Werte.

Ja. Jedes Mixin ist in sich geschlossen und lässt sich in jedes SCSS-Projekt kopieren. Manche Mixins verweisen auf Variablen – ersetze sie einfach durch eigene Werte oder definiere sie in deiner Variablen-Datei.

Mixins duplizieren ihre Ausgabe überall, wo sie eingebunden sind – bei übermäßigem Einsatz wächst die Datei. Für gemeinsame Deklarationen ist @extend mit Platzhalter-Selektoren oft die bessere Wahl. Mixins eignen sich am besten für parametrische Muster, die sich je nach Einsatz unterscheiden.