2

How to apply a transform to element without affecting position: absolute sibling. Been playing with this for a few hours to no avail. I think the code will explain clearer than I can put into words.

The below works as intented, until transform: translateX(10px) is applied to the ul. I need the transform to move the ul based on screen size, it's a longer list in reality. Can the hover state be preserved? Thanks, webstudent

    .relative {
        position: relative;
    }
    nav {
        min-width: 100vw;
        height: fit-content;
        overflow: hidden;
    }
    ul {
        display: block;
        min-width: 100vw;
        list-style-type: none;
        margin: 0;
        padding: 0;
        /* breaks stacking order */
        /* transform: translateX(10px); */
    }
    li {
        display: inline-block;
    }
    li a {
        display: block;
        padding: 4px 8px;
        font-size: 1rem;
        max-height: 1rem;
    }
    li a:hover {
        background-color: red;
    }
    .absolute-sibling {
        position: absolute;
        left: 0;
        top: calc(1rem + 8px);
        width: 100vw;
        height: fit-content;
        display: none;
    }
    li a:hover + .absolute-sibling,
    .absolute-sibling:hover {
        background-color: red;
        display: block;
    }
<div class="relative">
    <nav>
        <ul>
            <li>
                <a>text one</a>
                <!-- absolute child of .relative -->
                <div class="absolute-sibling">content one</div>
            </li>
            <li>
                <a>text two</a>
                <!-- absolute child of .relative -->
                <div class="absolute-sibling">content two</div>
            </li>
            <li>
                <a>text three</a>
                <!-- absolute child of .relative -->
                <div class="absolute-sibling">content three</div>
            </li>
        </ul>
    </nav>
</div>

Broken version with transform included, jsfiddle to reduce wall of code. Same code, apart from transform: translate(10px);

Update:

This describes the issue I'm trying to counter CSS stacking contexts

Also, for instance if I replace the transform: translateX(10px); with margin-left: 10px; everything is as intended. Just I'd like to use the transform for animation smoothness.

webstudent
  • 67
  • 1
  • 11
  • 1
    I dont see any media queries? And you shouldnt really need to use a transform to make a responsive layout. – GifCo Mar 11 '19 at 17:37
  • 2
    Remove overflow: hidden from you nav and it will work. But you really need to rethink your CSS and layout. – GifCo Mar 11 '19 at 17:41
  • Just remove `overflow: hidden;` from `nav`. – tao Mar 11 '19 at 17:41
  • Hey @GifCo & @AndreiGheorghiu ! Thanks for the comments. I misspoke slightly above. I'm not using it to hack responsiveness. It's a very long off-screen menu that has to slide depending on handlers and screen-size (to keep a selection in view). Removing the `overflow: hidden` solves one issue but creates another. The `div.absolute-sibling`s are now visible but need to have their position set dynamically. I'm trying to be creative with the layout, in my mind it makes sense, the item and content sibling template. Also the content can be shown without any JS. I'm open to suggestion though. Thanks – webstudent Mar 11 '19 at 20:35
  • Just updated my answer with another solution. – GifCo Mar 12 '19 at 14:31

1 Answers1

0

Heres one more solution, set the transform on your parent component div.relative and remove it from the ul. (you could also wrap that div and transform that if it works better for your layout)

Change this line in your css

 .relative {
    position: relative;
    transform: translateX(10px)
}

If this still breaks your design then you need to rethink your HTML. As per your article setting a transform creates a new stacking context causing these weird effects. By setting the transform on a parent or wrapper element then you are moving that context up the chain and the child elements should behave like normal.

GifCo
  • 1,350
  • 7
  • 13
  • Hi again @GifCo . I appreciate the answer, but this is not really what I'm looking for. I can't help but think that the solution lies within [this answer](https://stackoverflow.com/questions/20851452/z-index-is-canceled-by-setting-transformrotate) or something similar. I'm just not able to apply it to my context, due to a lack of understanding the relationship between `transforms` and `positions`. Or I could be totally wrong! :joy: Either way, will stick with it for a while more. Thanks – webstudent Mar 12 '19 at 06:34
  • PS: Updated the question with some more info re stacking context – webstudent Mar 12 '19 at 06:45
  • @webstudent ok well you arnt giving nearly enough information then on what you are really trying to achieve. The code you provided is fixed with the above solution without breaking anything else. So we either need the actual code you are working on or you need to fully explain these media queries and animations that are breaking with the solutions given so far. – GifCo Mar 12 '19 at 14:11
  • Hi again @GifCo . I just wanted to let this sit for a while to see if any other potential solutions came in. There's really nothing more to provide. I have no media queries. When I mentioned "screen size" above, I meant that the list could be longer that the available viewport width. Though this has no impact on the examples above, which still exhibit the issue as described. As mentioned in my update, using `margin` as opposed to `transform` solves the issue. I really think this is just an example of the "stacking contexts" of CSS in action. I appreciate your input though. Thanks! :thumbs_up: – webstudent Apr 04 '19 at 19:20