Bringing a HTML element to front with z-index on overflow in CSS

This was actually a surprisingly easy fix once you understood the structure and the actual problem. Div's covering div's. First you disable all click events on everything within .bracket-part as they aren't needed. Then you add the click events back onto the selects. To make it more generic for easier use again you can simple change select in the CSS selector a class .re-enable-events or something. The JS about z-index's wasnt actually needed.

#bracket-wrapper .bracket-part select {
  pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
  pointer-events: none;
}

See: https://jsfiddle.net/uws8pf1y/

Pointer events has a very good compatibility rate so this solution should be fine across pretty much all devices.


To get straight to the point: There is no clean CSS-only solution to your problem.
Since all your elements are pretty much identical (and by that I mean the class for example) you will not find a solution that covers all configurations. Since they do not differ from each other they all have the same z-index but not the same stacking context. Unless you give their parents a different z-index or change the stacking context you will not be able to access the blocked element. It also comes down to how limited you are with changing the code. The code looks like it has been build by JS and you just copied it to your fiddle for us to test.

Attempt #1

Attempt #1 is to just add high z-index directly to the according parent.
@mmshr already tried to do this. However, he tried to give the whole class a high z-index which is not gonna work out of course as you've already pointed out.

You could however try to only give this element a high z-index element in its style attribute. This comes down to how limited you are with changing the code. You could theoretically use JQuery for this but the way you would select the element (e.g. by nth-child()) brings me to Attempt #2 which uses the same pseudo-class and is a CSS-only attempt so using JS is nonsense in this case. By the way if you can change your code like this you could remove your little JQuery function that adds the forward class on hover.

Attempt #2

This attempt works fine and you are not limited by the ability to change code since this is pretty much one line of CSS. As already stated in Attempt #1 you could use a pseudo-class to select this element. However, this is not valid for all configurations. If you would add one element
(<div data-bind="template: { name: 'bracket-template', data: $data }">...</div>) before your blocked element you would have to change your CSS each time. But if there is no need for changing elements and configurations (or at least not the order) this is a valid solution:

#bracket-wrapper > div > div:nth-child(8) > div > div {
  z-index: 2 !important;
}

In this attempt you can (and have to) remove your little JQuery function too:

$('.bracket-part').hover(
  function() {
    debugger;
    $(this).addClass('forward');
  },
  function() {
    $(this).removeClass('forward');
  }
);

Remove the entire thing.

Attempt #3

Probably the cleanest and best attempt is to use the stacking context. The stacking context is explained right here. But to give you a simple overview (W3C):

Each box belongs to one stacking context. Each positioned box in a given stacking context has an integer stack level, which is its position on the z-axis relative other stack levels within the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.

Most important is this part because it applies to your structure:

Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.

If you take a look at your HTML tree you will find the following: HTML tree

According to the stacking-context we should be able to give your element in the background a higher stacking-order then your element in the front by changing the order of those elements in your tree.

It is just a guess but you probably have something like an array where you store the data and some JS-file builds a tournament bracket out of it. If you could somehow change the order of those two elements (for example by changing the order of your array) you would not use CSS and would not use any additional JQuery.

What if none of these work?

Well, then I do not see any solution that requires only CSS.

I also thought about a possible JS solution but this is a tough one and I couldn't figure out a (simple) solution. Let me explain the problem:

Since your select is behind a div element JQuery would not recognize it (e.g.) on hover so you would have to use pseudo-classes again which I already covered with a CSS-only attempt.
I also thought about adding a z-index of -1 to the blocking element, because JQuery could recognize it on hover. But this leads to problems too: the blocking element is now in the background and the blocked element in the front and you can also click it. The problem is that the (former) blocking element is now behind the #bracket-wrapper. This is also not a valid solution because you would have to use a pseudo-class again to target this specific element.

Conclusion

I am gonna be honest with you: This tournament tree is poorly designed and structured. There shouldn't be overlapping elements or elements outside of a container and certainly not both in combination. If none of my attempts are suitable I do not see any CSS or JS solution. At least not a simple one. You have provided little information about how the tournament tree is build but things could change if you do.
At this state I think rebuilding this whole structure is the only really clean solution.

Edit

Solution #1 by @Deckerz

@Deckerz provided a great solution which does not focus on the z-index. Instead, it uses pointer-events. I tried this approach but failed because I forgot an important part. The logic behind it is simple:

First you disable all click events on everything within .bracket-part as they arent needed. Then you add the click events back onto the selects. To make it more generic for easier use again you can simple change select in the CSS selector a class .re-enable-events or something. The JS about z-index's wasnt actually needed.

#bracket-wrapper .bracket-part select {
   pointer-events: all !important;
}
#bracket-wrapper .bracket-part {
   pointer-events: none;
}

However, this is still a workaround. I still recommend restructuring your code and CSS.

Tags:

Html

Css

Z Index