Active-CSS / active-css

The epic event-driven browser language for UI with functionality in one-liner CSS. Over 100 incredible CSS commands for DOM manipulation, ajax, reactive variables, single-page application routing, and lots more. Could CSS be the JavaScript framework of the future?
https://activecss.org
Other
42 stars 7 forks source link

New slide-up and slide-down commands #332

Closed bob2517 closed 1 year ago

bob2517 commented 1 year ago

When I make accordions with containers of height auto, I use a run command to max out the height when expanding and another to set to 0 when contracting. I use regular CSS transitions on the height, padding and margins of the inner containers to animate the slide.

Rather than show the run command hack, and it does look like a hack, I'm going to put this into an ACSS command, so they can be used with CSS transitions. I don't think it's a good idea to do a jQuery slideUp/slideDown, as those have limitations by their nature, and devs should learn standard CSS transitions as they are not hard to learn if an effort is made.

Hopefully one day CSS will be able to handle transitions on a height auto (which could be done these days if it's relooked at - need to confirm it doesn't already do it and I've just missed it), but meanwhile the new command will be:

set-height: max;
set-height: 0;

A full accordion example will be in the docs when this goes up.

dragontheory commented 1 year ago

Good morning, my friend! Long time no coms. Hope all is well across the pond.

Have you tried this approach? Replace the height with max height so that the height of the container does not overcome the actual size of the container or box and it actually works as auto. Secondly, we set the after-transition to “auto” instead we have to set it to a value that the container or box will never attain. ~ https://www.geeksforgeeks.org/how-to-make-transition-height-from-0-to-auto-using-css/

Video example with Grid and Flex layouts: ~ https://www.youtube.com/watch?v=B_n4YONte5A

bob2517 commented 1 year ago

Good morning! All good thanks. Hope all good with you.

Hmmm... thanks for that suggestion. That's a good point. The only thing to check is does it give an even transition on elements of varying heights? In other words does it take 1 second to expand a small div and 1s to expand a large div, so it takes the same amount of time to expand both divs fully? Ie. do the transitions for both the small and large divs finish at the same time?

Just need to check that. If it's fine then I'll close this issue as a red herring.

dragontheory commented 1 year ago

Yes, timing, regardless of distance, can be controlled via the timing function.

https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function

bob2517 commented 1 year ago

Yes indeed - just need to check if setting the max-height to 999999px on a small container of 200px gives us an inappropriately fast transition effect when setting the speed to 1s. If it's fine, then I'll close this issue.

bob2517 commented 1 year ago

Changing these to slide-up and slide-down to make them more obvious to people what this supposed to be used for. CSS will be needed for the transition, and the docs will show how that is done.

Checking the min-height solution. It's messy when used on its own. The solution I have used previously which got me onto doing this issue was to dynamically set the height to the actual size of the container at the point of click. This enables a smooth transition effect which doesn't create ugly jumping of sizes at the point of slide up or down.

bob2517 commented 1 year ago

Note to self - in the core, set up events to sort out the expanded els at point of resize and orientation change so it's a complete solution:

window:resize,
window:orientationchange {
    /* Adjust any "open" accordion sections so they are the correct size. */
    ul.slidingOptions > li.listItemSelected > div:nth-of-type(2) parallel {
        height: auto;
        height: {= o.secSelObj.offsetHeight + "px" =} after stack;
    }
}
bob2517 commented 1 year ago

Now on branch. Example code to follow.

bob2517 commented 1 year ago

Example code

ACSS:

li:not(.opened) .header:click {
    & < li {
        add-class: .opened;
    }
    slide-down: & + .slideable;
}

li.opened > .header:click {
    & < li {
        remove-class: .opened;
    }
    slide-up: & + .slideable;
}

#openAll:click {
    slide-down: .slideable;
    li {
        add-class: .opened;
    }
}

#closeAll:click {
    slide-up: .slideable;
    li {
        remove-class: .opened;
    }
}

HTML:

<button id="openAll">Open all</button>
<button id="closeAll">Close all</button>

<ul>
    <li>
        <div class="header">
            <div class="arrow">&#8595;</div>
            <div class="title">Option 1</div>
        </div>
        <div class="slideable">
            <div class="description">
                Lorem ipsum
            </div>
        </div>
    </li>

    <li>
        <div class="header">
            <div class="arrow">&#8595;</div>
            <div class="title">Option 2</div>
        </div>
        <div class="slideable">
            <div class="description">
                Lorem ipsum
            </div>
        </div>
    </li>

    <li>
        <div class="header">
            <div class="arrow">&#8595;</div>
            <div class="title">Option 3</div>
        </div>
        <div class="slideable">
            <div class="description">
                Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum
            </div>
        </div>
    </li>
</ul>

CSS:

:root {
    --slideSpeed: 1s;
}

ul {
    position: relative;
    width: 600px;
    list-style-type: none;
}

li {
    position: relative;
    margin: 0 0 10px;
    color: white;
    user-select: none;
    cursor: pointer;
}

li .header {
    padding: 10px 20px;
    background-color: darkslategray;
}

li .header > .arrow {
    float: right;
    transform: translateY(-2px);
    transition: transform var(--slideSpeed) ease-out;
}

li.opened .header > .arrow {
    transform: translateY(1px) rotate(-180deg);
}

li .slideable {
    height: 0;
    transition: height var(--slideSpeed) ease-out;
    overflow: hidden;
}

li .description {
    width: calc(100% - 20px);
    margin: 10px;
    padding: 10px 20px;
    background-color: lightgreen;
}
bob2517 commented 1 year ago

Syntax: slide-up: (selector); slide-down: (selector);

Selector can refer to a single element or a set of elements.

Don't add a margin or a padding to the element that is sliding. If you need a margin or a padding inside the sliding container, set them inside the container and not on the sliding element itself.

bob2517 commented 1 year ago

Still need to add the resize and orientation change events on this issue.

bob2517 commented 1 year ago

Orientation change handled after slide down transitionend by setting height to auto. Now on branch.

bob2517 commented 1 year ago

Closing in preparation for release.