SASS/SCSS

The Parent Selector (&)

20 min Lesson 6 of 30

The Parent Selector (&) in SASS

The parent selector (&) is one of SASS's most powerful and frequently used features. It allows you to reference the parent selector in nested rules, enabling you to write more concise and maintainable CSS. Understanding the parent selector is crucial for mastering SASS.

What is the Parent Selector (&)?

The ampersand (&) in SASS represents the parent selector in nested rules. When SASS compiles your code, it replaces & with the actual parent selector. This allows you to create complex selectors without repeating yourself.

Basic Parent Selector Example

// SCSS
.button {
  background: blue;
  color: white;

  &:hover {
    background: darkblue;
  }
}

// Compiled CSS
.button {
  background: blue;
  color: white;
}

.button:hover {
  background: darkblue;
}
Note: The & is replaced with the exact parent selector, including any classes, IDs, or other selectors. It doesn't just add a space—it directly concatenates.

Using & with Pseudo-Classes

One of the most common uses of the parent selector is with pseudo-classes like :hover, :focus, :active, :visited, and more. This keeps related states together in your code.

Multiple Pseudo-Classes

// SCSS
.link {
  color: blue;
  text-decoration: none;
  transition: all 0.3s ease;

  &:hover {
    color: darkblue;
    text-decoration: underline;
  }

  &:focus {
    outline: 2px solid blue;
    outline-offset: 2px;
  }

  &:active {
    color: navy;
    transform: translateY(1px);
  }

  &:visited {
    color: purple;
  }
}

// Compiled CSS
.link {
  color: blue;
  text-decoration: none;
  transition: all 0.3s ease;
}

.link:hover {
  color: darkblue;
  text-decoration: underline;
}

.link:focus {
  outline: 2px solid blue;
  outline-offset: 2px;
}

.link:active {
  color: navy;
  transform: translateY(1px);
}

.link:visited {
  color: purple;
}

Using & with Pseudo-Elements

The parent selector works seamlessly with pseudo-elements (::before, ::after, ::first-letter, etc.). This is perfect for adding decorative elements or icons.

Pseudo-Elements Example

// SCSS
.quote {
  position: relative;
  padding: 20px 40px;
  font-style: italic;

  &::before {
    content: """;
    position: absolute;
    left: 10px;
    top: 0;
    font-size: 60px;
    color: #ccc;
    font-family: Georgia, serif;
  }

  &::after {
    content: """;
    position: absolute;
    right: 10px;
    bottom: -40px;
    font-size: 60px;
    color: #ccc;
    font-family: Georgia, serif;
  }
}

// Compiled CSS
.quote {
  position: relative;
  padding: 20px 40px;
  font-style: italic;
}

.quote::before {
  content: """;
  position: absolute;
  left: 10px;
  top: 0;
  font-size: 60px;
  color: #ccc;
  font-family: Georgia, serif;
}

.quote::after {
  content: """;
  position: absolute;
  right: 10px;
  bottom: -40px;
  font-size: 60px;
  color: #ccc;
  font-family: Georgia, serif;
}

BEM (Block Element Modifier) Naming Convention

The parent selector is perfect for writing BEM-style CSS. BEM is a naming methodology that helps you create reusable components and avoid naming conflicts.

BEM Structure: Block__Element--Modifier. For example: .card__title--large

BEM with Parent Selector

// SCSS
.card {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);

  // Element: card__header
  &__header {
    border-bottom: 1px solid #eee;
    margin-bottom: 15px;
    padding-bottom: 15px;
  }

  // Element: card__title
  &__title {
    font-size: 24px;
    font-weight: bold;
    margin: 0;
    color: #333;

    // Modifier: card__title--small
    &--small {
      font-size: 18px;
    }

    // Modifier: card__title--large
    &--large {
      font-size: 32px;
    }
  }

  // Element: card__body
  &__body {
    color: #666;
    line-height: 1.6;
  }

  // Element: card__footer
  &__footer {
    margin-top: 15px;
    padding-top: 15px;
    border-top: 1px solid #eee;
  }

  // Modifier: card--featured
  &--featured {
    border: 3px solid gold;
    box-shadow: 0 4px 12px rgba(255,215,0,0.3);
  }

  // Modifier: card--dark
  &--dark {
    background: #333;
    color: white;

    .card__title {
      color: white;
    }

    .card__body {
      color: #ccc;
    }
  }
}

// Compiled CSS
.card {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.card__header {
  border-bottom: 1px solid #eee;
  margin-bottom: 15px;
  padding-bottom: 15px;
}

.card__title {
  font-size: 24px;
  font-weight: bold;
  margin: 0;
  color: #333;
}

.card__title--small {
  font-size: 18px;
}

.card__title--large {
  font-size: 32px;
}

/* ... and so on ... */

Using & with Sibling Combinators

The parent selector can be used with sibling combinators (+, ~) to style elements based on their siblings. This is useful for creating spacing systems or styling lists.

Adjacent Sibling Combinator (+)

// SCSS
.item {
  padding: 10px;
  border-bottom: 1px solid #ddd;

  // Style items that come right after another item
  & + & {
    margin-top: 10px;
  }
}

// Compiled CSS
.item {
  padding: 10px;
  border-bottom: 1px solid #ddd;
}

.item + .item {
  margin-top: 10px;
}

General Sibling Combinator (~)

// SCSS
.alert {
  padding: 15px;
  border-radius: 4px;
  margin-bottom: 10px;

  // Style all alerts after the first one
  & ~ & {
    opacity: 0.8;
  }

  &.alert-error {
    background: #fee;
    border: 1px solid #fcc;
    color: #c33;
  }

  &.alert-success {
    background: #efe;
    border: 1px solid #cfc;
    color: #3c3;
  }
}

// Compiled CSS
.alert {
  padding: 15px;
  border-radius: 4px;
  margin-bottom: 10px;
}

.alert ~ .alert {
  opacity: 0.8;
}

.alert.alert-error {
  background: #fee;
  border: 1px solid #fcc;
  color: #c33;
}

.alert.alert-success {
  background: #efe;
  border: 1px solid #cfc;
  color: #3c3;
}

Appending to Parent (Suffixes)

You can append strings to the parent selector by placing & before the text. This is useful for creating variations or state classes.

Suffix Pattern

// SCSS
.button {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;

  // Creates .button-primary
  &-primary {
    background: blue;
    color: white;
  }

  // Creates .button-secondary
  &-secondary {
    background: gray;
    color: white;
  }

  // Creates .button-large
  &-large {
    padding: 15px 30px;
    font-size: 18px;
  }

  // Creates .button-small
  &-small {
    padding: 5px 10px;
    font-size: 12px;
  }
}

// Compiled CSS
.button {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.button-primary {
  background: blue;
  color: white;
}

.button-secondary {
  background: gray;
  color: white;
}

.button-large {
  padding: 15px 30px;
  font-size: 18px;
}

.button-small {
  padding: 5px 10px;
  font-size: 12px;
}

Parent Selector in Compound Selectors

The parent selector can be combined with other selectors to create complex rules. This is useful for styling based on parent states or contexts.

Context-Based Styling

// SCSS
.nav-item {
  padding: 10px 15px;
  color: #333;

  // When inside .navbar-dark
  .navbar-dark & {
    color: white;
  }

  // When inside .sidebar
  .sidebar & {
    display: block;
    border-bottom: 1px solid #eee;
  }

  // When body has .mobile class
  body.mobile & {
    padding: 15px;
    font-size: 16px;
  }
}

// Compiled CSS
.nav-item {
  padding: 10px 15px;
  color: #333;
}

.navbar-dark .nav-item {
  color: white;
}

.sidebar .nav-item {
  display: block;
  border-bottom: 1px solid #eee;
}

body.mobile .nav-item {
  padding: 15px;
  font-size: 16px;
}
Tip: When & appears anywhere except at the beginning of a selector, it represents the parent selector at that position. This is incredibly useful for theming and context-specific styling.

Advanced Parent Selector Patterns

Multiple Parent References

// SCSS
.button {
  background: blue;
  color: white;
  padding: 10px 20px;

  &:hover {
    background: darkblue;
  }

  &:active,
  &:focus {
    outline: 2px solid lightblue;
    outline-offset: 2px;
  }

  // Disabled state
  &[disabled],
  &.disabled,
  &:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
  }

  // When button is inside a form that's submitting
  .form--submitting & {
    opacity: 0.6;

    &::after {
      content: "...";
      margin-left: 5px;
    }
  }
}

// Compiled CSS includes all these variations...

Common Pitfalls and Gotchas

Warning: The parent selector cannot be used to create new parent selectors in the middle of a compound selector. For example, .foo & .bar doesn't work as you might expect.

What NOT to Do

// WRONG - This won't work
.parent {
  .child & .grandchild {
    // Error: Parent selector can't be used here
  }
}

// CORRECT - Put & at the start or end
.parent {
  .outer & {
    .grandchild {
      // This works
    }
  }
}

Order Matters

// SCSS
.button {
  // This creates .button:hover.active
  &:hover&.active {
    background: green;
  }

  // This creates .button.active:hover
  &.active&:hover {
    background: red;
  }
}

// In CSS, these are actually equivalent,
// but being aware of the order helps readability

Real-World Example: Navigation Menu

Complete Navigation Component

// SCSS
.nav {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  background: #333;

  &__item {
    position: relative;

    // Add separator between items
    & + & {
      &::before {
        content: "";
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        height: 20px;
        width: 1px;
        background: rgba(255,255,255,0.2);
      }
    }
  }

  &__link {
    display: block;
    padding: 15px 20px;
    color: white;
    text-decoration: none;
    transition: all 0.3s ease;

    &:hover {
      background: rgba(255,255,255,0.1);
      color: #ffd700;
    }

    &:focus {
      outline: 2px solid #ffd700;
      outline-offset: -2px;
    }

    &--active {
      background: rgba(255,255,255,0.15);
      font-weight: bold;

      &::after {
        content: "";
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        height: 3px;
        background: #ffd700;
      }
    }
  }

  &--vertical {
    flex-direction: column;

    .nav__item + .nav__item::before {
      display: none;
    }

    .nav__link {
      border-bottom: 1px solid rgba(255,255,255,0.1);
    }
  }

  &--light {
    background: white;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);

    .nav__link {
      color: #333;

      &:hover {
        background: #f5f5f5;
        color: blue;
      }

      &--active::after {
        background: blue;
      }
    }
  }
}

// Usage in HTML:
// <nav class="nav">
//   <div class="nav__item">
//     <a href="#" class="nav__link nav__link--active">Home</a>
//   </div>
//   <div class="nav__item">
//     <a href="#" class="nav__link">About</a>
//   </div>
// </nav>

Exercise 1: Create a Card Component with Parent Selector

Create a card component using the parent selector that includes:

  • Base .card class with padding and border
  • BEM elements: __header, __title, __body, __footer
  • Modifiers: --featured (with gold border), --compact (less padding)
  • Hover state that lifts the card slightly
  • Use sibling combinator to add spacing between multiple cards

Exercise 2: Build a Button System

Create a comprehensive button system with:

  • Base .btn class
  • Variants using suffix pattern: -primary, -secondary, -danger, -success
  • Sizes using BEM modifiers: --small, --large
  • States: :hover, :active, :focus, :disabled
  • Loading state using parent selector and ::after pseudo-element

Exercise 3: Theme-Aware Component

Create a component that adapts to different themes:

  • Create a .message component
  • Use parent selector to style differently when inside .theme-dark
  • Use parent selector to style differently when inside .theme-light
  • Add icon using ::before pseudo-element
  • Include variants for success, error, and warning messages