Why doesn't this CSS transform work?

There are 5 buttons in a row in a grid with images. I have two images of the same class. When you hover over one, both should enlarge slightly.

However, only 1 enlarges. The other one has a rotate transform and doesn’t enlarge. If it remove the transform, then each will enlarge, but only on the image hovering.

How do I make both images enlarge at the same time while keeping the rotate transform on the one image?

CSS:

/* enlarge related buttons */
img.c1-corner:hover {
-ms-transform: scale(1.2,1.2); /* IE 9 */
  transform: scale(1.2,1.2); /* Standard syntax */
}

5 buttons, first and last with class=“c1-corner”:

<button value=""><img class="c1-corner" src="images/1-corner.png"></button>
<button value=""><img src="images/1-5-Lcorner.png"></button>
<button value=""><img src="images/1-center.png"></button>
<button value=""><img src="images/1-5-Rcorner.png"></button>
button value=""><img src="images/1-corner.png" class="c1-corner"></button>

I’m not quite sure what you are attempting but when you hover an item then only that item is affected. You can’t hover over either item and have them both affected at the same time.

You could hover the first item and then use the general sibling combinator to affect the last item but the reverse is not possible with css. Of course they would need to be siblings so you’d need to do this.

button:hover img.c1-corner {
  transform: scale(1.2); 
}
button:hover ~ button .c1-corner {
	transform: scale(1.2) rotate(45deg); 
}

However as mentioned you can’t hover the last item and affect the first as CSS doesn’t work backwards.

The only option you have without js is to wrap a div around the 5 buttons and then when you hover the wrapping div you can make the first and last ones scale or rotate as required.

div:hover img.c1-corner {
  transform: scale(1.2); 
}
/* if you wanted a different effect on the last button then add this*/
div:hover button:last-child img.c1-corner {
 transform: scale(1.2) rotate(45deg); 
}

The difference with this method is that the hover effect will stay in place all the time that you are over any of the items in the div.

Maybe if you gave us a use case for the effect you want then we could make alternative suggestions.

The use case: the square images are inserts that go into a part. (The other side of each insert has indentations that are offset.) They can be inserted 4 different ways. I thought it would be informative if the users hovered over one instance, they could see the other possibilities; they’ll see how the offsets are affected as they turn the inserts. In this case, hovering over the top left, they’ll see another possibility in the top right.

Hi there WebSteve,

@Paul_Wilkins will probably be able to give
you a more modern version of this example…

https://codepen.io/coothead/full/RwWgOpL

…and its code…

https://codepen.io/coothead/pen/RwWgOpL

coothead

2 Likes

One of the two relevant button images needs to have this styling:

style="transform: rotate(90deg);"

This is why it doesn’t work on my version.

If you add it, does your code still work?

Hi there WebSteve,

if this is one specific image, then
try the links in post #4 again. :winky:

coothead

Well starting from this cleaned-up version of the code:

(function(d) {
    "use strict";
    var clCorner = d.querySelectorAll(".c1-corner");
    function over() {
        for (var c = 0; c < clCorner.length; c+= 1) {
            clCorner[c].classList.add("scale");
        }
    }

    function out() {
        for (var c = 0; c < clCorner.length; c+= 1) {
            clCorner[c].classList.remove("scale");
        }
    }
    for (var c = 0; c < clCorner.length; c += 1) {
        clCorner[c].addEventListener("mouseover", over, false);
        clCorner[c].addEventListener("mouseout", out, false);
   }
}(document));

The first thing that I notice about this code is that each for loop is looping over exactly the same thing. The querySelectorAll method supports a forEach method, so let’s use the forEach method instead of for loops.

(function(d) {
    "use strict";
    var clCorner = d.querySelectorAll(".c1-corner");
    function over() {
        clCorner.forEach(function (corner) {
            corner.classList.add("scale");
        });
    }

    function out() {
        clCorner.forEach(function (corner) {
            corner.classList.remove("scale");
        });
    }
    clCorner.forEach(function (corner) {
        corner.addEventListener("mouseover", over, false);
        corner.addEventListener("mouseout", out, false);
   });
}(document));

About the only duplication involved now is that clCorner is being dealt with in three different places, so we can move that into a separate function called eachCorner():

(function(d) {
    "use strict";
    function eachCorner(callback) {
        d.querySelectorAll(".c1-corner").forEach(callback);
    }
    function over() {
        eachCorner(corner => corner.classList.add("scale"));
    }

    function out() {
        eachCorner(corner => corner.classList.remove("scale"));
    }
    eachCorner(function (corner) {
        corner.addEventListener("mouseover", over, false);
        corner.addEventListener("mouseout", out, false);
   });
}(document));

And because the over and out functions are so,simple, we can use arrow notation on those:

(function(d) {
    "use strict";
    function eachCorner(callback) {
        d.querySelectorAll(".c1-corner").forEach(callback);
    }
    const over = () => eachCorner(corner => corner.classList.add("scale"));
    const out = () => eachCorner(corner => corner.classList.remove("scale"));

    eachCorner(function (corner) {
        corner.addEventListener("mouseover", over, false);
        corner.addEventListener("mouseout", out, false);
   });
}(document));

I don’t think that I would modernise things much beyond there :slight_smile:

2 Likes

Interesting. :slightly_smiling_face:

Could this be an acceptable CSS solution?

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
<title>Untitled</title>
<style>
form {
  width:400px;
}
button{
  display:table-cell;
  width:80px;
}
.c1-corner1{
  float:left;
}
.c1-corner2{
  float:right;
}
.c1-corner2 img{
  transform:  rotate(90deg);
}
div:hover .c1-corner1 img{
  transform: scale(1.2,1.2);
}
div:hover .c1-corner2 img{
  transform: scale(1.2,1.2)  rotate(90deg);
}
</style>
</head><body>

<h1>Enlarge Related Buttons</h1>
<form>
  <div>
    <button class="c1-corner1" value=""><img src="images/1-corner.png"></button>
    <button class="c1-corner2" value=""><img src="images/1-corner.png"></button>
  </div>
  <button value=""><img src="images/1-5-Lcorner.png"></button>
  <button value=""><img src="images/1-center.png"></button>
  <button value=""><img src="images/1-5-Rcorner.png"></button>
</form>

</body></html>

Hopefully I’ve covered all conditions. Maybe I can come up with a different solution if this fails. :thinking:

EDIT)
Replaced the code because I missed that rotate should combine with the scale on hover state. A style attribute would override the hover state.

1 Like

If you want an element to scale and rotate at the same time you have to apply them in the one rule as the transform property will override any previous settings.

You need to do this as shown in my first example.

transform: scale(1.2) rotate(45deg);

If that’s the problem you were describing :slight_smile:

As an aside support for individual transform values that don’t cancel out previous values is starting to be implemented in browser at the moment.

Very clever Erik :slight_smile:

There is a slight problem in chrome though where the last button is dropping to a new line (not the right floated button).

Adding a div around the other three buttons and setting display:flex seems to fix it :wink:

1 Like

Nah, just old time thinking. :slightly_smiling_face:

Or old-time style; just skip the fancy “no white-space trick” and float all buttons: :smiley:

button{
/* display:table-cell; */
  float:left;
  width:80px;
}

The Chrome/Chromium seems to be immune to the table-cell trick to remove inline white-space. :thinking:

1 Like

Your example assumes that none of the images are rotated from the beginning. Actually, the same image is being used 4 different times, each time it appears, it is being rotated another 90 degrees. That’s before any hovering. So when I hover over any of the buttons, I want to enlarge all 4 instances of that image, keeping their rotation.

To keep it uncomplicated, I merely showed 1 row where the image is being used twice and rotated 90 degrees in one location.

See my reply #12. Hovering should enlarge all 4 instances of the same image, keeping their orientation.

If I can’t see a way to do that, I’ll either make new images that are already at their proper orientation, or skip this piece of the puzzle.

How would the full picture be then, if I’ll find time to try again?

1 Like

Yes I have given you the answer to that in my last few posts if I understand your problem.

It sounds to me as though you have rotated an element by default and then when you hover it you want to enlarge it. If this is correct then when you hover the image you cannot just use scale alone.

e.g.

.something{transform:rotate(45deg)}
.something:hover{transform:scale(1.2)}

The above won’t work as the rotation would be lost.
What you would need to do is this:

.something{transform:rotate(45deg)}
.something:hover{transform:rotate(45deg) scale(1.2)}

The transform property when used again will negate any previous transforms just like saying background:red will over-ride background:url(img.gif).

2 Likes

I return to work Thursday. I’ll try PaulOB’s medicine first and see what happens. Don’t sweat over this now.

At any rate, there will be a matrix of 25 button images, 5 across and down, and each button image is being used 4 times (rotated 3 of those times) except the center, which is used once and doesn’t rotate.

They are rotated to cut down the number of images I need to make. If worse comes to worse, I can make each rotation a different image.

2 Likes

Are all 4 images needed to be affected when any of them are hovered in each of those sets of 4?

That would change the original problem and should have been mentioned early on!

I think you mean @Paul_Wilkins . :slightly_smiling_face:

I wont. :wink:

Edit)
Though anything everything is possible in CSS. :smiley:

2 Likes

I thought with post #1 that if we could resolve the stated issue, then I could expand on the answer to cover 2 more images. The problem in #1 is: “How do I make both images enlarge at the same time while keeping the rotate transform on the one image?” Whatever solution I got I hoped to expand to all four images.

I think I answered that part of the question in every one of my posts. :wink:

If I haven’t been clear enough then just shout :slight_smile: . It can be confusing if you don’t understand how transforms work.

1 Like

Oh, that post was responding to Erik_J, not you :slight_smile: I’m anticipating your ode tomorrow!

1 Like