-1

I'm making a collapsible panel and the issue is with the [data-panel] not keeping the css transition when it's set to height: 100%. it works fine for fixed height i.e. height: 150px , but it's important to keep height dynamic since I don't know the available space of the content inside. i'd prefer not modifying the html or js but i'm open to suggestions...

Codepen: issue on line 44 in css
https://codepen.io/oneezy/pen/bGBpXaW

function activeLinks() {
    
    document.addEventListener('click', e => {
        let linkEl = e.target.closest('[data-link]');
        
        if (linkEl) {
            let url                         = linkEl.dataset.link;
            let linkEls                 = document.querySelectorAll('[data-link]');
            let ActivelinkEls   = document.querySelectorAll(`[data-link="${url}"]`);
                        
            // remove "active" class from all links
            Array.from(linkEls).forEach( (el) => {
                el.classList.remove('active');
            });
            
            // add "active" class to all matching links
            Array.from(ActivelinkEls).forEach( (el) => {
                let prevLink            = el.parentElement.previousElementSibling;
                let prevPrevLink    = el.parentElement.parentElement.previousElementSibling;
                
                el.classList.add('active'); 
                
                if (prevLink && prevLink.dataset.link) {
                    prevLink.classList.add('active');
                    prevLink.parentElement.classList.add('active');
                }
                
                if (prevPrevLink && prevPrevLink.dataset.link) {
                    prevPrevLink.classList.add('active');
                    prevPrevLink.parentElement.classList.add('active');
                }
            });
        }
        
    });
}

activeLinks();
/* Reset 
*********************************/
* { margin: 0; padding: 0; box-sizing: border-box; font-family: roboto; }
html, body { height: 100%; overflow-x: hidden; }
a { text-decoration: none; display: block; }


/* Layout 
*********************************/
#page { display: grid; grid-template-columns: 160px 1fr; gap: 3rem; height: 100%; }
#nav { background: black; display: block; align-items: start; align-content: start; justify-content: stretch; padding: 2rem 1rem; }
#main { display: flex; justify-content: space-around; padding: 2rem 5rem 0 0;  }


/* Navigation 
*********************************/
/* Sections */
#nav .link-level__one   { margin: 1rem 0; }
#nav .link-level__two   {  }
#nav .link-level__three { position: relative; }
#nav .link-level__three::after { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; width: 100%; background: gray; }

/* Links */
#nav .link-level__one a { padding: .25rem .5rem; color: gray; font-weight: 900; }
#nav .link-level__one a.active { color: white; }

#nav .link-level__two a { padding: .25rem .5rem; color: gray; font-weight: normal; }
#nav .link-level__two a.active { color: white; }

#nav .link-level__three a { padding: .25rem .5rem; color: gray; }
#nav .link-level__three a.active { color: white; font-weight: normal; }


/* Main 
*********************************/
#main section {  }
#main a { color: black; padding: 1rem .5rem; }
#main a.active { background: blue; color: white; }


/* Panel 
*********************************/
[data-panel]                        { height: 0; overflow: hidden; transition: .22s .22s ease-in-out; }
.active ~ [data-panel]  { height: 150px; } /* I NEED THIS TO BE DYNAMIC HEIGHT! */
<div id="page">
    <nav id="nav">
        
        <!-- LINK 1 
        ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
        <!-- LEVEL 1 -->
        <section class="navigation-links__wrapper link-level__one">
            <a href="#link1" data-link="link1">Link 1</a>
            
            <!-- LEVEL 2 -->
            <section class="link-level__two" data-panel>
                <a href="#link1a" data-link="link1a">Link 1a</a>
                
                <!-- LEVEL 3 -->
                <section class="link-level__three" data-panel>
                    <a href="#link1a-1" data-link="link1a-1">Link 1a-1</a>
                    <a href="#link1a-2" data-link="link1a-2">Link 1a-2</a>
                    <a href="#link1a-3" data-link="link1a-3">Link 1a-3</a>
                </section>
            </section>
        </section>
        
        <!-- LINK 2 
        ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
        <!-- LEVEL 1 -->
        <section class="navigation-links__wrapper link-level__one">
            <a href="#link2" data-link="link2">Link 2</a>
            
            <!-- LEVEL 2 -->
            <section class="link-level__two" data-panel>
                <a href="#link2a" data-link="link2a">Link 2a</a>
                
                <!-- LEVEL 3 -->
                <section class="link-level__three" data-panel>
                    <a href="#link2a-1" data-link="link2a-1">Link 2a-1</a>
                    <a href="#link2a-2" data-link="link2a-2">Link 2a-2</a>
                    <a href="#link2a-3" data-link="link2a-3">Link 2a-3</a>
                </section>
            </section>
        </section>
        
        <!-- LINK 3 
        ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
        <!-- LEVEL 1 -->
        <section class="navigation-links__wrapper link-level__one">
            <a href="#link3" data-link="link3">Link 3</a>
            
            <!-- LEVEL 2 -->
            <section class="link-level__two" data-panel>
                <a href="#link3a" data-link="link3a">Link 3a</a>
                
                <!-- LEVEL 3 -->
                <section class="link-level__three" data-panel>
                    <a href="#link3a-1" data-link="link3a-1">Link 3a-1</a>
                    <a href="#link3a-2" data-link="link3a-2">Link 3a-2</a>
                    <a href="#link3a-3" data-link="link3a-3">Link 3a-3</a>
                </section>
            </section>
        </section>
        
    </nav>

    <main id="main">
        <section>
            <h2>Link Level 1</h2>
            <a href="#link1" data-link="link1">Link 1</a>
            <a href="#link2" data-link="link2">Link 2</a>
            <a href="#link3" data-link="link3">Link 3</a>
        </section>
        <section>
            <h2>Link Level 2</h2>
            <a href="#link1a" data-link="link1a">Link 1a</a>
            <a href="#link2a" data-link="link2a">Link 2a</a>
            <a href="#link3a" data-link="link3a">Link 3a</a>
        </section>
        <section>
            <h2>Link Level 3</h2>
            <a href="#link1a-1" data-link="link1a-1">Link 1a-1</a>
            <a href="#link1a-2" data-link="link1a-2">Link 1a-2</a>
            <a href="#link1a-3" data-link="link1a-3">Link 1a-3</a>

            <a href="#link2a-1" data-link="link2a-1">Link 2a-1</a>
            <a href="#link2a-2" data-link="link2a-2">Link 2a-2</a>
            <a href="#link2a-3" data-link="link2a-3">Link 2a-3</a>

            <a href="#link3a-1" data-link="link3a-1">Link 3a-1</a>
            <a href="#link3a-2" data-link="link3a-2">Link 3a-2</a>
            <a href="#link3a-3" data-link="link3a-3">Link 3a-3</a>
        </section>
    </main>
</div>
Oneezy
  • 4,881
  • 7
  • 44
  • 73
  • Pretty sure this is a duplicate. I dont think there is a way to do this simply using CSS with relative heights. You'll probably have to calculate the height of your absolute content with js... – rx2347 Feb 08 '21 at 23:21

3 Answers3

0

It's a duplicate question that has been answered here: How can I transition height: 0; to height: auto; using CSS?

You can use a max-height greater than it will ever be to accomplish this.

#menu #list {
    max-height: 0;
    transition: max-height 1s ease-out;
    overflow: hidden;
    background: #d5d5d5;
}

#menu:hover #list {
    max-height: 1000px;
    transition: max-height 1s ease-in;
}
Tristanisginger
  • 2,181
  • 4
  • 28
  • 41
  • that's not going to work unfortunately... you see how using `max-height` makes the transition "jumpy" / "janky" ? https://codepen.io/oneezy/pen/poNbayO – Oneezy Feb 08 '21 at 23:50
  • It does work, you just need to adjust your transition time from .22s to something like 1s – Tristanisginger Feb 09 '21 at 16:34
  • 1 second transition isn't ideal though for me... .22s is the the animations speed for all elements in this project I'm working on. – Oneezy Feb 09 '21 at 19:19
  • You'll need to open another question to fix the jankyness my answer was just about the auto height – Tristanisginger Feb 10 '21 at 10:53
0

I've somewhat came up with a solution I'm proud of; however, it's not perfect. The main trick in getting this to work was giving the [data-panel] a line-height: 0 and transitioning it when it becomes active (THE LINE-HEIGHT ONLY). Also you'll need to make sure the contents of the [data-panel] don't have any margin or padding (until the panel becomes active) or it will completely throw off the UI.

https://codepen.io/oneezy/pen/bGBBEmp

/* Panel 
*********************************/
[data-panel] {
  overflow: hidden;
  line-height: 0;
  opacity: 0;
  pointer-events: none;
  transition: line-height .22s ease-in-out;
}

.active + [data-panel] {
  line-height: 1.4;
  opacity: 1;
  pointer-events: auto;
}

I'm answering my own question; however, I'm not accepting it as the chosen answer. I'd love to see more unique solutions added to this thread.

Oneezy
  • 4,881
  • 7
  • 44
  • 73
-1

The short answer is that you can't. Height transitions will only work on elements that use a unit based value for their height property.

Here's an article detailing different techniques to achieve the same outcome: https://css-tricks.com/using-css-transitions-auto-dimensions/

El-Mo
  • 370
  • 2
  • 13