---
title: 'Storefront: Styling With SCSS and Bootstrap | Shopware Community Hub'
description: >-
  Learn how to override Bootstrap and Shopware styling using SCSS variables, CSS
  variables, and mixins, and apply Bootstrap best practices for maintainable…
canonical_url: 'https://hub.shopware.com/learn/unit/storefront-styling-with-scss-and-bootstrap'
---

# Storefront: Styling With SCSS and Bootstrap

<LearningObjectives>

- Override Bootstrap and Shopware SCSS variables to customize the storefront styling.
- Customize individual components using scoped CSS variables without affecting global design decisions.
- Use SCSS mixins, especially Bootstrap breakpoint mixins, to implement responsive styling.
- Apply Bootstrap-first styling practices to reduce custom SCSS and improve long-term maintainability.
- Explain where Bootstrap styling ends and Shopware storefront behavior begins.

</LearningObjectives>

# Storefront: Styling With SCSS and Bootstrap

Shopware’s storefront is built on top of Bootstrap. That means you can usually get far with:

- **Bootstrap utilities** (spacing, display, flex, grid)
- **SCSS variables** (design tokens such as colors, border radii, spacing)
- **SCSS mixins** (especially breakpoint helpers)

In this learning unit, you will learn where to place overrides, how to write responsive SCSS in a maintainable way, and when to prefer Bootstrap utilities over custom CSS.

<Callout title="Bootstrap Is the Styling Foundation" type="info">

Shopware uses Bootstrap as a styling foundation. You can rely on Bootstrap utilities, SCSS variables, mixins, and layout concepts.

However, the storefront is not a plain Bootstrap project. Interactive behavior is usually handled by Shopware's storefront JavaScript plugins and Shopware's own component structure. Use Bootstrap-first thinking for styling, but do not assume that every Bootstrap JavaScript component works exactly like it does in a standalone Bootstrap project.

</Callout>

## Overriding Bootstrap Variables with SCSS

Shopware’s storefront theme is built on top of Bootstrap. SCSS variables control many global design decisions (e.g., colors, spacing, border radius).

### Where to Override Variables

If you want to override Bootstrap or Shopware SCSS variables, you must do it **before** the main storefront styles are loaded.

That’s why themes usually have a dedicated entry file, the `overrides.scss` file. This file is loaded before `@Storefront` in `theme.json`.

```json
{
  "name": "MyChildTheme",
  "author": "Your Name",
  "views": [ ... ],
  "style": [
    "app/storefront/src/scss/overrides.scss", // <-- overrides.scss is loaded before @Storefront
    "@Storefront",
    "app/storefront/src/scss/base.scss"
  ]
}
```

### Example: Override Variables

Put your SCSS variable overrides in `overrides.scss`. You can redefine any variable defined in Bootstrap or Shopware.

```scss
// app/storefront/src/scss/overrides.scss

$primary: #0055ff;
$border-radius: 0.5rem;
```

Use this file only for variable overrides. Avoid writing custom CSS in it.

**Rule of thumb:**

- The `overrides.scss` file is used to override SCSS variables (global design decisions).
- The `base.scss` file is used for small global rules and imports for your own component SCSS files.

## Overriding Bootstrap Components with CSS Variables

Many Bootstrap components (including Shopware’s Storefront components) provide **CSS variables** that control spacing, colors, and sizing.

These variables allow you to customize a single component without changing the global styling.

In practice, you often set CSS variables in SCSS files. SCSS will compile them into regular CSS **custom properties** (the `--...` variables) which exist at runtime in the browser.

### Example: Adjust Button Padding Without Affecting All Buttons

Assume you want a custom button variant based on Bootstrap’s `.btn`, but with different padding.

```twig
<button class="btn my-button">Button text</button>
```

In SCSS, you can override Bootstrap’s button CSS variables **only for that element**:

```scss
.my-button { // <-- your custom class
  // Bootstrap uses $prefix (default: "bs-") for CSS variables.
  // This compiles to: --bs-btn-padding-x / --bs-btn-padding-y
  --#{$prefix}btn-padding-x: 1rem; // left + right
  --#{$prefix}btn-padding-y: 0.25rem; // top + bottom
}
```

You can also use the plain CSS version:

```css
.my-button {
  --bs-btn-padding-x: 1rem;
  --bs-btn-padding-y: 0.25rem;
}
```

CSS variables can also be referenced using the standard CSS [`var()` function](https://www.w3schools.com/css/css3_variables.asp). This is useful when you want to reuse an existing variable inside your own styling.

```css
.my-button {
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
}
```

This approach lets you create component-specific variants without affecting other buttons or global design variables.

<Callout title="Common Pitfall" type="warning">

Don’t write `--#{$prefix}-btn-padding-x`. The `$prefix` already contains the trailing dash (`bs-`), so adding another `-` would produce an incorrect variable name.

</Callout>

<Callout title="Tip" type="info">

Prefer scoped CSS variable overrides for component variants (e.g., one specific button), and prefer variable overrides in `overrides.scss` for global design decisions (e.g., changing the primary brand color).

</Callout>

## Mixins and Responsive Breakpoints

SCSS mixins are reusable styling helpers. In storefront development, they are often used to implement responsive behavior.

Bootstrap already provides breakpoint mixins, so you usually do not need to write custom media queries.

Bootstrap defines the following breakpoints:

- `xs`: 0 up to 575px
- `sm`: 576px up to 767px
- `md`: 768px up to 991px
- `lg`: 992px up to 1199px
- `xl`: 1200px up to 1399px
- `xxl`: 1400px and above

And provides several helper mixins:

- `@include media-breakpoint-up(breakpoint)`
- `@include media-breakpoint-down(breakpoint)`
- `@include media-breakpoint-between(min, max)`
- `@include media-breakpoint-only(breakpoint)`

You can still use regular CSS media queries if you need custom ranges:

- `@media (min-width: 500px)`
- `@media (max-width: 800px)`
- `@media (min-width: 400px) and (max-width: 1200px)`

### Example: Responsive Adjustments

```scss
// app/storefront/src/scss/base.scss

.my-banner {
  padding: 8px 12px;

  @include media-breakpoint-up(md) {
    padding: 16px 24px;
  }

  @include media-breakpoint-down(sm) {
    text-align: center;
  }
}
```

### Example: Targeting Specific Ranges (`between` / `only`)

```scss
.my-sidebar {
  // Example: only adjust between md and lg
  @include media-breakpoint-between(md, lg) {
    margin-top: 16px;
  }

  // Example: only adjust on xl
  @include media-breakpoint-only(xl) {
    margin-top: 0;
  }
}
```

Using Bootstrap's breakpoint mixins helps you:

- Keep breakpoints consistent across themes and plugins.
- Avoid duplicated breakpoint definitions.
- Maintain responsive styling more easily.

If you want to dive deeper into media queries, check out the [Bootstrap documentation](https://getbootstrap.com/docs/5.3/layout/breakpoints/).

## Conditionals in SCSS (`@if`, `@else`)

SCSS conditionals are evaluated **at compile time**. This means that only the matching branch is written into the final compiled CSS.

Conditionals are useful when you want to build different theme variants (e.g., comfortable vs. compact spacing) from the same codebase without duplicating code.

### Example: A Feature Flag

A common pattern is defining a variable once and using `@if` to include or exclude styling.

`!default` means: “use this value unless another file overrides it earlier.”

You can define the flag directly in `overrides.scss`:

```scss
// app/storefront/src/scss/overrides.scss
$footer-hide-link-hover-color: false !default;
```

You can also expose the same idea through theme configuration. In that case, the value can be changed in the administration instead of being hardcoded in SCSS.

```json
{
  "name": "MyChildTheme",
  "config": {
    "fields": {
      "footer-hide-link-hover-color": {
        "type": "bool",
        "value": false,
        "label": {
          "en-GB": "Hide footer link hover color",
          "de-DE": "Footer-Link-Hover-Farbe ausblenden"
        },
        "editable": true
      }
    }
  }
}
```

```scss
// app/storefront/src/scss/base.scss (or a footer component SCSS)
.footer-link-item {
  // You can write `@if $flag` instead of `@if (true == $flag)`
  @if $footer-hide-link-hover-color {
    // Flag ON: keep links “neutral” (inherit color, no dedicated hover color)
    .footer-link {
      color: inherit;
    }
  } @else {
    // Flag OFF: use explicit link colors + explicit hover color
    .footer-link {
      color: $sw-footer-text-color;
    }

    .footer-link:hover {
      color: $sw-footer-link-hover-color;
    }
  }
}
```

This allows the same theme code to compile either with or without the hover color styling.

### Conditional Logic Inside Mixins

Conditionals are often used inside mixins to enable optional styling behavior.

**Example One**

```scss
// Definition
@mixin sidemenu-sticky-filter($show) {
  @if $show {
    position: fixed;
    top: 10px;
  }
}

// Usage
.my-filter {
  // You could pass a variable here instead of `true`
  @include sidemenu-sticky-filter(true);
}
```

**Example Two**

```scss
// Definition
@mixin category-sidebar-fade($show) {
  @if $show {
    content: "";
    position: absolute;
    inset: auto 0 0 0; // bottom overlay, full width
    height: 3rem;
    background: linear-gradient(transparent, rgba(255, 255, 255, 1));
  }
}

// Usage
.category-sidebar {
  position: relative;

  &::after {
    // Adds a fade overlay at the bottom (useful for “scroll hint” UIs)
    @include category-sidebar-fade(true);
  }
}
```

In these two examples, conditional CSS is generated based on a variable. If `$show` is `true`, the mixin generates the corresponding CSS, otherwise not.

### Practical Example: Guarding a Brand Color

Conditionals can also be used to adjust styling automatically if a specific value is problematic.

```scss
$brand-link-color: $primary !default;

.content a {
  color: $brand-link-color;

  // If the link color is pure yellow, use a readable fallback
  @if $brand-link-color == #ffff00 {
    color: $my-shop-global-link-color-black;
  }
}
```

This ensures links remain readable even if the selected brand color is difficult to read.

<Callout title="Important" type="info">

Conditionals are evaluated during compilation. If you want to change the behavior (e.g., user interaction), use storefront JavaScript or different CSS classes.

</Callout>

If you want to dive deeper into flow control in SCSS, check out the [SASS documentation](https://sass-lang.com/documentation/at-rules/control/).

## Best Practices and Debugging Workflow

When customizing the storefront styling, follow a consistent workflow to keep your styling maintainable and predictable.

### Step 1: Choose the Right Customization Level

When you want to change styling, always start with the most stable approach:

- **Global design decisions**: Override SCSS variables in `overrides.scss`.
- **Utilities-first (layout and spacing adjustments)**: Use Bootstrap utilities directly in Twig to reduce custom CSS if possible.
- **Selector-first (component-specific styling)**: Write scoped selectors in a component SCSS file instead of large global rules.

### Step 2: Follow Styling Best Practices

The following guidelines help you avoid unnecessary custom styling and reduce long-term maintenance.

- Prefer utilities in Twig over custom one-off CSS rules.
- Keep selectors shallow to avoid specificity problems.
- Avoid `!important` where possible.
- Prefer variable-level overrides instead of copying full component CSS.

### Step 3: Debug Styling Changes

If styling changes do not behave as expected, check the following:

- Inspect the element in browser DevTools and check which selector wins.
- Verify that the expected breakpoint is currently active.
- Confirm that the correct class is applied to the element.
- Ensure variable overrides are placed in the `overrides.scss` file.
- Use the classic project script `bin/watch-storefront.sh` to watch for changes during development. Shopware CLI equivalent: `shopware-cli project storefront-watch`.
- Run `bin/console theme:compile` manually after making changes if you are not using a watcher.

## Troubleshooting Checklist

If you encounter any issues while customizing the storefront styling, check the following list for common problems and solutions:

- **Variable override has no effect**: Ensure the override file is loaded before `@Storefront`.
- **Responsive mixin doesn't do anything**: Ensure the SCSS file is imported and compiled.
- **Changes don't show up**: Clear the cache with `bin/console cache:clear` and recompile the theme.

## Summary

In this learning unit, you learned how to:

- Override global storefront styling using SCSS variables and place overrides in `overrides.scss`.
- Customize individual components using CSS variables without affecting global design decisions.
- Use Bootstrap breakpoint mixins to implement responsive styling consistently.
- Apply SCSS conditionals to create optional styling behavior.
- Understand that Bootstrap is the styling foundation, while storefront behavior is still Shopware-specific.
- Follow a structured customization and debugging workflow to keep storefront styling maintainable and predictable.

With this knowledge, you can implement maintainable storefront styling changes by choosing the right customization level (variables, utilities or component-level overrides) for each use case.
