The stacking order of a child element within a parent element, which has a transform

Hey there, I've encountered a problem and was wondering if you could assist me with it.

In the code snippet provided below, you'll see that there are elements with:

transform: translate(0,0);

Within these elements, there is a "dropdown" element that appears upon clicking a button.

The issue arises when parts of this dropdown end up hidden behind other elements. After some investigation, I realized that this is due to the parent element having the transform property.

https://i.sstatic.net/OB7us.png

This is just a simplified example; my actual code is more extensive. Unfortunately, I'm unable to remove the transform property.

Is there a CSS-only solution to this dilemma? Your insights would be greatly appreciated!

Cheers!!

$(document).ready(function() {
  $('button[name="button"]').click(function(e) {
    $(e.currentTarget).parent().find('.template-options-dropdown').toggleClass('open');
  });
});
.boxes {
  list-style-type: none;
}

.boxes >li {
  float: left;
  width: 100px;
  height: 100px;
  background-color: red;
  margin: 5px;
  transform: translate(0, 0);
}

.download-container {
  background: rgba(40, 39, 39, 0.8);
  bottom: 0;
  position: absolute;
  text-align: center;
  width: 100%;
}

.download-container .dropdown-container {
  display: inline-block;
  position: relative;
}

.download-container .dropdown-container button {
  background: #0bb9ab;
  color: #fff;
  padding: 6px 12px;
}

.template-options-dropdown {
  list-style-type: none;
  text-align: left;
  padding: 0;
  position: absolute;
  background-color: #111;
  visibility: hidden;
}

.template-options-dropdown.open {
  visibility: visible;
}

.template-options-dropdown li a {
  color: white;
  text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="boxes">
  <li>
    <div class="download-container">
      <div class="dropdown-container">
        <button type="button" name="button">Download</button>

        <ul class="template-options-dropdown">
          <li>
            <a href="#">Original</a>
          </li>
          <li>
            <a href="#">Thumb</a>
          </li>
          <li>
            <a href="#">Mobile</a>
          </li>
          <li>
            <a href="#">Tab</a>
          </li>
          <li>
            <a href="#">Web</a>
          </li>
          <li>
            <a href="#">Large web</a>
          </li>
        </ul>
      </div>
    </div>
  </li>
  <li><div class="download-container">
      <div class="dropdown-container">
        <button type="button" name="button">Download</button>

        <ul class="template-options-dropdown">
          <li>
            <a href="#">Original</a>
          </li>
          <li>
            <a href="#">Thumb</a>
          </li>
          <li>
            <a href="#">Mobile</a>
          </li>
          <li>
            <a href="#">Tab</a>
          </li>
          <li>
            <a href="#">Web</a>
          </li>
          <li>
            <a href="#">Large web</a>
          </li>
        </ul>
      </div>
    </div></li>
  … (content continues)
</ul>

Answer №1

It seems that finding a CSS-only solution to this problem may be challenging due to the creation of a new stacking context by CSS3 transitions. For more information, refer to the documentation and this thread.

If a property has a non-none value, it will create a stacking context.

Source: MDN

To address this issue, you can replace translate(0,0) with position: relative and add a z-index greater than zero to .template-options-dropdown for resolution.

A somewhat unconventional approach that alters the layout is to introduce additional transforms:

  1. Invert the appearance order of the list by applying scaleY(-1) to the ul, as higher indexed list items will overlap lower ones.

  2. Add a reversing scaleY(-1) to the li elements to restore normalcy.

  3. Additionally, clear the floats on the li elements.

Check out the demonstration below:

$(document).ready(function() {
$('button[name="button"]').click(function(e) {
$(e.currentTarget).parent().find('.template-options-dropdown').toggleClass('open');
});
});
.boxes {
list-style-type: none;
transform: scaleY(-1);
}
.boxes:after {
content: '';
clear: both;
display: block;
}

.boxes >li {
float: left;
width: 100px;
height: 100px;
background-color: red;
margin: 5px;
transform: translate(0, 0) scaleY(-1);
}

.download-container {
background: rgba(40, 39, 39, 0.8);
bottom: 0;
position: absolute;
text-align: center;
width: 100%;
}

.download-container .dropdown-container {
display: inline-block;
position: relative;
}

.download-container .dropdown-container button {
background: #0bb9ab;
color: #fff;
padding: 6px 12px;
}

.template-options-dropdown {
list-style-type: none;
text-align: left;
padding: 0;
position: absolute;
background-color: #111;
visibility: hidden;
}

.template-options-dropdown.open {
visibility: visible;
}

.template-options-dropdown li a {
color: white;
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="boxes">
<li>
<div class="download-container">
<div class="dropdown-container">
<button type="button" name="button">Download</button>

<ul class="template-options-dropdown">
<li>
<a href="#">Original</a>
</li>
<li>
<a href="#">Thumb</a>
</li>

...

</li>
</ul>
</div>
</div></li>

...

</li>
</ul>

If removing translate(0,0) proves futile, resorting to JavaScript may be necessary:

  1. Reverse the stacking order by assigning a z-index corresponding to the list index.

  2. Apply position:relative to the li elements.

Explore the demo provided below:

$(document).ready(function() {

// ADDED
$($('ul.boxes > li').get().reverse()).each(function(index){
$(this).css('z-index', index);
});

$('button[name="button"]').click(function(e) {
$(e.currentTarget).parent().find('.template-options-dropdown').toggleClass('open');
});
});
.boxes {
list-style-type: none;
}

.boxes >li {
float: left;
width: 100px;
height: 100px;
background-color: red;
margin: 5px;
transform: translate(0, 0);
position: relative;
}

.download-container {
background: rgba(40, 39, 39, 0.8);
bottom: 0;
position: absolute;
text-align: center;
width: 100%;
}

.download-container .dropdown-container {
display: inline-block;
position: relative;
}

.download-container .dropdown-container button {
background: #0bb9ab;
color: #fff;
padding: 6px 12px;
}

.template-options-dropdown {
list-style-type: none;
text-align: left;
padding: 0;
position: absolute;
background-color: #111;
visibility: hidden;
}

.template-options-dropdown.open {
visibility: visible;
}

.template-options-dropdown li a {
color: white;
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="boxes">

...

</ul>

Answer №2

When using the <code>z-index property, remember that it will only work on elements with a position of absolute, fixed, or relative. Therefore, make sure to set the position of the element to relative.

If you have a fixed number of elements, consider assigning z-index values in the following manner:

.boxes li:nth-child(1) {
  z-index: 8;
}

.boxes li:nth-child(2) {
  z-index: 7;
}

... (continue for the rest of the elements)

Alternatively, for an unknown number of elements, you can use a script to apply z-index dynamically. Here's an example:

$(document).ready(function() {
  $('button[name="button"]').click(function(e) {
    $(e.currentTarget).parent().find('.template-options-dropdown').toggleClass('open');
  });
});
.boxes {
  list-style-type: none;
}

.boxes >li {
  float: left;
  width: 100px;
  height: 100px;
  background-color: red;
  margin: 5px;
  transform: translate(0, 0);
  position: relative;
}

.download-container {
  background: rgba(40, 39, 39, 0.8);
  bottom: 0;
  position: absolute;
  text-align: center;
  width: 100%;
}

... (continue with the CSS styles)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="boxes">
 ... (example HTML structure)
</ul>

Answer №3

You're almost there, but if it were up to me, I would apply the .open class either to the <li> element or the div.download-container. By setting a high z-index value and utilizing the cascade effect, we can reveal the sub-menu. Remember to include position:relative; on the element with the z-index property for it to take effect.

Here's an example:

$(document).ready(function() {
  $('button[name="button"]').click(function(e) {
    $(e.currentTarget).parents('li').toggleClass('open');
  });
});
.boxes {
  list-style-type: none;
}

.boxes >li {
  float: left;
  width: 100px;
  height: 100px;
  background-color: red;
  margin: 5px;
  transform: translate(0, 0);
  position:relative;
}

.boxes >li.open {
    z-index:500;
}

.download-container {
  background: rgba(40, 39, 39, 0.8);
  bottom: 0;
  position: absolute;
  text-align: center;
  width: 100%;
}

.download-container .dropdown-container {
  display: inline-block;
  position: relative;
}

.download-container .dropdown-container button {
  background: #0bb9ab;
  color: #fff;
  padding: 6px 12px;
}

.template-options-dropdown {
  list-style-type: none;
  text-align: left;
  padding: 0;
  position: absolute;
  background-color: #111;
  visibility: hidden;
}

.boxes li.open .template-options-dropdown {
  visibility: visible;
}

.template-options-dropdown li a {
  color: white;
  text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="boxes">
  <li>
    <div class="download-container">
      <div class="dropdown-container">
        <button type="button" name="button">Download</button>

        <ul class="template-options-dropdown">
          <li>
            <a href="#">Original</a>
          </li>
          <li>
            <a href="#">Thumb</a>
          </li>
          <li>
            <a href="#">Mobile</a>
          </li>
          <li>
            <a href="#">Tab</a>
          </li>
          <li>
            <a href="#">Web</a>
          </li>
          <li>
            <a href="#">Large web</a>
          </li>
        </ul>
      </div>
    </div>
  </li>

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

Struggling to animate the selector of a nested div in Jquery?

Despite trying numerous variations, I am struggling to identify the correct selector of a nested div. The goal is to animate this particular div, but since no animations are taking place, I suspect that I have not selected the right element. Here is the a ...

What is the way to display the final list item when clicking in jQuery?

I am attempting to achieve a specific behavior where clicking on a button will trigger the content below to scroll in such a way that only the last item in the list is visible. I have been using jQuery for this functionality, but unfortunately, it is not ...

Craft a unique parallax effect using Framer Motion's clipping feature

To help visualize my concept, I have sketched it out using Figma. This idea involves a slide transitioning between pages. The goal is to cover the entire page with a sliding effect, and then place a sticker (dubbed the Parallax Box) on top of it. However ...

Only the first column of a row in Flexbox will have a line break when exceeding the

Currently, I am utilizing flex with a row direction for a set of items with fixed widths causing overflow and a horizontal scrollbar, which is the desired outcome. Nevertheless, my requirement is for the first column in these rows to be full-width, while ...

I am in need of a customized 'container' template that will display MyComponent based on a specific condition known as 'externalCondition'. MyComponent includes the usage of a Form and formValidation functionalities

container.html <div ngIf="externalCondition"> <!--Initially this is false. Later became true --!> <my-component #MyComponentElem > </my-component> <button [disabled]= "!myComponentElemRef.myDetailsF ...

Having trouble eliminating the underline on Vue router-link?

I've experimented with various approaches in an attempt to remove the underline from router-link. This is the code I have: <router-link :to="{name: 'Plan'}"> <div>Plan Your Trip</div> <div class=&apos ...

Issue with content overlapping when hamburger icon is tapped on mobile device

When the hamburger menu is pressed on smaller screens, I want my navbar to cover the entire screen. To achieve this, I included the .push class in my code (see the jQuery and CSS) to trigger when the .navbar-toggle-icon is pushed. However, after implemen ...

Issue with Displaying Local Server Image in Angular 2 HTML

I am facing an issue with my Angular 2 Application. It retrieves items from a local database where the server stores the image of the item and the database stores the path to that image stored on the server. While I can retrieve all the items without any p ...

Is the user currently browsing the 'Home screen webpage' or using the Safari browser?

In JavaScript, is there a method to determine if the user has accessed the website from their home screen after adding it to their home screen, or if they are browsing via Safari as usual? ...

The length of the LinearProgress bar does not match the length of the navbar

Utilizing the LinearProgress component from Material UI, I created a customized ColoredLinearProgress to alter its color: import React, { Component } from 'react'; import { withStyles } from '@material-ui/core/styles'; import { LinearP ...

Safari is truncating the box-shadow of an element enclosed within a button

I'm struggling with a button that has an element inside receiving a box-shadow: button { padding: 0; border: 0; margin: 0; overflow: visible; -webkit-appearance: none; background: white; } .shadow { display: inline-block; vertical- ...

How can we avoid animations being interrupted by user interaction?

My webpage has an animation that runs smoothly on desktop, but stops as soon as I interact with the page on a touch device. I have tested this issue on Chrome and Safari on iPad. I'm curious if this behavior is intentional on the part of browser vend ...

Struggling with implementing CSS in React even after elevating specificity levels

I am struggling with a piece of code in my component that goes like this: return ( <div className="Home" id="Home"> <Customnav color="" height="80px" padding="5vh"/> <div className= ...

Any tips for avoiding a new line when generating html attribute values to prevent my json string from breaking?

When working with JSON string values in button element attributes, I have encountered an issue where a single quote causes the value to break and create newlines. For example: var $json = JSON.stringify('{"Long_text":"This is \'my json stri ...

Tips for referencing Google Maps initialization in individual files within a website application

After setting up my Google Maps API snippet: <script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"></script> in the index.html file, I encountered the error: Uncaught InvalidValueEr ...

Activate the Chrome Extension that allows you to open a link in a new tab with just a middle click or regular click, without closing the popup

When I try to click a link in my extension popup and open it in a new tab using "middle click -> open link in a new tab", the popup closes. Is there a way to keep the popup open so I can click on multiple links from my extension without interruption? A ...

Steps to assign a value to an input element using the state in a React application

Hey there, I hope everything is going well for you! I have a question regarding setting the value of an input field based on the state received from props. I've tried to populate the input with data from the "profile" state using placeholders, but it ...

Pair of buttons triggering the submission of a form

I'm encountering an issue where I have 2 buttons in my form, one for submitting and one for going to the previous page, but both seem to be performing the same action. How is this happening? <div style="position:fixed; left: 50px; ...

Is there a way to ensure certain items are displayed on different lines?

Currently, I am working on styling an HTML list with the following properties: font-weight: bold; padding: 0px; margin: 0px; list-style-type: none; display: block; width:700px; font-size: 14px; white-space: pre-wrap; The individual cells within this list ...

Flexbox is not properly repeating elements horizontally

I am struggling to align text boxes horizontally within ngFor loop, and I can't seem to pinpoint the mistake. Here is the HTML code from the parent component: <div class="maintenance-section"> <div class="yearly"> ...