Make CSS height transition smoother - css

I have the following HTML markup and CSS to build navigation menus:
.submenu {
max-height: 0;
overflow-y: hidden;
transition: max-height 0.3s ease-in;
}
.submenu.opened{
max-height: 200px;
}
<ul class="navigation navigation-main navigation-accordion">
<li>Dashboard</li>
<li>
Products
<ul class="submenu">
<li>All Products</li>
<li>Popular Products</li>
</ul>
</li>
</ul>
I toggle the class opened on submenu using JavaScript. The submenu slides up and down on click with the help of the transition. But I want the transitions as smooth as possible.
How can I improve the above CSS code to make it as smooth as possible, as it doesn't work well if the Product link is clicked in quick succession.

I guess everybody has another definition of smooth, but I would start here with changing the ease function from ease-in to ease-in-out and than just play with the duration of the transition. 0.3s is a bit fast in this situation, increase the duration until it fits for you. Here is an example with a duration of 1.5s:
document.querySelector('#prod').addEventListener('click', function() {
document.querySelector('.submenu').classList.toggle('opened');
}, false);
.submenu {
max-height: 0;
overflow-y: hidden;
transition: max-height 1.5s ease-in-out;
}
.submenu.opened{
max-height: 200px;
}
body {
font-size: 1.5em;
font-family: sans-serif;
line-height: 1.7
}
<ul class="navigation navigation-main navigation-accordion">
<li>Dashboard</li>
<li>
Products
<ul class="submenu">
<li>All Products</li>
<li>Popular Products</li>
</ul>
</li>
</ul>

Related

How to make after in Tailwindcss?

I'm trying to turn my website to full Tailwindcss as i'm just learning it
how can i turn AFTER value in Tailwindcss ?
spanthis::before {
content: "OMANI";
animation: animate infinite 3s;
padding-left: 10px;
}
#keyframes animate {
0% {
content: "OMANI";
}
5% {
content: "COOL";
}
15% {
content: "PROFESSIONAL";
} }
UPDATE: Since v2.2 Tailwind now supports before/after
Tailwind does not support before/after pseudo-classes.
There is opened feature request about it: https://github.com/tailwindlabs/tailwindcss/discussions/2119
"Full tailwind" does not have to mean dropping CSS completely and having everything inline. You can as well combine #apply with pseudo classes.
But there is unofficial plugin for that if you really need this inline https://github.com/shimyshack/tailwindcss-pseudo-element-plugin
<ul class="inline-block">
<li class="inline-block after:inline-block after:pseudo-content-comma after:mr-1">Item 1</li>
<li class="inline-block after:inline-block after:pseudo-content-comma after:mr-1">Item 2</li>
<li class="inline-block after:inline-block after:pseudo-content-oxford-ampersand after:mr-1">Item 3</li>
<li class="inline-block">Item 4</li>
</ul>

Show partial content of UL then collapse with transition

I've created a list that shows partial content and collapses with a trigger. Everything is working fine except I can't manage to make this works with CSS transition when it collapses. Basically, I toggle between 2 classes and apply a height: 100%
HTML
<div class="list">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
</ul>
<span class="more-less"></span>
</div>
CSS
.list.expand {
height: 180px;
overflow: hidden;
}
.list.expand.open {
height: 100%;
padding-bottom: 20px;
}
JS
var list = $(".list");
$(".more-less").click(function() {
list.toggleClass("open closed");
});
I made CODEPEN to make some tests. I think this is a specific situation that needs a specific solution. I've spent hours trying snippets found here on Stackoverflow (CSS and JS) but without success.
neither CSS transition: height .5s ease; or .animate(height...) seems to work for me :/ So, any help or clue would be much appreciated :) Thanks
EDIT: I forgot a crucial information: The list content is loaded dynamically (WP), so that's why I need to set the height to "auto".
have you tried to add a transition to .list.expand?
.list.expand {
height: 180px;
overflow: hidden;
-webkit-transition: height 2s; /* For Safari 3.1 to 6.0 */
-moz-transition: height 2s;
transition: height 2s;
}
Thanks to this post, I finally found a workaround with jQuery. Probably not the best way to achieve that, but it works :p
var list = $(".list");
// Apply only if list height is taller than 100px
if (list.height() > 100) {
list.addClass("expand closed");
}
// First, set height to auto then memorize the height value in a variable,
// then set the height to 100px
list.css("height", "auto");
var listheight = list.css("height");
list.css("height", "100px");
// When click to the "more-less" trigger, toggle between "open" and "closed" class,
// then apply the correct height for each class
$(".more-less").on("click", function() {
list.toggleClass("open closed");
if (list.hasClass("open")) {
list.height(listheight);
}
if (list.hasClass("closed")) {
list.height(100);
}
});
CSS
.list.expand {
height: 180px;
overflow: hidden;
-webkit-transition: height .3s ease-in-out;
-moz-transition: height .3s ease-in-out;
transition: height .3s ease-in-out;
}
DEMO HERE on CodePen
I found a better way to achieve this, with .scrollHeight
JS
var list = $(".list");
// variable storing an integer corresponding to the scrollHeight pixel value of the element.
var fullHeight = list[0].scrollHeight+'px';
if (list.height() > 100) {
list.addClass("expand closed");
list.height(100);
}
$(".more-less").on("click", function() {
if(list.hasClass("closed")) {
list.animate({
height: fullHeight
}, 200);
} else if (list.hasClass("open")) {
list.animate({
height: "100px"
}, 200);
}
list.toggleClass("open closed");
});
CSS
.list.expand {
overflow: hidden;
}
DEMO HERE on CodePen

transition/opacity rendering issues in Chrome?

I am having an issue with a CSS opacity transition. It doesn't seem to work well on Chrome - most of the time.
When it does work, it is very choppy - goes to about 1/2 opacity, then full.
When it doesn't work, it goes to less than full opacity, and stops there.
What am I doing wrong? I thought it had been working well when I first implemented this (mid June, I think). Since it does transition to full opacity sometimes, I'm not entirely sure that it was ever fully working in Chrome. But both me and my client noticed it (separately) at about the same time - late June/early July.
Here is my HTML and CSS code, and a JSFiddle. (Possibly a little more than I need to replicate this error)
.fade {
opacity:0;
transition: opacity 0.5s;
-moz-transition: opacity 0.5s;
-webkit-transition: opacity 0.5s;
-o-transition: opacity 0.5s;
}
#submenu {
opacity:0;
position:absolute;
left:185px;
}
#submenu a {
width: 90px;
padding: .4em .5em;
}
.horizontal-menu2 {
opacity:inherit;
position:absolute;
left:113px;
}
.horizontal-menu1 {
opacity:inherit;
position:absolute;
left:5px;
}
.image-menu {
opacity:inherit;
position:absolute;
right:175px;
}
.person:hover #submenu {
opacity: 1;
}
<ul>
<li class="person">Person One
<ul class="fade" id="submenu">
<li class="horizontal-menu1"><a onclick="#">menu1</a></li>
<li class="horizontal-menu2">menu2</li>
<li class="image-menu"><img src="#" alt="photo of person"></li>
</ul>
</li>
</ul>
I'm aware of an old bug in Chrome v. 40, however that was back in January (I think) and I'm on v. 43 now
It appears to be a similar issue to this, however mine does appear to work sometimes, and so perhaps this persons' issue isn't fully resolved.
Also, the other questions of this type are older - some are a direct result of Chrome v. 40's (now fixed) bug.
Your rendering bug appears to be related to the use of opacity: inherit; on the children of an element with transitioning opacity. If you remove these lines, it behaves as expected.
Working Example (JSFiddle):
.fade {
opacity:0;
transition: all 0.5s;
-moz-transition: all 0.5s;
-webkit-transition: all 0.5s;
-o-transition: all 0.5s;
}
#submenu {
opacity:0;
position:absolute;
left:185px;
}
#submenu a {
width: 90px;
padding: .4em .5em;
}
.horizontal-menu2 {
position:absolute;
left:113px;
}
.horizontal-menu1 {
position:absolute;
left:5px;
}
.image-menu {
position:absolute;
right:175px;
}
.person:hover #submenu {
opacity: 1;
}
<ul class="interview-menu">
<li class="person">Person One
<ul class="fade" id="submenu">
<li class="horizontal-menu1"><a onclick="#">menu1</a>
</li>
<li class="horizontal-menu2">menu2
</li>
<li class="image-menu">
<img src="#" alt="photo of person">
</li>
</ul>
</li>
</ul>
Pure speculation, but I'm guessing it's caching the value it inherits from the parent element at some point during the transition, and not updating it during the transition.

Grandchild :focus Not keeping Parent Open Even With ~ Selector

I have a little experiment going on. I'm trying to create an onclick menu without javascript using :focus. The issue I'm having is with grandchild, which clicked it still closes the parent. I tried using the ~ selector to keep it open, but it isn't working and I don't understand as to why.
<nav id="main-menu">
<ul>
<li>Menu 1</li>
<li tabindex="0" class="onclick-item"><span>Menu 2</span>
<ul class="onclick-show-content">
<li>Sub-Menu 1</li>
<li tabindex="0" class="onclick-item"><span>Sub-Menu 2</span>
<ul class="onclick-show-content">
<li>Sub-Sub-Menu 1</li>
</ul>
</li>
</ul>
</li>
<li>Menu 3</li>
<li>Menu 4</li>
</ul>
</nav>
.onclick-item { outline: none; }
.onclick-item:focus {
pointer-events: none;
}
.onclick-item > .onclick-show-content {
overflow: hidden;
max-height: 0;
-webkit-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
transition: all .5s ease-in-out;
}
.onclick-item:focus > .onclick-show-content, .onclick-item:focus ~ .onclick-show-content {
max-height: 540px;
pointer-events: auto;
}
codepen: http://codepen.io/anon/pen/iuhtn
When you click on the grandchild, focus is taken off of its grandparent. That causes the :focus > rule to no longer apply to the grandparent.
The ~ selector doesn't work the way you're using it as there are no .onclick-show-content elements that are following siblings of .onclick-item elements. The structure that you have doesn't seem to be conducive for using ~ either, as it's parent-child-based, not sibling-based.

CSS Descendent Selector After Hover Psuedo Class Only Works in Chrome

I am creating a menu where I want the menu items to fade in when I hover on them and fade out when I hover off of them. I am using CSS 3. This code works in Chrome and in no other browsers. It seems to be the line in the CSS where there is a direct descendent selector after the hover psuedo class that is causing the problem.
HTML
<div class="mainMenu">
<ul id="nav">
<li class="dir">
Menu Item
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</li>
</ul>
</div>
CSS
li.dir > ul{
opacity: 0;
transition: opacity .3s ease-in-out;
-moz-transition: opacity .3s ease-in-out;
-webkit-transition: opacity .3s ease-in-out;
}
li.dir:hover > ul {
opacity: 1.0;
}

Resources