Variables & Tokens
The Guppy theme uses a deliberate SCSS architecture on top of Bootstrap 5, complemented by custom functions, mixins, and token sets. This page is the full developer reference.
Directory layout
src/Resources/app/storefront/src/scss/
├── overrides.scss # theme hook, loads before @DmfGuppyTheme
├── base.scss # theme hook, loads after @DmfGuppyTheme
├── abstract/
│ ├── functions/
│ │ ├── boolean.scss
│ │ ├── px-to-rem.scss
│ │ └── strip-unit.scss
│ ├── mixins/
│ │ ├── button-adaptive-hover.scss
│ │ ├── focus-style.scss
│ │ └── rlh.scss
│ └── variables/
│ ├── bootstrap.scss
│ └── custom.scss
├── base/ # accessibility, container, typography
├── components/ # buttons, cards, forms, slider, …
├── elements/ # skip-link, splide-slider
├── layout/ # header, footer, USP, navigation, …
├── page/ # account, checkout, detail, …
└── skin/shopware/ # integration with the default Shopware storefront
├── abstract/variables/
│ ├── bootstrap.scss
│ ├── custom.scss
│ └── theme.scss
├── base.scss
├── base/ # base.scss, inter-fontface.scss
└── component/ # cms-block, cms-element, modal, …Build order
theme.json defines the compile order:
{
"style": [
"app/storefront/src/scss/overrides.scss",
"@StorefrontBootstrap",
"@Plugins",
"app/storefront/src/scss/skin/shopware/base.scss",
"app/storefront/src/scss/base.scss"
]
}Order matters: overrides.scss loads before Bootstrap, it's where early variable overrides go; base.scss loads after everything and contains the final selector styles.
Functions
px-to-rem($px, $base-font-size: 16px)
@function px-to-rem($px, $base-font-size: 16px) {
@return ($px / $base-font-size) * 1rem;
}
.element {
font-size: px-to-rem(18px); // 1.125rem
padding: px-to-rem(24px); // 1.5rem
}strip-unit($value)
@function strip-unit($value) {
@return ($value / ($value * 0 + 1));
}
$value: strip-unit(100px); // 100Bootstrap color functions (available)
shade-color($color, $weight) // darker
tint-color($color, $weight) // lighter
shift-color($color, $weight) // automatic (based on lightness)Mixins
rlh($value) and line-height($value)
Responsive line heights via Bootstrap RFS:
h1 { @include line-height(1.2); }
.title { @include rlh(1.5, line-height); }focus-style
Consistent focus styles for accessibility:
@mixin focus-style {
outline-offset: $focus-outline-offset;
outline: $focus-outline-color solid $focus-outline-width;
box-shadow: $focus-outline-box-shadow;
}
button:focus-visible { @include focus-style; }button-adaptive-hover($base-color)
Hover effects only when the device truly supports hover:
@mixin button-adaptive-hover($base-color) {
&:hover {
@media (hover: hover) {
background-color: shade-color($base-color, 15%);
}
}
}text-ellipsis and text-clamp($lines)
@mixin text-ellipsis { /* single line */ }
@mixin text-clamp($lines: 2) { /* multi line */ }visually-hidden
Screen-reader-only content:
.sr-only { @include visually-hidden; }Bootstrap variables (excerpt)
The most important token families from abstract/variables/bootstrap.scss. They bind to $sw-* tokens, which in turn are populated from the theme configuration.
// Colors
$gray-100: $sw-color-gray-100 !default;
$gray-900: $sw-color-gray-900 !default;
// Typography
$font-size-base: $sw-font-size-base !default;
$h1-font-size: $sw-h1-font-size !default;
// Container and grid
$container-max-widths: (xs: $guppy-container-width-default) !default;
$grid-gutter-width: 1.5rem !default;
// Buttons and inputs
$btn-font-size: $sw-input-btn-font-size !default;
$btn-border-radius: $sw-input-btn-border-radius !default;
$btn-font-weight: $sw-input-btn-font-weight !default;Custom variables (excerpt)
Guppy-specific tokens in abstract/variables/custom.scss:
// Icons
$icon-base-size: 22px !default;
$icon-base-color: currentColor !default;
$icon-accessibility-touch-size: 44px !default;
// Product images
$product-image-height: 240px !default;
$product-image-aspect-ratio: #{10/9} !default;
$product-image-background: $sw-color-product-image !default;
// Accessibility
$focus-outline-width: 2px !default;
$focus-outline-color: $sw-color-brand-primary !default;
$focus-outline-offset: 2px !default;
$focus-outline-box-shadow: 0 0 0 2px #fff;
// Delivery status
$guppy-delivery-shipping-free-color: #023B5A;
$guppy-delivery-shipping-free-background: #CEEDFE;
$guppy-delivery-available-color: #154634;
$guppy-delivery-available-background: #D3F2E7;
$guppy-delivery-restock-color: #5D3B00;
$guppy-delivery-restock-background: #FFEFD4;
$guppy-delivery-soldout-color: #303030;
$guppy-delivery-soldout-background: #EEEEEE;Token tables
Brand colors
| Variable | Default | Use |
|---|---|---|
$sw-color-brand-primary | #215AFF | Primary |
$sw-color-brand-secondary | #0B1845 | Secondary |
$sw-background-color | #FFFFFF | Background |
$sw-border-color | #CFD1D7 | Borders |
$sw-text-color | #1B1F29 | Text color |
$sw-headline-color | #1B1F29 | Headlines |
Greyscales
| Variable | Default | Use |
|---|---|---|
$sw-color-gray-100 | #F9F9F9 | Backgrounds, footer |
$sw-color-gray-200 | #EEEEEE | Disabled elements |
$sw-color-gray-300 | #BCC1C7 | Borders, dividers |
$sw-color-gray-400 | #CED4DA | Input borders |
$sw-color-gray-500 | #ADB5BD | Placeholders |
$sw-color-gray-600 | #798490 | Secondary text |
$sw-color-gray-700 | #495057 | Text |
$sw-color-gray-800 | #4A545B | Headlines |
$sw-color-gray-900 | #212529 | Body text |
Typography
| Variable | Default | Use |
|---|---|---|
$sw-font-size-base | 1rem | Base font size |
$sw-h1-font-size | 32px | H1 |
$sw-h2-font-size | 24px | H2 |
$sw-h3-font-size | 20px | H3 |
$sw-h4-font-size | 18px | H4 |
$sw-h5-font-size | 16px | H5 |
$sw-h6-font-size | 15px | H6 |
$sw-h1-line-height | 44px | H1 line height |
$sw-h2-line-height | 36px | H2 line height |
$sw-h3-line-height | 32px | H3 line height |
Accessibility
| Variable | Default | Use |
|---|---|---|
$focus-outline-width | 2px | Focus outline width |
$focus-outline-color | $sw-color-brand-primary | Focus outline color |
$focus-outline-offset | 2px | Distance from element |
$focus-outline-box-shadow | 0 0 0 2px #fff | Additional shadow |
$icon-accessibility-touch-size | 44px | Min. touch target |
Container and breakpoints
Standard Bootstrap breakpoints:
| Breakpoint | Class infix | Dimension | Container max-width |
|---|---|---|---|
| Extra small | – | < 576 px | 100 % |
| Small | sm | ≥ 576 px | 540 px |
| Medium | md | ≥ 768 px | 720 px |
| Large | lg | ≥ 992 px | 960 px |
| Extra large | xl | ≥ 1200 px | 1140 px |
| XXL | xxl | ≥ 1400 px | 1320 px |
Guppy container padding per breakpoint:
$guppy-container-default-padding-x-mobile: 10px;
$guppy-container-default-padding-x-sm: 24px;
$guppy-container-default-padding-x-md: 48px;
$guppy-container-default-padding-x-lg: 48px;
$guppy-container-default-padding-x-xl: 48px;
$guppy-container-default-padding-x-xxl: 48px;Breakpoint mixins:
@include media-breakpoint-up(md) { /* ≥ 768 px */ }
@include media-breakpoint-down(lg) { /* < 992 px */ }
@include media-breakpoint-between(md, xl) { /* 768–1199 px */ }
@include media-breakpoint-only(lg) { /* 992–1199 px */ }Child theme overrides
In a child theme:
// overrides.scss, variable overrides
$guppy-usp-background-color: #f8f9fa !default;
$product-image-height: 300px !default;
$primary: #007bff !default;// base.scss, additional styles
.my-custom-component {
background-color: $primary;
.title { @include line-height(1.3); }
}Don't break the order
Variables must be set in overrides.scss (loads before Bootstrap), in base.scss they apply too late.
Best practices
Theme variables instead of hardcodes
// good
.custom-component {
color: $sw-text-color;
background-color: $sw-color-gray-100;
}
// bad
.custom-component {
color: #333;
background-color: #f9f9f9;
}Bootstrap breakpoints instead of custom media queries
// good
@include media-breakpoint-up(md) { display: flex; }
// bad
@media (min-width: 768px) { display: flex; }Focus styles via mixin
// good
.custom-button:focus-visible { @include focus-style; }
// bad
.custom-button:focus { outline: 2px solid blue; }Debugging
@debug "Container width: #{$guppy-container-width-default}";
@debug "Primary color: #{$sw-color-brand-primary}";Practical example
// _my-component.scss
.my-component {
background-color: $sw-color-gray-100;
border: 1px solid $sw-border-color;
border-radius: $border-radius;
padding: $spacer;
.title {
font-size: $sw-h3-font-size;
@include line-height($h3-line-height);
color: $sw-headline-color;
}
@include media-breakpoint-up(md) {
display: flex;
gap: $spacer * 2;
}
&:focus-visible { @include focus-style; }
.action-button {
@include button-reset;
@include button-adaptive-hover($sw-color-brand-primary);
}
}Related
- Architecture: folder structure and inheritance order.
- Twig Overrides: consume theme config in templates.
- Theme Variables Reference: lookup table for
theme.jsonfields.