Mark Lundin
Mark Lundin

Reputation: 327

Click areas break using CSS 3D transforms

On Chrome on OSX, rotating a element in 3D and performing the inverse of the rotation on a child element breaks mouse events on the child including any links. The hit area seems to be misaligned.

The dom structure is:

<div class='test'>
  <div><a href='http://www.google.com'>Click me</a></div>
</div>

The above dom structure is also on JSFiddle

Does anyone know a workaround using the same dom structure that preserves the correct click area?

Upvotes: 19

Views: 2701

Answers (2)

Patrick W. McMahon
Patrick W. McMahon

Reputation: 3561

if a DOM element has an event connected to it for example a click element and you rotate it 90 degrees the element is still at that location but you can't click on it due to it being flat. DOM elements have a zero depth so when you rotate a DOM element 90 degrees you can't see it. if you rotate that same element back you will see it and the click event works. technically the click area works when the element is rotated 90 degrees it just has a zero point area to be clicked.

For the people that do not believe that the event is still attached test this out and see for your self. The event will stay connected to the element no matter how many transformation you do. It also works for chrome. This also works for links too. The only time an event is removed is when you remove the event or remove the element. transformation will never remove the event or the element.

document.getElementById("testButton").addEventListener("click", function() {
  alert("It works");
});
document.getElementById("flipButton").addEventListener("click", function() {
  if (document.getElementById("testButton").style.webkitTransform == "rotateX(0deg)") {
    document.getElementById("testButton").style.webkitTransform = "rotateX(90deg)";
    document.getElementById("test").style.webkitTransform = "rotateX(90deg)";
  } else {
    document.getElementById("testButton").style.webkitTransform = "rotateX(0deg)";
    document.getElementById("test").style.webkitTransform = "rotateX(0deg)";
  }
});
<html>

<body>
  <button id='testButton'>test button</button>
  <div id='test'>
    <div><a href='http://www.google.com'>Click me</a></div>
  </div>
  <button id='flipButton'>transform button</button>
</body>

</html>

Here is an example using your example:

.test {
  -webkit-transform-style: preserve-3d;
  -webkit-transform: rotateX( 90deg);
}

.test>* {
  -webkit-transform: rotateX( -90deg);
}
<html>

<body>
  <div id='test'>
    <div><a href='http://www.google.com'>Click me</a></div>
  </div>
</body>

</html>

You will notice that it still works. The reason your code is not working is that your href you have href='htpp://boom'. The URI htpp://boom is not a real address.

There is no such thing as htpp:// and boom is not an address. Your bug in your code has nothing to do with transformation and nothing to do with css. Your bug is not using a real URI.

Upvotes: 1

guest271314
guest271314

Reputation: 1

The -webkit-transform property may be functioning properly in displaying either element(s) at rotateX(90deg), or rotateX(-90deg), respectively.

Whereas at rotateX(90deg), the elements would not be expected to be rendered "view-able", or "visible".

The element(s) would be "flattened" along their X axis, as it were.

At rotateX(90deg) the css is probably transform 'ing the element(s) to just that - 90 deg (rees) sic.

Please see linked jsfiddle, with the css trasform property set to rotateX(45deg), and rotateX(-45deg), respectively, to view the prospective rotateX((n)deg) progression, at 45deg.

Again, the transform property may simply be attempting to achieve a true 90 deg (ree) sic angle, which, along the X axis, might resemble - if visible -

_

or a "horizon".

| - Y axis

_ - X axis

jsfiddle http://jsfiddle.net/guest271314/3XpFG/

Edit (update, workarounds)

You're answer does not mention the clickable area. Also, your demo does not provide a workaround that preserves the click area. – Mark Lundin

If requirement includes setting css property rotateX() value to 90deg, element may appear to render similar to display : none;, that is, render virtually "invisible" on screen. See http://jsfiddle.net/guest271314/N6MdE/

Workarounds

1) applicable to both options a), and b), below

html

<!-- add `tabindex` attribute to `.test > a`,
     whether `element` rendered "visible", or "invisible",
     pressing `Tab` `key` possible to select `a` `element`,
     possibly add `title` attribute, 
     both `attributes` added for "notification", 
     of `a` `element` ("link") presence at that `position` in `document`,
     still possible to `navigate` to `a` `link`, utilizing `Tab` `key`
-->
<a href='htpp://boom' tabindex="1">Click me</a>

a) Render elements at css property rotateX(89deg), rotateX(-89deg), respectively, which should render the elements on screen, perhaps preserving at least some of the "effect" such a ndeg "rotateX()", offset by 1deg. jsfiddle http://jsfiddle.net/guest271314/bzdak/

    .test{
    -webkit-transform-style: preserve-3d;
    -webkit-transform: rotateX( 89deg );
    height : 50px;
    opacity : 1.0;
}

.test > a{
    -webkit-transform: rotateX( -89deg );
}

.test:hover, .test a:hover {  
    -webkit-transform : rotateX(0deg);
     outline : thin solid blue;
     opacity : 1.0;
     cursor : pointer;
}

.test a:link, .test a:active {
    color : #c17d11; 
    font-size : 24px;
}

b) Render elements at css property rotateX(89deg), rotateX(-89deg), respectively, including css property opacity value set to 0.9, which should render the elements virtually "invisible", similar to a rotateX(90deg) rendering (see http://jsfiddle.net/guest271314/N6MdE/), adding css :hover and/or :active pseudo elements, either, or both, for "notification" of a element ("link") presence at that position in document jsfiddle http://jsfiddle.net/guest271314/De7P6/

    .test{
    -webkit-transform-style: preserve-3d;
    -webkit-transform: rotateX( 89deg );
    display : block;
    height : 50px;
    opacity : 0.9;
}

.test > a{
    -webkit-transform: rotateX( -89deg );
}

.test:hover, .test a:hover {  
    -webkit-transform : rotateX(0deg);
     outline : thin solid blue;
    opacity : 1.0;
     cursor : pointer;
}

.test a:link, .test a:active {
    color : #c17d11; 
    font-size : 24px;
}

Upvotes: 0

Related Questions