How to add a transition when styling display? [duplicate] - javascript

This question already has answers here:
Transitions on the CSS display property
(37 answers)
Closed 1 year ago.
I have a program, where I use JavaScript to make one div appear and another disappear when I click something:
<div id="first" class="active"> some content here </div>
<div id="second" class="inactive"> some content here </div>
<button onclick="change()"> button </button>
function change(){
document.getElementById("first").className="inactive";
document.getElementById("second").className="active"
}
.active{ display: block; }
.inactive{display: none; }
I'd like to make it so that one div fades in while the other fades out.
I've tried transition: ease 1s;, transition: display 1s and using a custom transition, however none of them have worked.
Try clicking the different buttons on this Carrd - the words fade in and out. I'm going for that effect here.
I'd prefer a solution using only HTML, CSS and/or JavaScript -- trying to keep this project simple.

Use opacity:
function change() {
document.getElementById("first").className = "inactive";
document.getElementById("second").className = "active"
}
.active{
opacity:1;
}
.inactive{
opacity:0;
}
div{
transition:opacity 1s;
}
<div id="first" class="active"> some content here </div>
<div id="second" class="inactive"> some content here </div>
<button onclick="change()"> button </button>
To prevent the hidden element from taking up space, use:
function change() {
const f1 = document.getElementById("first");
f1.style.opacity = "0";
setTimeout(() => {
f1.style.display = "none"
const f2 = document.getElementById("second");
f2.style.display = "block";
setTimeout(() => {
f2.style.opacity = "1";
}, 50);
}, 1000);
}
.active {
display: block;
opacity: 1;
}
.inactive {
display: none;
opacity: 0;
}
div {
transition: opacity 1s;
}
<div id="first" class="active"> some content here </div>
<div id="second" class="inactive"> some content here </div>
<button onclick="change()"> button </button>

Related

Making text transition in, with text below moving to make room for text above

I am trying to make the toggled descriptions either slide or fade in, instead of suddenly appear. I also want to preserve the feature of the text moving up and down to accommodate the text that has been toggled on. Ideal situation would be to do this with CSS or Javascript, without jQuery etc.
Already tried CSS opacity transition, but the text doesn't move up and down to accommodate the toggled on text;
function view(id) {
var x = document.getElementsByClassName("descriptions");
var i;
for (i = 0; i < x.length; i++) {
if (x[i].id !== id)
x[i].style.display = "none";
}
var e = document.getElementById(id);
if (e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
.descriptions {
display: none;
}
<div class="toggle" id="a" onclick="view('a1');">Toggle Div 1
<div id="a1" class="descriptions"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>
<div class="toggle" id="b" onclick="view('a2');">Toggle Div 2
<div id="a2" class="descriptions"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>
<div class="toggle" id="c" onclick="view('a3');">Toggle Div 3
<div id="a3" class="descriptions"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>
Maybe something like this using the height?
function view(id) {
let el = document.getElementById(id);
if (el.classList.contains('hide')) {
el.classList.remove('hide');
} else {
el.classList.add('hide');
}
}
.toggle {
overflow: hidden;
}
.descriptions {
max-height: 100px;
transition: all 0.5s ease-in;
}
.hide {
max-height: 0 !important;
transition: all 0.2s ease-out;
}
<div class="toggle" id="a" onclick="view('a1');">Toggle Div 1
<div id="a1" class="descriptions hide"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>
<div class="toggle" id="b" onclick="view('a2');">Toggle Div 2
<div id="a2" class="descriptions hide"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>
<div class="toggle" id="c" onclick="view('a3');">Toggle Div 3
<div id="a3" class="descriptions hide"> Here's some text we want to toggle visibility of. Let's do it!</div>
</div>

Displaying show/hide content with a button and an .active css class

I am trying to create a testimonial section on a wordpress site where there is an "expand" button to show the full testimonial quote. I want the text in the button to change to "collapse" after it is clicked. I also need to add a class to the div wraper so I can implement custom css styling when the button is active. I need this pasted three times. The problem is it fails after the first testimonial.
I have this working with the code below, with it duplicated three times (for three different testimonials) and it works on a basic html document. But when I implement it in a wordpress site by pasting the code, only the first testimonial totally works. The other two do show/hide my inner div element, but they won't insert the .active class or change the text of the button to "collapse"
Both of the second testimonials give a
"Uncaught TypeError: Cannot set property 'innerHTML' of null" in the console.
So for example, here are two out of three of my testimonials I want to show. I have to change the ID's on them to avoid the javascript conflict.
function showhide() {
var content = document.getElementById('hidden-content');
var wrap = document.getElementById('testimonial-wrap');
var btn = document.getElementById('button1');
if (content.style.display === 'none') {
content.style.display = 'block';
wrap.style.background = 'grey';
btn.innerHTML = 'COLLAPSE';
wrap.classList.add('active');
} else {
content.style.display = 'none';
wrap.style.background = 'white';
btn.innerHTML = 'EXPAND';
wrap.classList.remove('active');
}
}
function showhide2() {
var content2 = document.getElementById('hidden-content2');
var wrap2 = document.getElementById('testimonial-wrap2');
var btn2 = document.getElementById('button2');
if (content2.style.display === 'none') {
content2.style.display = 'block';
wrap2.style.background = 'grey';
btn2.innerHTML = 'COLLAPSE';
wrap2.classList.add('active');
} else {
content2.style.display = 'none';
wrap2.style.background = 'white';
btn2.innerHTML = 'EXPAND';
wrap2.classList.remove('active');
}
}
<div id="testimonial-wrap" style="background-color: white;">
<div id="testimonial">
above testimonial content
<div id="hidden-content" style="display: none;">
<p>"hidden content”</p>
</div>
<button id="button1" onclick="showhide()">EXPAND</button>
</div>
</div>
<div id="testimonial-wrap2" style="background-color: white;">
<div id="testimonial">
above testimonial content
<div id="hidden-content2" style="display: none;">
<p>"hidden content.”</p>
</div>
<button id="button2" onclick="showhide2()">EXPAND</button>
</div>
</div>
I think this is what you're looking for. You can do it much easier with jQuery & a small amout of code.
I didn't use display: none as I want to add the transition to the action. (transition won't work with display: none)
$(document).ready(function() {
$(".toggle-button").on("click", function() {
$(this).closest(".testimonial-wrap").toggleClass("active");
});
});
.testimonial-wrap {
background-color: #C1C1C1;
padding: 5px;
margin-bottom: 10px;
}
.testimonial-wrap.active {
background-color: #0095FF
}
.hidden-content {
height: 0px;
visibility: hidden;
transition: all 0.5s ease-out;
}
.active .hidden-content {
height: 100px;
visibility: visible;
transition: all 0.5s ease-in;
background-color: rgba(0, 0, 0, 0.5);
}
button {
display: inline-block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="testimonial-wrap">
<div id="testimonial">
<p>above testimonial content</p>
<div class="hidden-content">
<p>"hidden content”</p>
</div>
<button id="button1" class="toggle-button">EXPAND</button>
</div>
</div>
<div class="testimonial-wrap">
<div id="testimonial">
<p>above testimonial content</p>
<div class="hidden-content">
<p>"hidden content.”</p>
</div>
<button id="button2" class="toggle-button">EXPAND</button>
</div>
</div>

document.getElementById can't select more than one element

I'm working on loading. I have div #loading which is visible. And more divs #message which are hidden. I have js function.
function loading() {
setTimeout(function() {
document.getElementById("loading").style.display = "none";
document.getElementById("message").style.display = "block";
}, 500, "fadeOut");
}
But that row document.getElementById("message").style.display = "block"; selects only first div #message.
function loading() {
setTimeout(function() {
document.getElementById("loading").style.display = "none";
document.getElementById("message").style.display = "block";
}, 500, "fadeOut");
}
loading();
#loading {
display: block;
}
#message {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="messages" onload="loading();">
<div id="loading">
...
</div>
<div id="message">
QWERTY
</div>
<div id="message">
123456
</div>
</div>
As the others have mentioned ids are unique and can only be used once on a page, so use a class instead. Here I've used querySelectorAll to grab a static list of classes.
The other issue is that you seem to be trying to use jQuery to fade the elements out, but you're not using jQuery for anything else. I'm going to suggest you CSS transitions. They're easy to use, and you don't have the need of loading a huge library. Here I add new classes fadein and fadeout which (based on your code) increases/reduces the opacity of the specified elements to zero over three seconds.
function loading() {
setTimeout(function() {
// use a class for the loader too otherwise the transition
// won't work properly
const loader = document.querySelector('.loading');
loader.classList.add('fadeout');
// grab the elements with the message class
const messages = document.querySelectorAll('.message');
// loop over them and add a fadeout class to each
[...messages].forEach(message => message.classList.add('fadein'));
}, 500);
}
loading();
.loading {
opacity: 1;
}
.message {
opacity: 0;
}
.fadein {
transition: opacity 3s ease-in-out;
opacity: 1;
}
.fadeout {
transition: opacity 3s ease-in-out;
opacity: 0;
}
<div class="messages">
<div class="loading">
Loading
</div>
<div class="message">
QWERTY
</div>
<div class="message">
123456
</div>
</div>
You need to use unique ID's for your DOM elements. Try modify your code like this:
<script type="text/javascript">
function loading() {
setTimeout(function() {
document.getElementById("loading").style.display = "none";
var el = document.getElementsByClassName('message');
console.log(el);
$.each(el, function(i, item){
item.style.display = 'block';
});
}, 500, "fadeOut");
}
loading();
</script>
<style>
#loading {
display: block;
}
.message{
display: none;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="messages" onload="loading();">
<div id="loading">
...
</div>
<div class="message">
QWERTY
</div>
<div class="message">
123456
</div>
</div>
ID attribute must be unique. You can't use same ID multiple times on the page. If you like to use same key then use it as a class or data-id which can be same or differ.
You cannot have same id twice in a document in order to select multiple elements group them by same Class rather than by id and then use the following to select them all.
document.querySelectorAll(".ClassName")
Or
document.getElementsByClassName(".ClassName");
Note that both methods returns a collection of all elements in the document with the specified class name, as a NodeList object.
function loading() {
setTimeout(function() {
document.getElementById("loading").style.display = "none";
document.getElementById("message").style.display = "block";
}, 500, "fadeOut");
}
loading();
#loading {
display: block;
}
#message {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="messages" onload="loading();">
<div id="loading">
...
</div>
<div id="message">
QWERTY
</div>
<div id="message">
123456
</div>
</div>

How can I select the child of a sibling element?

My accordion keeps filling up the space of my div bigger and smaller based on it opening and closing. I want to wrap a div around it and set it to the height of the accordion expanded to prevent this behavior. Trouble is my js is dependent on selecting this.nextSibling and that breaks everything.
var acc = document.getElementsByClassName("review-button");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].onclick = function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight){
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + 'px';
}
}
}
It must be using "this" within scope because there are multiple accordions.
My original thought was to do something like...
this.nextElementSibling.children[0];
but that didn't work.
how do I wrap the current content in a div with a set height, while still keeping the accordion functionality?
<!--accordion 1-->
<button class="review-button" data-target="#demo{{ gameIndex }}">
<span class="review-button-chevron fa fa-angle-down"></span>
Our Reviews
</button>
<!-- Slide out -->
<div class="quote-machine-container">
<div id="demo{{ gameIndex }}" class=" quote-machine"></div>
</div>
<!--accordion 2-->
<button class="review-button" data-target="#demo{{ gameIndex }}">
<span class="review-button-chevron fa fa-angle-down"></span>
Our Reviews
</button>
<!-- Slide out -->
<div class="quote-machine-container">
<div id="demo{{ gameIndex }}" class=" quote-machine"></div>
</div>
Placed each <header> and <div> in it's own <section>
Wrapped everything in <main> and added an eventListener() to it. Any clicks to it will be delegated to the header that was clicked (e.target.)
The event handler (acc()) will:
determine what is e.target (clicked node) by comparing it to the e.currentTarget (the node being captured at the moment.)
Once established, e.target will lose or gain the .active class.
In order to eliminate the limiting property of nextElementSibling, we replace that functionality with a simple CSS ruleset: .active + .x-panel which is basically the same as nextElementSibling.
SNIPPET
var main = document.getElementById("x-main");
main.addEventListener('click', acc, false);
function acc(e) {
if (e.target !== e.currentTarget) {
var tgt = e.target;
tgt.classList.toggle("active");
}
}
.x-section {
height: 100px;
}
.x-header {
cursor: pointer;
border: 3px outset grey;
height: 30px;
}
.x-panel {
border: 3px inset black;
max-height: 0;
opacity: 0;
transition: opacity .2s ease-in;
}
.active + .x-panel {
opacity: 1;
max-height: 300px;
overflow-y: hidden;
transition: max-height 1s ease-in .1s, opacity 1s;
}
<main id='x-main'>
<section class='x-section'>
<header class='x-header'>HEADER</header>
<div class='x-panel'>
CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT
</div>
</section>
<section class='x-section'>
<header class='x-header'>HEADER</header>
<div class='x-panel'>
CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT
</div>
</section>
<section class='x-section'>
<header class='x-header'>HEADER</header>
<div class='x-panel'>
CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT CONTENT
</div>
</section>
</main>

menu expandable CSS script on hover or Onclick on a link / button

I want to create a css with following specifications :
When I click on a link / button in a form, it should expand its options horizontally.
It should collapse after selecting the option.
EDIT:
To elaborate my query, let me attach the few images which will explain the exact query.
Step 1. Onhover or OnClick on Image Field, it should expand a Div included with 4 Images.
Step 2. If I select one of the Four Image, the collapse the Div and Display the Selected image in the Image field.
Please suggest the best possible code.
well..hopefully i have understood you correctly..
var expandFn = function(){
var wrappBl = document.getElementsByClassName('expand')[0];
var trigg = document.getElementById('trigger');
var el = document.getElementsByTagName('input');
var elArr = [].slice.call(el);
this.getAction = function(){
trigg.addEventListener('click', function(){
if(wrappBl.classList.contains('active')){
wrappBl.classList.remove('active');
}
else {
wrappBl.classList.add('active');
}
});
}
getAction()
this.checkIf = function(){
for (var i = 0; i < elArr.length; i++) {
elArr[i].addEventListener('click', function(){
if( this.checked === true){
wrappBl.classList.remove('active');
};
})
}
}
checkIf();
}
setTimeout(function(){expandFn();},0)
.expand input,
.expand label{
display: block;
width: 50%;
}
div.expand{
width: 100px;
-webkit-transition: transform 400ms ease, opacity 400ms ease;
transition: transform 400ms ease, opacity 400ms ease;
visibility:hidden;
opacity: 0;
}
div.expand.active{
visibility: visible;
opacity: 1;
}
<div class="wrap">
<a id="trigger" href="#">expand</a>
<div class="expand">
<h4>title of the option</h4>
<input name="option1" type="checkbox">
<label for="option1">choose that</label>
<input name="option2" type="checkbox">
<label for="option2">choose that</label>
<input name="option3" type="checkbox">
<label for="option3">choose that</label>
</div>
</div>

Categories