Can anyone suggest a more efficient approach to handling variations using CSS?

Within the message component, there are currently only two variants available: error and success.

This project is built using vue3 script setup and utilizes SCSS for styling.

<script setup lang="ts">
defineOptions({
  name: 'NotificationMessage',
})

withDefaults(defineProps<{ variant?: string }>(), { variant: 'success' })
</script>

<template>
  <div :class="`notifications-message notifications-message--${variant}`">
    <div class="tw-flex tw-flex-row tw-items-center tw-gap-4">
      <span class="notifications-message__icon material-symbols-outlined"> check_circle </span>
      <div>message</div>
    </div>
    <span class="tw-red-primary tw-text-xl material-symbols-outlined"> close </span>
    <div class="notifications-message__loader" />
  </div>
</template>

<style lang="scss" scoped>
@keyframes widthIncrease {
  100% {
    width: 100%;
  }
}
.notifications-message {
  @apply tw-w-64 tw-pt-2 tw-pb-3 tw-px-4 tw-flex tw-flex-row tw-justify-between tw-items-center;
  color: #6a5d6a;
  word-wrap: break-word;
  display: flex;
  border-radius: 4px;
  max-width: 100%;
  box-shadow: 0 0 3px 1px $blue-secondary;
  background-color: $white-primary;

  &--success {
    .notifications-message {
      &__icon {
        color: $green-primary;
      }

      &__loader {
        background-color: $green-primary;
      }
    }
  }

  &--error {
    .notifications-message {
      &__icon {
        color: $red-primary;
      }

      &__loader {
        background-color: $red-primary;
      }
    }
  }

  &__loader {
    @apply tw-absolute tw-bottom-0 tw-left-0 tw-w-0 tw-h-1 tw-rounded-bl-md tw-rounded-br-md;
    animation: widthIncrease 4s linear forwards;
  }
}
</style>

Is there a way to assign styles directly based on the parent class variant?

The :has() selector allows us to apply certain styles only if the parent contains specific elements.

Can we achieve something similar with a child element in order to avoid repetition?

For example:

.notifications-message {
// ....
 &__icon {
    
    // Apply green primary color if notifications-message contains class --success 
      color: $green-primary;
    

    // Apply red primary color if notifications-message contains class --error 
      color: $red-primary;
    
 }
}

Answer №1

There isn't a one-size-fits-all solution. Each developer has their own preferred method, and most of them have some merit. The best approach depends on the specific use case and the extent of changes needed in each variation.

In your situation, I recommend utilizing CSS properties since you are using the same color for every overwritten property in each variant. However, if you were to change multiple options with different values (e.g., 3 properties with varying shades of color), then your current method may be more suitable.

For example:

.notifications-message {
    --notification-color: gray;
    color: var(--notification-color);
    border: 1px solid var(--notification-color);
    box-shadow: 0 2px 10px var(--notification-color);
    margin-bottom: 1rem;
    padding: .5rem;
}

.notifications-message.notifications-message--success {
    --notification-color: green;
}

.notifications-message.notifications-message--error {
    --notification-color: red;
}
<div class="notifications-message">default</div>
<div class="notifications-message notifications-message--success">success</div>
<div class="notifications-message notifications-message--error">error</div>

Regarding the use of :has(), I strongly advise against using it, at least for now. While it is supported in any browser running webkit, Mozilla is hesitant to implement it without enabling optional features in the browser.
Learn more about the compatibility of :has()
Further information can be found here

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating uniform URLs using MVC .NET routing: a guide

While using ASP.Net MVC 5 in .NET Framework 4.8, I am constantly facing a 404 error due to inconsistent URL generation. For instance, when including the _PageNav.chstml partial at the top of each page and adding @Url.Action("Index", new { controller = "Hom ...

The pictures are not showing up in the photo album

I am currently in the process of building a swim image gallery inspired by the Flex Panel Gallery project from Javascript30 (Repo Link). Upon previewing the site in a browser, I encountered an issue where the images extend beyond the frame, leaving only t ...

Adjusting the height of an element as you scroll will activate the scroll event

One issue I'm facing is with adding a class to my header. The goal is to reduce the height of the top part of the header when the user scrolls down and then remove the class when they scroll back up. While this functionality is working, there is an un ...

How can I align images of varying sizes to the bottom using Bootstrap 4 or CSS?

I'm having an issue with CSS align-xxxx:bottom not working. I want to align images of different heights at the bottom. .width-book{ width: 100px; } <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" rel="s ...

How can we generate 3 different arrays, each containing an equal number of items except for the last array, using VueJS?

Incorporating Bootstrap5 and VueJS 2, I am working on designing a layout of cards in a "pinterest-style" arrangement, as depicted in the following screenshot: https://i.sstatic.net/AvdWR.png To achieve the layout showcased above, the HTML markup required ...

Add motion to the div element when hovering and moving the mouse away

Looking to add animation to a list moving from left to right and vice versa. Now, I want the list to animate from left to right when the mouse hovers over the div, and then animate from right to left when the mouse leaves the div. Can someone assist me wit ...

Is there a glitch or a misinterpretation of the specifications concerning the use of relative padding

VIEW DEMO At times, I like to create a square (or any rectangle) that maintains its ratio regardless of size, using a technique similar to this method. My Objective: To prevent the square from extending beyond the viewport on devices with limited heigh ...

I'm having trouble getting Grunt Source Maps to function properly within the foundation-press theme

I'm struggling to enable source maps for the npm package grunt-sass. Here's a snippet from my Gruntfile.js: The issue lies in this line: sourceMap: true, at line 13 module.exports = function(grunt) { var jsApp = [ 'js/app.js' ...

Synchronize Protractor with an Angular application embedded within an iframe on a non-Angular web platform

I'm having trouble accessing elements using methods like by.binding(). The project structure looks like this: There is a non-angular website | --> Inside an iframe | --> There is an angular app Here's a part of the code I'm ...

Implement a callback function for unchecked checkboxes on change

Currently, I am working with a gridview that includes a checkbox field. My goal is to use jQuery to create a function that activates when an unchecked checkbox is checked. function clickAllSize() { alert("helloy"); } $(document).ready(function () { ...

Capturing the dynamic server response with nested JSON structures

I am in the process of creating a dynamic data-binding function named assemble that requires two input parameters: server response (JSON) - nested JSON object. instruction set (JSON) - a configuration object that dictates the binding. The Issue: The cur ...

Effortless Page Navigation - Initial click may lead to incorrect scrolling position, but the subsequent link functions perfectly

While implementing the Smooth Page Scroll code from CSS Tricks, we encountered an issue where clicking on a navigation link for the first time only scrolls down to a point that is approximately 700px above the intended section. Subsequent clicks work perfe ...

How can I adjust the size of the renderer in Three.js to fit the screen?

Encountering issues with the code snippet below: //WebGL renderer renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); //TODO: set optimal size document.body.appendChild(renderer ...

Leverage Webpack's File-Loader to Import Images

I have implemented Webpack in my React application. I have added 'File-loader' & 'Url-loader' to my webpack configuration. But I am uncertain about how to connect images to my components. I'm storing the image source ('s ...

Could anyone provide recommendations on how to globally declare jQuery in a Vue-CLI 3 project?

I've come across numerous inquiries on various platforms about this issue, but I have yet to find a solution. To provide some background, I constructed a single-page application website using Vue by initiating a project with an older command. Althoug ...

There was an issue locating the moment/ts3.1-typings/moment module

Encountering an ERROR after updating Angular version: Could not resolve moment/ts3.1-typings/moment in node_modules/ngx-daterangepicker-material/ngx-daterangepicker-material.d.ts ...

Use jQuery to smoothly scroll a div

I created a container using a <div> element which is divided into 3 inner divs. The first two inner divs are meant to serve as previous and next buttons, with ids of prev and next respectively. At the bottom, there are 3 more inner divs, each with un ...

Angular dropdown button positioned to the left side

I'm encountering a slight issue with a dropdown button while working on making my website mobile-friendly. My goal is to have the button drop down on the left-hand side of it. Below is the snippet of my html code: <!-- A div element for the button ...

Text not perfectly centered on the page

I'm working on a layout with 4 columns, and I want the first 3 columns to display text vertically. However, I'm having trouble aligning the text in the center of the column. Even after using justify-content and align-items properties, the text is ...

Troubleshooting a CSS problem with iPad browsers

I have a specific issue related to CSS on iPad. I am working with a set of sublinks and have defined the styles in CSS as follows: #leftNav .searchBySub {...} #leftNav a.searchBySub:hover {...} #leftNav .searchBySubClicked {...} In my JavaScr ...