Only implement the CSS styles if there are multiple elements that have the same class

I have 2 cards with the class card displayed within a card-stack. There can be any number of such cards.

<div class="card-stack">
  <div class="clear"><button name="clear" value="Clear all" onclick="removeAllCards(this)">Clear All</button></div>
  <div class="card" style="--y:1" onclick="remove(this)">
    <div class="card-header">
      <div class="card-avatar">
        <img src="https://static.thenounproject.com/png/363633-200.png">
      </div>
      <div class="card-title">Announcement 1</div>
    </div>
    <div class="card-body">
      This is announcement 1.
    </div>
  </div>
  <div class="card" style="--y:2" onclick="remove(this)">
    <div class="card-header">
      <div class="card-avatar">
        <img src="https://static.thenounproject.com/png/363633-200.png">
      </div>
      <div class="card-title">Announcement 1</div>
    </div>
    <div class="card-body">
      This is announcement 1.
    </div>
  </div>
</div>

When hovering on the card-stack, CSS is applied to each card

.card-stack:hover .card{
  transform: translateY(calc((var(--y) * -105% + 200px)));
  box-shadow: none;
}

I want the HOVER effect to apply only if there are more than one elements with the class card. How can this be achieved using CSS?

CodePen link for the snippet above

function remove(element) {
  element.remove();
}

function removeAllCards(element) {
  element.remove();
  document.querySelectorAll(".card").forEach(el => el.remove());
}
body {
  background-color: #e8eaed;
}

.card {
  width: 300px;
  min-height: 150px;
  background-color: white;
  position: fixed;
  top: 75vh;
  right: 100px;
  transform: translate(-50%, -50%);
  display: grid;
  border-radius: 5px;
  font-family: sans-serif;
  font-size: 14px;
  color: #00000080;
  box-shadow: 0 5px 15px 0 #00000040, 0 5px 5px 0#00000020;
  transition: transform 200ms;
  padding:15px;
  cursor:pointer;
}

.card {
  transform: translateY(calc((var(--y) * 20px) - 50%)) scale(calc(1.0 + var(--y) * 0.05));
}

.card-avatar {
  display:block;
}
.card-avatar img {
  width:40px;
  height:40px;
  float:left;
}
.card-title {
  font-size:16px;
  display:inline-block;
  margin-top:10px;
  margin-left:10px;
}

.card-header {
  height:30px;
  display: inline-block;
}
.card-body {
  margin-top:-30px;
}

.card-stack:hover .card{
  transform: translateY(calc((var(--y) * -105% + 200px)));
  box-shadow: none;
}

.card-stack:hover .clear {
  visibility: visible;
  transform: translateY(calc((var(--y) * -105% + 200px)));
  position:absolute;
  top:2vh;
  right:40px;
}

.card-stack {
  position:fixed;
  width: 400px;
  min-height: 100vh;
  position: fixed;
  right: 65px;
}

.clear {
  visibility:hidden;
}
<div class="card-stack">
  <div class="clear"><button name="clear" value="Clear all" onclick="removeAllCards(this)">Clear All</button></div>
  <div class="card" style="--y:1" onclick="remove(this)">
    <div class="card-header">
      <div class="card-avatar">
        <img src="https://static.thenounproject.com/png/363633-200.png">
      </div>
      <div class="card-title">Announcement 1</div>
    </div>
    <div class="card-body">
      This is announcement 1.
    </div>
  </div>
  <div class="card" style="--y:2" onclick="remove(this)">
    <div class="card-header">
      <div class="card-avatar">
        <img src="https://static.thenounproject.com/png/363633-200.png">
      </div>
      <div class="card-title">Announcement 1</div>
    </div>
    <div class="card-body">
      This is announcement 1.
    </div>
  </div>
</div>

Answer №1

One interesting approach could be to style elements that are both the first and last child of their parent simultaneously.

.myClass {
  color: tomato;
}

.myClass:first-child:last-child {
  color: DarkSlateGrey;
}
<div>
  <span class="myClass">I'm alone</span>
</div>

<div>
  <span class="myClass">We are two</span>
  <span class="myClass">We are two</span>
</div>

Answer №2

To avoid code duplication, you can follow Creaforge's suggestion and override the styles only when there is a single .card element. However, this would require specifying the transform and box shadow values twice, which might not be the most efficient approach due to the length of those values.

There are two more concise methods to achieve this:

  1. Utilize a selector. While normally recommending

    .card-stack:hover .card:not(:nth-child(2):last-child)
    , it's worth considering that support for level 4 :not() is still not fully complete. In such cases, you may need to resort to the older method, demonstrated below:

    .card-stack:hover .card:not(:nth-child(2)), .card-stack:hover .card:not(:last-child) {
      transform: translateY(calc((var(--y) * -105% + 200px)));
      box-shadow: none;
    }
    
  2. Remove the .clear element from within the .card-stack element. There doesn't seem to be a substantial reason for its placement there. Subsequently, adjust the selector as follows:

    .card-stack:hover .card:not(:only-child) {
      transform: translateY(calc((var(--y) * -105% + 200px)));
      box-shadow: none;
    }
    

    (Note that in the absence of level 4 :not(), the combination :not(:first-child:last-child) mentioned by Creaforge isn't directly viable in CSS, but you have the option of utilizing :only-child)

Answer №3

To separate them, you can assign the IDs "Card1" and "Card2" to each element and then style them in CSS using #Card1 and #Card2. I hope this solution works for you! :)

Answer №5

Perhaps you could consider dynamically adding a class using JavaScript instead? This involves updating the CSS properties for hover effects and applying the class only if the card-stack element contains more than two children, triggered by the "onmouseover" event.

<div class="card-stack" onmouseover="onHover(this)">
...
</div>
.card-stack-h:hover  .card{
  transform: translateY(calc((var(--y) * -105% + 200px)));
  box-shadow: none;
 }

.card-stack-h:hover .clear {
  visibility: visible;
  transform: translateY(calc((var(--y) * -105% + 200px)));
  position:absolute;
  top:2vh;
  right:40px;
}
function onHover(stack) {
  let cards = stack.querySelectorAll(".card")
  if(cards.length > 1) stack.classList.add("card-stack-h")
  else stack.classList.remove("card-stack-h");
}

Codepen

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

I'm having an issue where my footer is getting cut off when I resize the browser and start side scrolling. Can

I designed a webpage with a footer that contains another div holding centered content. The footer is supposed to span the entire width, while the inner content div is set to 960px with a margin auto to center it. <footer> <div class="footer-in ...

Navigation buttons that move the user either up or down the page

I am a beginner in programming and I wanted to create two buttons for my webpage. One button should appear when the page is scrolled more than 300px and take the user to the top, while the other button should be displayed immediately and scroll the user to ...

What are the steps for populating a table cell with data using AJAX, MySQL, and PHP in the given situation?

The challenge is to create an HTML table with two columns where the first column gets its data from PHP and MySQL. The goal is to turn the values in the first column into clickable links that, when clicked, trigger an AJAX call to fetch information from th ...

React App Showing Scrollbar When Material UI AppBar is Present

I'm encountering a straightforward issue in my React application. How can I get rid of the scrollbar on my page? It seems like the problem arises from the height value I set to 100vh. However, upon removing the AppBar, the scrollbar disappears. Any su ...

Incorporating fresh data from a node.js backend to refresh a webpage section

I'm currently working on creating an app that can retrieve the song a user is currently listening to using a web scraper. While I've managed to direct users to the page and display the current song title, they must manually refresh the entire pag ...

Unveiling the Magic: Enhancing Raphaeljs with Interactive Click Events on a Delicious Slice of the

I'm having trouble responding to a click event on each slice of a Raphael Pie Chart. I've tried implementing the code below, but it doesn't seem to be working. The code is just two lines, commented as "My Code", in the example from the offic ...

What are the steps for distributing a styled React component?

My goal is to release a UI library using React, but I am struggling with how to handle styles. When I write code in a project, I typically use webpack and babel to build my code, resulting in the creation of a *.css file. import React from 'react&ap ...

Top methods for incorporating whitespace on both sides of the page

Currently working on a ReactJS/MaterialUI webapp and looking to enhance the layout. Seeking advice on whether it's best practice to add padding or margin to create space on the left and right side of the page, similar to popular websites like Stack Ov ...

Shimmering effect on hover for CSS animation

Is there a way to create a CSS-only animation that fades in and out until hovered when displayed in full? I can achieve both effects separately, but I'm struggling to make them work together. The hover element doesn't seem to be functioning prope ...

What is the best way to decrease the font size of every element in the DOM?

Is there a way to decrease the size of all DOM elements by a specific amount? Currently, I am using Bootstrap styles where h5 is set at 14px and I need it to be 12px, and h1 is at 36px when I want it to be 34px, and so forth. I have considered two option ...

Recover Checkmark Status from Data

Currently, I am storing form data in json format and encountering an issue when trying to load values from a previously created json file. The plain old JavaScript function provided below successfully loads values into a form from a file, effectively resto ...

How come the CSS for my angular ngx-mat-datetime-picker and mat-datepicker collide when they are both present on the same page?

Within the same form, I have two input fields stacked under each other. One is an ngx-mat-datetime-picker and the other is a mat-datepicker. Individually, they function correctly. However, when I open them for the second time, the one I opened first appear ...

Steps for selecting a radio button based on a MySQL table value:

My table has two fields, name and gender. When I retrieve the data and attempt to display it in input fields, everything works fine for the Name field. However, I am curious if there is a way to automatically select the radio button based on the gender d ...

What are the best methods to activate grayscale and transition effects on Firefox and Internet Explorer?

In order to achieve a grayscale effect for all images on Internet Explorer 10 and IE 11, I came across a helpful solution in this post: internet explorer 10 - howto apply grayscale filter?. However, the method provided is only for a single image. How can I ...

Tips for adjusting the maximum height of the column panel within the DataGrid element

I'm trying to adjust the max-height of a column panel that opens when clicking the "Columns" button in the Toolbar component used in the DataGrid. I am working with an older version of @material-ui/data-grid: "^4.0.0-alpha.8". https://i.stack.imgur.c ...

Tips for choosing an image using jQuery from an external HTML page

I'm attempting to embed an HTML page within a div and then individually select all the img tags within that page to display an overlay div on top of the images. Currently, I can insert the HTML into a div named "asd" and it seems like the jQuery is f ...

Remove the innerHTML content of dynamically added elements using jQuery

After researching, it seems that event handlers are commonly added using methods such as .live(), .on(), .bind(), or .delegate(). My previous question may not have been clear, so I decided to delete it and ask a simpler one. Is there a way to clear the in ...

Using the Loop Function in Node.js with EJS Templates

Seeking help with a node.js application that utilizes bootstrap. I am trying to display the bootstrap cards in rows of 3, with each row containing data from my dataset in columns. However, my current implementation using two for loops is leading to repeate ...

Editing HTML using the retrieved jQuery html() content

I need to modify some HTML that is stored in a variable. For example: var testhtml = $('.agenda-rename').html(); console.log($('input',testhtml).attr('name')); I also tried the following: console.log($(testhtml).find(' ...

The themes showcased in the Bespoke.js documentation and demo exhibit unique designs

Recently, I stumbled upon an incredible HTML5 framework for presentations. For more information, you can check out the documentation here. You can also view a demo of the framework by visiting this link. However, I was disappointed to find that the caro ...