I am trying to create an accordion with React. I asked a question on this previously on StackOverflow in terms of, how do I assign classes to an accordion on click and open multiple at once. Somebody linked me the below code sandbox which will toggle a background colour on click.
https://codesandbox.io/s/nice-http-n0omm?file=/src/App.js
So, I have tried to put it into my code to open and close the accordion, and it will not transition no matter what I do. It is an instant change and I can't seem to figure out why. I have also tried making the transition from a bg colour of blue, to red, and same thing, it instantly changes with no transition.
Can somebody look at my code and help figure it out?
The only difference I have noticed in the difference between the code sandbox and my code, is that on the sandbox version, on the dom using inspect element, when the button is clicked, only the selected element flashes purple (chrome) to indicate something is changed. On my version, EVERY instance of the map flashes purple, to indicate that all the elements mapped out have been affected in some way.
const [accordionOpen, setAccordionOpen] = useState([]);
function openAccordion(num) {
setAccordionOpen((state) => {
return state.includes(num)
? state.filter((n) => n !== num)
: [...state, num];
});
}
return parsedData.map((data) => {
<>
<div
className="mortgage_moreinfo"
onClick={() => openAccordion(data.ProductCode)}
key={data.ProductCode}
>
<p>More Info</p>
</div>
</>
})
SCSS
.accordionClosed {
transition: all 1s ease;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
.accordionOpen {
max-height: 101px !important;
}
Try something like this for your scss:
.accordion {
max-height: 0;
overflow: hidden;
transition: all 1s ease;
transition: max-height 0.2s ease-out;
}
.accordion.open {
max-height: 101px !important;
}
And for your React Component:
<div className=`accordion ${ConditionForOpeningTheAccordion ? 'open' : ''}`>
</div>
So you are basically having a .accordion class wich defines the basic style for your accordion, but with your height of 0px. And when your condition for opening the accordion is met you are adding the .open class to the accordion wich has a width of 101px. This should ensure, that your transition gets played every time the .open class gets removed or added to the accordion.
I hope my explanation helps you. If not I can provide a codesandbox or something like that.
Related
I have one div, with buttons that trigger JS functions to add/remove CSS classes to the div. I understand this is a common way of doing simple animations ("transitions"). Try pressing the first two buttons, one after another. The red div will teleport up and become semi transparent, then fade in and slide back down. It always works.
The third button simply executes the same code as the first two buttons, but from one function. I expected it to have the same visible effect: the div immediately would jump up from the translate and be transparent, then during the course of 1 second it would slide back to its normal spot and fade in to full opacity. But it does not - the button has no visible effect.
Why? How can I make this work?
Here is the JS, see the whole thing at the codepen link.
const div = document.getElementById('red-box')
function translateUp() {
div.classList.remove('no-translate');
div.classList.add('translate-up');
}
function noTranslate() {
div.classList.remove('translate-up');
div.classList.add('no-translate');
}
//why does this function not show any transition animation?
function both() {
translateUp();
noTranslate();
}
https://codepen.io/DMcCreepy/pen/BampPyB
No jQuery please :)
The reason is that the functions are executed immediately one after the another, with no time to see the effect. transition in CSS refers to when the class is applied (could be related to a CSS state like :hover), not to switching classes via JavaScript.
To add the 1 second delay in the JS, you can use window.setTimeout:
function both() {
translateUp();
window.setTimeout(noTranslate, 1000);
}
You are relying on the div getting rerendered and all its properties being recomputed before switching the class again with the second function. I am not sure entirely what order things are done in under the hood, but I am sure you cannot rely on constructions like this working in general. It is true that switching classes is a common way to do animations and maybe it is possible to work out a solution like that, but I have provided a workaround using a CSS animation. You can read more about animations here https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations
const div = document.getElementById('red-box')
div.addEventListener('animationend', reset);
function reset() {
div.classList.remove('dropin');
}
function both() {
div.classList.add('dropin');
}
button {
display: block;
}
.box {
height: 70px;
width: 80px;
font-size: 50px;
background-color: red;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-name: none;
}
.box.dropin {
animation-name: dropin;
}
#keyframes dropin {
from {
transform: translate(0, -40px);
opacity: 0.1;
}
to {
transform: translate(0, 0);
opacity: 1;
}
}
<div id="red-box" class="box">div</div>
<button onclick='both()'>Do Both</button>
My Intention:
Using the Vue.js (v2) attribute [v-cloak], I want to have the "app" hidden until ready. When [v-cloak] is removed, I want the "app" to fade in. Using CSS opacity and transitions to achieve the fade.
The Problem:
When [v-cloak] is removed from my "app" there is no transition as I would expect. It just goes from hidden to visible immediately. Seems to ignore the CSS.
Example:
I have made an exaggerated example with Vue.js and a JavaScript simulated version to show how they both behave.
https://codepen.io/freemagee/pen/wXqrRM
When viewing this example, you will see the "Plain old JavaScript" red box fade into view over 5 seconds. But the Vue controlled version just appears without a fade. They share the same CSS for the transition, so in theory should work the same way.
Anyone used [v-cloak] effectively to achieve smooth transitions?
Codepen Code
HTML
<div id="app" v-cloak>
<div class="red-box"></div>
<p>Vue.js {{ message }}</p>
</div>
<div id="app2" v-cloak>
<div class="red-box"></div>
<p>Plain old JavaScript</p>
</div>
CSS
html,
body {
margin: 0;
height: 100%;
min-height: 100%;
}
[v-cloak] .red-box {
opacity: 0;
visibility: hidden;
transition: visibility 0s 5s, opacity 5s linear;
}
#app,
#app2{
padding-top: 50px;
}
.red-box {
margin: 0 auto;
width: 100px;
height: 100px;
background: red;
opacity: 1;
visibility: visible;
transition: opacity 5s linear;
}
p {
text-align: center;
}
JS
new Vue({
el: "#app",
data: {
message: "Hello world"
}
});
window.setTimeout(function() {
document.getElementById("app2").removeAttribute("v-cloak");
}, 500);
This won't work because after the Vue app instance initializes, the #app div is actually removed, re-rendered and becomes a different div, even though it looks the same. This is probably due to Vue's virtual DOM mechanism.
The #app2 elements is still the same DOM after document.getElementById("app2").removeAttribute("v-cloak");: https://codepen.io/jacobgoh101/pen/PaKQwV
The #app element is a different DOM after new Vue(...): https://codepen.io/jacobgoh101/pen/ERvojx?editors=0010
For the Vue app, the element with v-cloak is removed, another element without v-cloak is added back. There is no element that transition from "with v-cloak" to "without v-cloak". That's why the CSS transition won't work. Hope that this is clear enough.
(If you don't already know this, )You can use Transition Component
As explained, there is no transition possible with [v-cloak], as the DOM element without the v-cloak is a new one.
I've figured a simple workaround, using the mounted methods and its hook vm.$nextTick(), in which case, the use of v-cloak isn't necessary anymore.
Mounted is called when the original app element has been replaced with the new one generated by Vue, but it doesn't necessarily mean that every child has been rendered yet. nextTick is called when every child element has been rendered inside the app view.
First, I have setup my HTML app element like this :
<div id="main-view" :class="{ready: isPageReady}">...</div>
In my vue app :
new Vue({
el: "#main-view",
data: {
isPageReady: false,
[...]
mounted: function() {
this.$nextTick(function () {
this.isPageReady = true;
});
}
});
Finally in the CSS, I tried a simple fadein using opacity:
#main-view {
opacity: 0;
}
#main-view.ready {
opacity: 1;
transition: opacity 300ms ease-in-out;
}
Beware: the transition doesn't always show if you have the browser's inspector/debugger open.
I am hoping someone can help!
I am trying to add bootstrap support to an existing jQuery/CSS site. Aside from realizing bootstrap changes a bunch of formatting that I have to fix - it seems to be affecting a popup transition I have, and can't seem to figure out. I hope you can help, thanks!
With regular jQuery/CSS (not UI), I am creating a modal dialog box that I popup.
BEFORE bootstrap - it would "fade" in the popup box (i.e., the opacity/alpha). However, AFTER adding the bootstrap .css/.js - now it just
makes the background grey and totally opaque.
How do I fix it?
This is the code that works with just css/jQuery
<div class=sample-dialog>
<div class=modal-overlay>
<div class=modal-content>
<div class=modal-body>
random content
</div>
</div>
</div>
</div>
then the jQuery popup code that I call
function showModal() {
var m = $('.sample-dialog');
var o = m.find('.modal-overlay');
var c = m.find('.modal-content');
var b = c.find('.modal-body');
m.css('display','block');
o.animate({'opacity':.8},350);
b.animate({'opacity':1,'margin-top':0},350,function() {
c.css('overflow-y','auto');
});
}
This "works" with just the jQuery/css.
HOWEVER, as soon as I add the bootstrap .js/.css file in my header, the exact same transition now shows no opacity (just a grayed out background).
Any idea on how to fix?
As a second thing - I also notice with the bootstrap files added, the transition seems to be 'choppy' as opposed to the nice 'smooth' one I had. If you have insight for that too, that would be great!
Thanks very much!
It may be that the rules of bootstrap transitions are creating conflict, I remember working with version 4.0.0-alpha.6 it was impossible to modify the transition of the height in a model.
These would be the default values of the modal transition (
with the .fade class)
_transitions.scss
.fade.show {
opacity: 1;
}
.fade {
opacity: 0;
-webkit-transition: opacity 0.15s linear;
-o-transition: opacity 0.15s linear;
transition: opacity 0.15s linear;
transition-property: opacity;
transition-duration: 0.15s;
transition-timing-function: linear;
transition-delay: initial;
}
This I think could help you;
Enables predefined transitions on various components
$enable-transitions: true (default) or false
Documentation bootstrap#4.0.0-alpha.6 /Customizing variables
Sorry if the bootstrap version does not help, but it's the only version I've worked with.
Now i am officially desperated. I bought a Script to use a MegaMenu on my Site.
The Script is MegaNavBar 2.2
http://preview.codecanyon.net/item/meganavbar-v-220-advanced-mega-menu-for-bootstrap-30/full_screen_preview/8516895?_ga=2.119686542.744579007.1495443523-2131821405.1495443282
I wanted the script to open the submenus on hover, so i configured it as described on the Demo-Page (see above).
This worked fine. But i wanted to add a delay, because its irritating users, if they move the mouse pointer from top to bottom, and everytime the menu is open immediately while hovering.
What i tried:
Asking the support - No Answer
Trying to add an animation and animation-delay
The Animation is working, but the delay is not working, i assume because of the "display:block"
Trying to add an transition
The Transition is not working, because Transition is not working with "display:block".
Is there anybody out there, who can help me with this stuff?
Here is my Bootply:
https://www.bootply.com/A50M0Wk9NK
(The assumed css rule is in line 29 of pasted css-code)
Best Regards,
Michael
You can try to use Visibility instead of Display, and thus use transitions.
e.g.:
div > ul {
visibility: hidden;
opacity: 0;
transition: visibility 0s, opacity 0.5s linear;
}
div:hover > ul {
visibility: visible;
opacity: 1;
transition-delay:2s; //set delay here
}
more precisely, I've seen websites where there's a kind of header image, which loops through 3-4 different images, and each image is referenced by a dot, and you can pick the image you want by clicking the dot as well. I'm sure everyone has seen this somewhere.
as an example, go to http://www.tsunamitsolutions.com/
my question is, how do I make these dots appear/disappear when I hover on the image (like on the site I shared above) is it javascript or can this be accomplished just in the CSS with the "hover" style.
In other words, can hovering over one html portion/div/section make another div/section appear/disappear just by using CSS?
It can be done in the CSS.
Assuming the dots/arrows are child elements of banner container, you can do something like:
.bannerContainerClass .dotClass {
display: none;
}
.bannerContainerClass:hover .dotClass {
display: block;
}
You can also do it in jQuery if you need effects like fade:
$(".bannerContainerClass").hover(function() {
$(this).children(".dotClass").fadeIn(500);
}, function() {
$(this).children(".dotClass").fadeOut(500);
});
The jQuery method can be modified to work even if the dots aren't children of banner container.
You can accomplish it using Jquery and javascript. As in any website header images there is a tag for image one tag for collection of those points.
Suppose.
<div id="header_image">
..code for header image..
</div>
which is header tag. and there is a tag which cointains the points.
<div id="points_container">
..code for points...
</div>
Now in its javascript code if you want to disappear "points_container" tag when mouse is hovered over "header_image".and appears again when mouse is hovered out, you can write in its Javascript code.
$(document).ready(function(){
$("#header_image").hover(function(){
$("#points_container").hide();
},function(){
$("points_container").show();
});
});
You can use css on hover with either the visibility attribute or opacity attribute to hide an object, the full implementation of a gallery widget like this is somewhat more complicated though. CSS solution:
.dots:hover
{
opacity:0;
}
Makes anything with the dots class invisible on mouse over.
Or if you don't want it to take up any space when invisible:
.dots:hover
{
display:none;
}
Try this with simple CSS transitions, like this
HTML
<div id="parent"><br/><span class="bullets">* * * *</span></div>
CSS
.bullets{
opacity:1;
}
#parent:hover > .bullets{
opacity:0;
transition: opacity .2s ease-out;
-moz-transition: opacity .2s ease-out;
-webkit-transition: opacity .2s ease-out;
-o-transition: opacity .2s ease-out;
}
FIDDLE HERE>>