skip to Main Content

I need to reuse a css class, but change some of its properties conditionally.

For example, i’d like to merge these two classes into one to avoid having duplicated lines (my real world scenario has many more duplicated properties)

&__logo-small {
    color: $white;
    display: block;
    max-width: 3rem;

    &--link {
        display: flex;
        flex-direction: row;
        height: 3rem;
        width: 3rem;  
    }
}

&__logo-big {
    color: $white;
    display: block;
    max-width: 6rem;

    &--link {
        display: flex;
        flex-direction: row;
        height: 6rem;
        width: 6rem;  
    }
}

I find this tricky because the changes happen in different levels. If it was a sinlge level i could use inheritance, but in this case I’m stuck.

Is something like this achievable?

Edit: I’m adding a snippet of HTML for better context.

What I’m trying to do is provide support to two kind of logos.

The old format is called ‘logo’, the new format is ‘desktopLogo’. They are rendered differently.

<img *ngIf="logo" class="navbar__logo" [src]="logo" alt="logo">
<a 
  *ngIf="desktopLogo"
  class="navbar__logo"
  (click)="onItemClicked(desktopLogo)"
  [attr.id]="desktopLogo.id"
>
  <img class="navbar__logo--link" [src]="desktopLogo.icon" alt="logo">
</a>

Notice that the class navbar__logo–link only applies to the new version.

Thanks everyone for your kind answers, I made it work with Pete’s suggestion !

3

Answers


  1. My suggestion is:

    &__logo {
      color: $white;
      display: block;
      
      &-small {
        max-width: 3rem;
      }
      
      &-big {
        max-width: 6rem;
      }
      
      &--link {
        display: flex;
        flex-direction: row;    
        
        .logo-small & {
            height: 3rem;
            width: 3rem;        
        }
        
        .logo-big & {
            height: 6rem;
            width: 6rem;        
        }
      }
    }
    
    Login or Signup to reply.
  2. I think you are using your modifier wrong – the modifier in this case would be small and big.

    I would start off with a base class and then just change the bits with the modifiers

    &__logo {
      color: $white;
      display: block;
      max-width: 3rem;
      
      &-link {
        display: flex;
        flex-direction: row;
        height: 3rem;
        width: 3rem;
        
        &--big {
          height: 6rem;
          width: 6rem;
        }
      }
      
      &--big {
        max-width: 6rem;
      }
    }
    
    a normal logo would look like this:
    <a href="class__logo-link"><img class="class__logo"></a>
    
    a big logo would look like this:
    <a href="class__logo-link class__logo-link--big"><img class="class__logo class__logo--big"></a>
    

    If your html is structured like the above, you may want to only put the modifier on the link, then you can do something like this

    &__logo {
      color: $white;
      display: block;
      max-width: 3rem;
      
      &-link {
        display: flex;
        flex-direction: row;
        height: 3rem;
        width: 3rem;
        
        &--big {
          height: 6rem;
          width: 6rem;
          
          .class__logo {
             width: 6rem;
          }
        }
      }
    }
    
    a normal logo would look like this:
    <a href="class__logo-link"><img class="class__logo"></a>
    
    a big logo would look like this:
    <a href="class__logo-link class__logo-link--big"><img class="class__logo"></a>
    
    Login or Signup to reply.
  3. I may be wrong, you may have tried this already, and this may not quite be what your are asking but I hope I am on the right track. To remove some redundancy and increase reusability, you could abstract the similarities between the two classes into one logo class, and then use CSS variables to write the differences elsewhere. I am writing this in normal CSS instead due to personal preferences but feel free to adapt to SCSS:

    :root { --clr-light: #FFFFFF; }
    
    .logo:has(.logo-small) { --size-logo: 3rem; }
    .logo:has(.logo-big) { --size-logo: 6rem; }
    
    .logo {
        color: var(--clr-light);
        display: block;
        max-width: var(--size-logo);
    }
    
    .logo .link {
        display: flex;
        flex-direction: row;
        height: var(--size-logo);
        width: var(--size-logo);
    }

    A few other tips:

    • Setting heights is generally bad practice (according to Kevin Powell) but understandable here as it is an image!
    • You may want to change the .logo .link to .logo > .link if it is only wanted for a direct child.
    • I believe flex-direction: row is the default so that probably is not needed but I may be wrong!
    • .has() is not supported in some browsers still so may not be the best way to go. You can use .logo-big and .logo-small.
    • This approach might increase the number of classes you may need to add into the HTML but hopefully for the better to aid styling.

    I hope this helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search