Episode 7 of 12

Pseudo Classes

Handle pseudo-classes and pseudo-elements in SASS — hover, focus, before, after, and the & parent selector.

Pseudo Classes

Pseudo-classes and pseudo-elements are effortless in SASS thanks to the & (parent selector). No more repeating the selector name for every state.

Pseudo-Classes with &

// SCSS
.link {
    color: #3498db;
    text-decoration: none;
    transition: color 0.2s;

    &:hover {
        color: #2980b9;
        text-decoration: underline;
    }

    &:focus {
        outline: 3px solid rgba(52, 152, 219, 0.3);
        outline-offset: 2px;
    }

    &:active {
        color: #1a5276;
    }

    &:visited {
        color: #8e44ad;
    }
}
/* Compiled CSS */
.link { color: #3498db; text-decoration: none; transition: color 0.2s; }
.link:hover { color: #2980b9; text-decoration: underline; }
.link:focus { outline: 3px solid rgba(52, 152, 219, 0.3); outline-offset: 2px; }
.link:active { color: #1a5276; }
.link:visited { color: #8e44ad; }

Pseudo-Elements with &

.quote {
    position: relative;
    padding: 20px 30px;
    font-style: italic;
    color: #555;

    // &::before → .quote::before
    &::before {
        content: '\201C';  // Left double quote
        font-size: 60px;
        color: #3498db;
        position: absolute;
        top: -10px;
        left: 5px;
        line-height: 1;
    }

    // &::after → .quote::after
    &::after {
        content: '';
        display: block;
        width: 50px;
        height: 3px;
        background: #3498db;
        margin-top: 15px;
    }
}

Structural Pseudo-Classes

.list-item {
    padding: 12px 16px;
    border-bottom: 1px solid #eee;

    &:first-child {
        border-radius: 8px 8px 0 0;
    }

    &:last-child {
        border-bottom: none;
        border-radius: 0 0 8px 8px;
    }

    &:nth-child(even) {
        background: #f8f9fa;
    }

    &:nth-child(odd) {
        background: white;
    }

    // Only child — special styling
    &:only-child {
        border-radius: 8px;
    }
}

Form Pseudo-Classes

.input {
    border: 2px solid #ddd;
    padding: 10px 14px;
    border-radius: 6px;
    transition: border-color 0.2s;

    &:focus {
        border-color: #3498db;
        outline: none;
    }

    &:disabled {
        background: #f5f5f5;
        color: #999;
        cursor: not-allowed;
    }

    &:invalid {
        border-color: #e74c3c;
    }

    &:valid {
        border-color: #27ae60;
    }

    &::placeholder {
        color: #bbb;
        font-style: italic;
    }
}

Combining & with Classes

.button {
    background: #3498db;
    color: white;

    // Same element with extra class
    &.disabled {
        opacity: 0.5;
        cursor: not-allowed;

        &:hover {
            // Nested: .button.disabled:hover
            background: #3498db;  // Don't change on hover
        }
    }

    // Parent context
    .dark-mode & {
        // .dark-mode .button
        background: #2980b9;
        color: #ecf0f1;
    }
}

Mixin for Hover States

@mixin hover-lift($distance: -2px) {
    transition: transform 0.2s, box-shadow 0.2s;

    &:hover {
        transform: translateY($distance);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    }
}

.card { @include hover-lift; }
.button { @include hover-lift(-1px); }

Key Takeaways

  • &:hover, &:focus, &:active — pseudo-classes with the parent selector
  • &::before, &::after — pseudo-elements for decorative content
  • &:nth-child(), &:first-child, &:last-child — structural pseudo-classes
  • &.class — same element with an additional class
  • .parent & — reference the parent in a different context
  • Combine pseudo-classes with mixins for reusable hover effects