I have an element with a max-height of 0. I want to transition it to no max-height auto or none; whatever makes it expand based on the number of elements present. I don't want to use JS nor flex, yet.
Here's the jsfiddle: https://jsfiddle.net/m9pd8bjh/19/
HTML:
<nav>
<input type="checkbox" id="menu-main-checkbox" hidden>
<label class="toggler" for="menu-main-checkbox">Menu</label>
<div class="hide toggleable">
<ul>
<li>Home</li>
<li>Sample Page</li>
</ul>
</div>
</nav>
CSS:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
max-height: 68px;
}
.toggleable {
transition: visibility 1.5s ease-in-out, max-height .75s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
When I set the max-height to 68px (the height fitting two list items) it works perfectly, but when I set the max-height to 500px, for example, leaving room for future list items, it takes time to transition from 500 to 0, making it give a delay before the list items disappear again.
I do not wish to use scaling as it complicates it and I have to come up with a solution to solve the spacing under it. It keeps the spacing under the element and reserves it for when it opens out.
One workaround what I found was to use animation with #keyframes.
Remember to add vendor-prefixes.
Browser support for this is the following:
Firefox 5+, IE 10+, Chrome, Safari 4+, Opera 12+
I modified your CSS to this:
.hide {
visibility: hidden;
overflow: hidden;
max-height: 0;
}
input[type=checkbox]:checked~.toggleable {
visibility: visible;
animation: height1 .75s forwards;
}
input[type=checkbox]:not(:checked)~.toggleable {
visibility: visible;
animation: height2 .50s forwards;
}
.toggleable {
transition: visibility 1.5s ease-in-out;
}
.toggler {
cursor: pointer
}
nav {
background: #e74c3c;
}
#keyframes height1 {
0% { max-height: 0; }
100% { max-height: 500px; }
}
#keyframes height2 {
0% { max-height: 500px; }
100% { max-height: 0; }
}
If used like this there will be smaller delay when clicking again.
Here is the updated jsfiddle: https://jsfiddle.net/m9pd8bjh/25/
Related
I have tried multiple methods to get this transition to work, however, ran out of ideas. The transition works fine when checking, but not unchecking. Things I have tried:
not using visibility to unhide more-info div
using all, however, it transitions, but with a fade affect, which is not what I want transition: all 300ms ease-in-out;
HTML:
<input :id="id" type="checkbox" class="checkbox" role="button">
<div class="more-info">
Content
</div>
CSS:
.more-info {
max-height: 0;
transition: max-height 300ms ease-in-out;
visibility: hidden;
opacity: 0;
overflow: hidden;
position: absolute;
bottom: 0;
width: calc(100% + 2px);
margin-bottom: -1px;
}
.checkbox {
display: none;
}
.checkbox:checked ~ .more-info {
max-height: 700px;
visibility: visible;
opacity: 1;
}
visibility: hidden; and opacity: 0; cancels the animation, as, in theory, the animation is running in max-height, the fact that you set it as hidden doesn't show the expected result.
Removing visibility: hidden; and adding opacity to your transition should fix the problem, opacity will hide the element while max-height goes to 0
I am following a tutorial on how to create CSS tooltips. Everything works just fine, but there is one modification that I would like to make. I want the tool tip to show up 3 seconds after I hover over an item, but to fade out immediately when I stop hovering over the item. This is the (relevant) code I have right now:
.tooltip:hover .tooltip-text {
opacity: 0.7;
visibility: visible;
}
.tooltip-text {
...
opacity: 0;
transition: all 500ms;
transition-delay: 3s;
visibility: hidden;
...
}
This ALMOSTS works. It delays showing the tooltip for 3 seconds, like I want. However, it also delays removing the tooltip (which I do NOT want). How can I modify my code so that the tool tip fades in 3 seconds after I hover with my mouse and starts fading out immediately when I stop hovering?
Define transition properties in :hover class. Like this:
.tooltip:hover .tooltip-text {
opacity: 0.7;
visibility: visible;
transition: all 500ms;
transition-delay: 3s;
}
.tooltip-text {
opacity: 0;
visibility: hidden;
}
See working demo below. (Try hovering the red box)
.box {
width: 100px;
height: 30px;
background-color: red;
}
.tooltip {
opacity: 0;
visibility: hidden;
}
.box:hover .tooltip {
opacity: 1;
visibility: visible;
transition: all 500ms;
transition-delay: 2s;
}
<div class="box">
<div class="tooltip">
This is tooltip.
</div>
</div>
Demo of the problem: https://jsfiddle.net/t0qsek8n/1/
<div class="test" id="test">Test text</div>
.test {
position: relative;
top: 0px;
border: 1px solid #ccc;
animation: test 5s;
transition: top 1s;
}
#keyframes test {
0% {
opacity: 0;
transition: none;
}
100% {
opacity: 1;
transition: none;
}
}
const test = document.getElementById('test');
setTimeout(() => {
test.style.top = "100px"
}, 1000);
I expect if the value of top property is changed by JS, transition transition: top 1000ms doesn't happen because of transition: none that provides #keyframes test, but actually, the transition happens.
I cannot understand why transition value from keyframes doesn't override any existing definition for transition.
let's take another example using display:
.test {
position: relative;
top: 0px;
border: 1px solid #ccc;
animation: test 5s forwards;
}
#keyframes test {
0% {
opacity: 0;
display: none;
}
100% {
opacity: 1;
display: none;
}
}
<div class="test" id="test">
Test text
</div>
We logically expect to never see the element since we set display:none and we made the animation to be forwards but display is simply ignored because it cannot be animated. Same logic with transition since it's a property that we cannot animate ref.
Basically, any property that cannot be animated will simply get ignored when used with keyframes.
Properties that aren't specified in every keyframe are interpolated if possible — properties that can't be interpolated are dropped from the animation. ref
I'm working on this mobile menu where you can expand and collapse different categories. When doing so, a sliding animation should be performed on the expanded submenu (when expanding) or on the top-level menu (when collapsing).
The structure of the HTML is the following:
<div class="slideOpenMainMenu">
<div class="sideMenuGeneral">
...Top-level menu...
</div>
<div class="sideMenuPanelMainChildren">
...Expanded submenu...
</div>
</div>
By adding and removing classes, I show the appropriate div while hiding the other from view. As you'll notice, I go out of my way to not use anything like display:none; since then I won't be able to animate the containers. Instead I use a combination of width, height, visibility and flex properties to hide and show the containers.
/* Menu parent container */
.slideOpenMainMenu {
position: fixed;
width: 100%;
box-sizing: border-box;
background: linear-gradient(90deg, #12416e 0%, #0d3050 100%);
display: flex;
justify-content: center;
}
/* Top-level menu - Initial state */
.sideMenuGeneral {
width: 100%;
max-width: 620px;
display: flex;
flex-flow: column;
padding: 20px 16px 0 16px;
box-sizing: border-box;
overflow: hidden;
}
/* item submenu - Initial state */
.sideMenuPanelMainChildren {
width: 0;
height: 0;
flex: 0 1 0;
max-height: 100vh;
overflow: hidden;
visibility: hidden;
-webkit-overflow-scrolling: touch;
}
/* Top-level menu - Expanded state */
.slideOpenMainMenu.item-expanded .sideMenuGeneral {
width: 0%;
padding: 0 !important;
visibility: hidden;
}
.slideOpenMainMenu.item-expanded .sideMenuPanelMainChildren {
flex: 1 1 auto;
flex-flow: column;
width: 100%;
height: auto;
overflow: scroll;
visibility: visible;
}
For the animation, I use transform:translateY and opacity properties to create the sliding effect I want.
/* Initial state */
.slideOpenMainMenu .sideMenuPanelMainChildren {
opacity: 0;
transform: translateX(30%);
transition: opacity 0.5s ease, transform 0.5s ease, visibility 0s ease;
}
.slideOpenMainMenu .sideMenuGeneral {
opacity: 1;
transform: translateX(0%);
transition: opacity 0.5s ease, transform 0.5s ease, visibility 0s ease;
}
/* Expanded state */
.slideOpenMainMenu.item-expanded .sideMenuPanelMainChildren {
opacity: 1;
transform: translateX(0%);
}
.slideOpenMainMenu.item-expanded .sideMenuGeneral {
opacity: 0;
height: 0px;
transform: translateX(-50%);
}
As you can see on this fiddle, the animation works well in Chrome and Firefox. Not so well on Webkit and Edge. From what I can tell, there seems to be some kind of conflict between the change in width and the transitions, because when I disable changes in width, you can see the animation play out. What could cause the change in behavior between platforms? Is there a way to correctly sequence the changes?
So while writing this question, I arrived at the answer (as it often happens). The issue seems to be rooted in that the sequence of CSS property changes is different on different browsers. by adding a tiny delay (0.01s) to the transform transition I got it to work, like so:
transition: opacity 0.3s ease, transform 0.3s ease 0.01s, visibility 0s ease;
Still, I find this a little odd and also interesting. If anyone has info on how these things are sequenced in the browser that'd be really great to learn.
So i've recently working on some private project, and since i am a huge CSS fan i want to do most of the animations in CSS rather than in JavaScript.
Today i wanted to create something like this:
Text moving from left to right
I think this might be possible with CSS Animations. In theory, I have a div wrapper with position:relative, a fixed width and overflow:hidden. Inside, there is a div with position:absolute and left:0 and bottom:0. Now in some cases, the text is too long for the parent div, and i wanted to let text text "float" though the parent div: actually animating the div from left:0 to right:0.
I stumbled upon some CSS Animations and tried this
#keyframes floatText{
from {
left: 0;
}
to {
right: 0;
}
}
on the child div. And of course this didn't worked. Animations like from left :0 to left: -100px work, but this doesn't ensure that the whole text is visible, when it is longer than those additional 100px. Is there a nice and clean way to make this work? Surely JavaScript might rock this desired functionality. But I'd wanted to know if there is a way to do this in pure CSS.
Thanks in advance!
EDIT:
To clearify what I have in my mind, i've created a gif displaying what i want to accomplish with CSS animations:
Animated
As you see, we have three of that kind next to each other, some have a name which fits directly, some others might be too long and should be animated forth and back, so the user can read it :)!
Thanks again!
EDIT2:
Is there a way to accomplish something like this?
#keyframes floatText{
from {
left: 0px;
}
to {
left: (-this.width+parent.width)px;
}
}
This would be the ultimate solution, I know that this kind of coding is not possible in CSS, but maybe with some CSS3 tweaks like calc() or something? I'm out of ideas now :(
You can stop when your text hits the right border
This solution uses CSS translate.
The trick is that translate's percentages are corresponding to the current element and left referrs to the parent.
Make sure your text's display property is NOT inline.
Downsides of this CSS only approach:
Shorter texts also get animated. To counter that consider JavaScript or make your text min-width: 100%;. This can lead to minimal wiggling by the animation.
All texts get the same amount of animation duration, which can be awful for long texts. Again, consider JavaScript (you'll want to look at scrollWidth) or make many animation classes, which can be very hard to manage.
.animated {
overflow: hidden;
width: 11rem;
white-space: nowrap;
}
.animated > * {
display: inline-block;
position: relative;
animation: 3s linear 0s infinite alternate move;
}
.animated > *.min {
min-width: 100%;
}
#keyframes move {
0%,
25% {
transform: translateX(0%);
left: 0%;
}
75%,
100% {
transform: translateX(-100%);
left: 100%;
}
}
/* Non-solution styles */
.container {
display: flex;
flex-wrap: wrap;
}
.animated {
font-size: 2rem;
font-family: sans-serif;
border: 0.1rem solid black;
margin: 1rem;
}
.animated > * {
box-sizing: border-box;
padding: .5rem 1rem;
}
<div class="container">
<div class="animated">
<span>Short</span>
</div>
<div class="animated">
<span class="min">Short</span>
</div>
<div class="animated">
<span>Some more text</span>
</div>
<div class="animated">
<span>A really long text to scroll through</span>
</div>
</div>
change your keyframe value in %
Try This
body{
overflow: hidden;
}
p{
position: absolute;
white-space: nowrap;
animation: floatText 5s infinite alternate ease-in-out;
}
#-webkit-keyframes floatText{
from {
left: 00%;
}
to {
/* left: auto; */
left: 100%;
}
}
<p>hello text</p>
hi dude i have tried this
Note : but you will find one thing is missing and will see that animation will not reach to the purely left and right i mean you can't
see the whole text of the div.
and that is due to the value of the left and right i have set to the -100 and 100 so because i couldn't find the alternative for that so
right now trying to see that how can you make this happen.
and here is my try
div.main_div{
margin:0;
padding:0;
width: 20%;
height: 60%;
background-color:grey;
position:absolute;
overflow: hidden;
}
div.transparent_div{
width:100%;
height:50px;
bottom:0;
background:red;
position:absolute;
}
div.text_wrapper{
height:50px;
bottom:0;
z-index:10;
background:transparent;
white-space: nowrap;
font-family: Segoe UI,Frutiger,Frutiger Linotype,Dejavu Sans,Helvetica Neue,Arial,sans-serif;
color:white;
font-size:2em;
vertical-align: middle;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
-ms-transition: all 0.3s ease-in-out;
position:absolute;
-webkit-animation: anim 1.5s infinite;
animation: anim 1.5s infinite;
animation-direction: alternate-reverse;
-webkit-animation-timing-function: linear; /* Chrome, Safari, Opera */
animation-timing-function: linear;
}
#-webkit-keyframes anim {
from {
left: -100%;
}
to {
left:100%;
}
}
#keyframes anim {
from {
left: -100%;
}
to {
left:100%;
}
}
<body>
<div class="main_div">
<div class="text_wrapper">Hiii i am going right to left infinete times and here are the news
</div>
<div class="transparent_div"></div>
</div>
</body>
and here you can check out the demo of the above working code
DEMO CODE
Add ease-in-out to the animation for smoothness, and use % instead of px to move it left or right.
we can write jQuery code, for finding over-flow text and enable animation:
function AutoScrollText() {
var els = document.getElementsByClassName('container');
[].forEach.call(els, function myFunction(el) {
var isOverflowing = el.clientWidth < el.scrollWidth;
if (isOverflowing) {
$(el).children('span:first-child').addClass('animated');
}
var curOverf = el.style.overflow;
if (curOverf == "" || curOverf === "visible") {
$(el).css({ "overflow":"hidden"});
}
});
}