1

I'm trying to apply a “zoom out” to a .chip sibling element when I hover above a .slot (.chip elements in the DOM aren't children of a .slot since they move from .slot to .slot, and I didn't implement moving a .chip as removing it from the old .slot children and appending it to the .new slot children; I just update data-slot attributes of .chip elements).

So I have the following CSS rule:

#board.start_move > .slot.movable[data-slot="1"]:hover ~ .chip.top[data-slot="1"],
#board.start_move > .slot.movable[data-slot="2"]:hover ~ .chip.top[data-slot="2"],
#board.start_move > .slot.movable[data-slot="3"]:hover ~ .chip.top[data-slot="3"],
#board.start_move > .slot.movable[data-slot="4"]:hover ~ .chip.top[data-slot="4"],
#board.start_move > .slot.movable[data-slot="5"]:hover ~ .chip.top[data-slot="5"],
#board.start_move > .slot.movable[data-slot="6"]:hover ~ .chip.top[data-slot="6"],
#board.start_move > .slot.movable[data-slot="7"]:hover ~ .chip.top[data-slot="7"],
#board.start_move > .slot.movable[data-slot="8"]:hover ~ .chip.top[data-slot="8"],
#board.start_move > .slot.movable[data-slot="9"]:hover ~ .chip.top[data-slot="9"],
#board.start_move > .slot.movable[data-slot="10"]:hover ~ .chip.top[data-slot="10"],
#board.start_move > .slot.movable[data-slot="11"]:hover ~ .chip.top[data-slot="11"],
#board.start_move > .slot.movable[data-slot="12"]:hover ~ .chip.top[data-slot="12"],
#board.start_move > .slot.movable[data-slot="13"]:hover ~ .chip.top[data-slot="13"],
#board.start_move > .slot.movable[data-slot="14"]:hover ~ .chip.top[data-slot="14"],
#board.start_move > .slot.movable[data-slot="15"]:hover ~ .chip.top[data-slot="15"],
#board.start_move > .slot.movable[data-slot="16"]:hover ~ .chip.top[data-slot="16"],
#board.start_move > .slot.movable[data-slot="17"]:hover ~ .chip.top[data-slot="17"],
#board.start_move > .slot.movable[data-slot="18"]:hover ~ .chip.top[data-slot="18"],
#board.start_move > .slot.movable[data-slot="19"]:hover ~ .chip.top[data-slot="19"],
#board.start_move > .slot.movable[data-slot="20"]:hover ~ .chip.top[data-slot="20"],
#board.start_move > .slot.movable[data-slot="21"]:hover ~ .chip.top[data-slot="21"],
#board.start_move > .slot.movable[data-slot="22"]:hover ~ .chip.top[data-slot="22"],
#board.start_move > .slot.movable[data-slot="23"]:hover ~ .chip.top[data-slot="23"],
#board.start_move > .slot.movable[data-slot="24"]:hover ~ .chip.top[data-slot="24"],
#board.start_move > .slot.movable.selected[data-slot="1"] ~ .chip.top[data-slot="1"],
#board.start_move > .slot.movable.selected[data-slot="2"] ~ .chip.top[data-slot="2"],
#board.start_move > .slot.movable.selected[data-slot="3"] ~ .chip.top[data-slot="3"],
#board.start_move > .slot.movable.selected[data-slot="4"] ~ .chip.top[data-slot="4"],
#board.start_move > .slot.movable.selected[data-slot="5"] ~ .chip.top[data-slot="5"],
#board.start_move > .slot.movable.selected[data-slot="6"] ~ .chip.top[data-slot="6"],
#board.start_move > .slot.movable.selected[data-slot="7"] ~ .chip.top[data-slot="7"],
#board.start_move > .slot.movable.selected[data-slot="8"] ~ .chip.top[data-slot="8"],
#board.start_move > .slot.movable.selected[data-slot="9"] ~ .chip.top[data-slot="9"],
#board.start_move > .slot.movable.selected[data-slot="10"] ~ .chip.top[data-slot="10"],
#board.start_move > .slot.movable.selected[data-slot="11"] ~ .chip.top[data-slot="11"],
#board.start_move > .slot.movable.selected[data-slot="12"] ~ .chip.top[data-slot="12"],
#board.start_move > .slot.movable.selected[data-slot="13"] ~ .chip.top[data-slot="13"],
#board.start_move > .slot.movable.selected[data-slot="14"] ~ .chip.top[data-slot="14"],
#board.start_move > .slot.movable.selected[data-slot="15"] ~ .chip.top[data-slot="15"],
#board.start_move > .slot.movable.selected[data-slot="16"] ~ .chip.top[data-slot="16"],
#board.start_move > .slot.movable.selected[data-slot="17"] ~ .chip.top[data-slot="17"],
#board.start_move > .slot.movable.selected[data-slot="18"] ~ .chip.top[data-slot="18"],
#board.start_move > .slot.movable.selected[data-slot="19"] ~ .chip.top[data-slot="19"],
#board.start_move > .slot.movable.selected[data-slot="20"] ~ .chip.top[data-slot="20"],
#board.start_move > .slot.movable.selected[data-slot="21"] ~ .chip.top[data-slot="21"],
#board.start_move > .slot.movable.selected[data-slot="22"] ~ .chip.top[data-slot="22"],
#board.start_move > .slot.movable.selected[data-slot="23"] ~ .chip.top[data-slot="23"],
#board.start_move > .slot.movable.selected[data-slot="24"] ~ .chip.top[data-slot="24"] {
    transform-origin: center;
    transform: scale(1.3);
}

because I want only the .top .chip associated with the :hovered .slot to zoom-out.

The above works as-is. We can discuss alternate ways to achieve what I do, but the question is:

Can I simplify the above 48 selectors to just 2 by specifying that I want the data-slot attribute be the same in both elements?

Update 2

As requested, a working sample in JSFiddle.
As a side note: slots are numbered counter-clockwise from the top right, where is slot 1 (slot 24 is at the bottom right); you can use the console provided by JSFiddle to enter commands like tvl.move(1,5) to move a chip from one slot to another.

tzot
  • 92,761
  • 29
  • 141
  • 204
  • 2
    Can we see the HTML ? – Rainbow Jul 05 '20 at 20:45
  • Do you have all of the `.slot` element first and then all of the `.chip` elements? – Muhammad Talha Akbar Jul 05 '20 at 20:45
  • 1
    I don't think this will work: https://stackoverflow.com/questions/41707199/css-selector-compare-2-attributes – disinfor Jul 05 '20 at 20:46
  • 1
    the answer to your question is: No – Temani Afif Jul 05 '20 at 20:47
  • 1
    That said, if you use a preprocessor (SASS/SCSS/LESS), you could use a `@for` loop and not have to worry about writing it out. `@for $i from 1 to 50 { #board.start_move { > .slot.movable[data-slot="#{$i}"]:hover, .slot.movable.selected[data-slot="#{$i}"]:hover { ~ .chip.top[data-slot="#{$i}"] { transform-origin: center; transform: scale(1.3); } } } }` – disinfor Jul 05 '20 at 20:47
  • The HTML is simple, because slots and chips are created programmatically; and like I said this works as-is, so yes, the .slot elements are before the .chip elements. I believe that TemaniAfif is correct, and that using a preprocessor like disinfor says would be a solution. If anyone want to write this as an answer, I'd gladly accept it. – tzot Jul 05 '20 at 20:51
  • 1
    if you share the HTML you will get better answers. We can answer your question like *you cannot do this but you can try ..*. It would be more intresting and you will probably get surprised with different and better way to achieve what you want. – Temani Afif Jul 05 '20 at 20:54
  • 1
    @tzot **Off-topic, Suggestion:** Perhaps, you can drop maintaining `data-slot` attributes by styling the ***nth sibling***. See: https://stackoverflow.com/questions/44428250/css-style-nth-sibling – Muhammad Talha Akbar Jul 05 '20 at 20:59
  • The code is not complete. We are meant to blindly copy paste your code and see exactly what you see, I advise you put up a working snippet on jsfiddle or some other platform for people to be able to test. – Rainbow Jul 05 '20 at 21:19
  • @ZohirSalak I provided a working JSFiddle sample. – tzot Jul 05 '20 at 21:52
  • 1
    @MuhammadTalhaAkbar Thanks for the suggestion, but it isn't always the same nth sibling; chips move to different slots during the course of the game. – tzot Jul 05 '20 at 21:53
  • Doesn't seem to be a workaround given your html structure, What you have right now is ugly but at least it works. – Rainbow Jul 05 '20 at 22:47
  • @ZohirSalak the whole point of posting a fiddle was to allow readers to suggest any alternatives, given that the code works and the question seems to be answered. You have the ability to suggest a better HTML structure and make it beautiful and operational at the same time. You can teach a backend developer the real beauty of HTML, CSS and JavaScript. You wouldn't ask for a fiddle if the only contribution you could provide was your opinion about its beauty, right? – tzot Jul 05 '20 at 23:10
  • There's zero opinion in what i said, all of it is quoted from you. – Rainbow Jul 05 '20 at 23:22
  • So your comment was basically a reiteration of a comment in my fiddle (re “ugliness”), and a reiteration of a previous comment by disinfor (“can't be done”). What could be done with a different HTML structure, if we don't consider my HTML structure as a given (it never was)? – tzot Jul 05 '20 at 23:32

1 Answers1

1

Since you can't do this with a single CSS selector rule (since there is no "same attribute value" selector) - I would recommend using a preprocessor (SASS/SCSS/LESS) to manage the actual writing of the selectors.

You can use @for loop provided to loop through any number of iterations you need.

@for $i from 1 to 50 {
  #board.start_move {
     > .slot.movable[data-slot="#{$i}"]:hover,
        .slot.movable.selected[data-slot="#{$i}"]:hover {
        ~ .chip.top[data-slot="#{$i}"] {
          transform-origin: center;
          transform: scale(1.3);
        }
     }
  }
}

https://www.sassmeister.com/gist/3b0c9ed2cfda0d668d91666aafdebfed

This keeps the solution closest to a "CSS solution" - without changing your JS or how the current code is written.

disinfor
  • 10,865
  • 2
  • 33
  • 44