Set transition for specific property in javascript doesn't work - javascript

I am using transition(0.3s) in CSS when hover some texts for changing the color, but I also used transition in Javascript for "translate" the text. My problem now is that, when I hover them, they don't use anymore the transition in CSS (0.3s) but what I set in javascript. I tried using element.style.transition = "translate 5.4s ease" or in css I set delay for specific property but in vain.How can i set the transition in Js only for translate? Thank you in advance
CSS
social-media-texts p {
position:relative;
color:white;
font-size:20px;
transition: opacity 0.3s;
transform: translate(-300%);
opacity: 0;
}
JavaScript
socialTexts.forEach((element) => {
element.style.opacity = "1";
element.style.transform = "translate(0)";
element.style.transition = 1.1 * countP + "s";
countP += 0.3;
});

It is because you are overwriting the previous transition property. You would need to expand it by adding a comma followed by your new transition (eg. transform 1.1s)
That would result in the following property: transition: opacity 0.3s, transform: 1.1s;
See section Change Several Property Values: https://www.w3schools.com/css/css3_transitions.asp

Related

How can I control CSS transitions and animations with JS?

I have an image that goes from opacity 0 to 1 when a bit of text is hovered. I would like the transition to be smooth, something similar to CSS transition. Can't really figure out how to make this happen, so any help would be appreciated.
The JavaScript looks like this:
document.getElementById("text-hover").addEventListener("mouseover", imageTransition);
document.getElementById("text-hover").addEventListener("mouseout", imageTransitionOut);
function imageTransition() {
document.getElementById("pic").style.opacity = "1";
}
function imageTransitionOut() {
document.getElementById("pic").style.opacity = "0";
}
Just define the transition in css, it will trigger when you change the opacity value in javascript:
#pic {
transition: opacity .3s;
opacity: 0;
}
You don't need to change your javascript
Update
If you need to animate more than one property, it is better to define the animation in css and then trigger it from javascript by toggling a class on the element
the css:
#pic {
transition: all .3s;
opacity: 0;
transform: scale(.1);
}
#pic.animate {
opacity: 1;
transform: scale(1);
}
javascript:
var textHover = document.getElementById("text-hover");
var pic = document.getElementById("pic");
textHover.addEventListener("mouseover", function() {
pic.classList.add('animate');
});
textHover.addEventListener("mouseout", function() {
pic.classList.remove('animate');
});

Css transition manifests only inside timeout function

I've created new div using JavaScript and set its width and height. Immediately after that I need to resize it to 100% width with transition effect. But it manifests only when the styles editing is inside of Timeout function. Without that it just jump to new width.
Css:
#project-detail {
#extend .project-detail-preview;
transition: width 0.25s ease-out, top 0.25s ease-out, left 0.25s ease-out, height 0.25s ease-out;
}
Script:
var detailContainer = document.createElement("div");
detailContainer.id = "project-detail";
detailContainer.innerHTML = previewContent.innerHTML;
detailContainer.style.width = previewWidth;
detailContainer.style.height = previewHeight;
blocksContainer.appendChild(detailContainer);
for (let project of source.projects) {
if(project.id == projectID) {
setTimeout(function () {
detailContainer.style.width = "100%";
}, 1);
}
}
JS is single threaded if you change width to 20 and then to 100, the change to 20 is like if didn't happen. so you need to use a setTimeout() so it first changes it to 20, and "later" it changes to 100
I believe this is because you append the div to the DOM, and immediately (next line of code), you resize it to 100% width.
The problem is that in the page's life cycle, the CSS doesn't have time to catch up and apply between these two lines of code. So, the transition duration is not yet applied, and you already resize the div, so it jumps immediately to 100%.
On the other hand, when you set a Timeout, being asynchronous, the function inside the Timeout is executed at the end of the execution stack, that is, after applying the CSS rules to the newly created elements. You can even set a 0 delay or no delay at all, it will work all the same.
I tried to do things like this with JS, even read bunch of articles about requestAnimationFrame and understood, that things like that better to do with CSS classes. Try to toggle class on action:
for (let project of source.projects) {
if(project.id == projectID) {
detailContainer.className += ' fullwidth-class';
}
}
And add same CSS class:
.fullwidth-class {
width: 100%!important;
}
#project-detail {
animation-duration: 1s;
}

Rotate function

Why isn't this working? I need it for a school project. It should be simple.
var Rotate = function(d){
$(".fab").css({
'-webkit-transition-duration: 1s; /* Safari */',
'transition-duration: 1s;',
'-moz-transform':'rotate('+d+'deg)',
'-webkit-transform':'rotate('+d+'deg)',
'-o-transform':'rotate('+d+'deg)',
'-ms-transform':'rotate('+d+'deg)',
'transform': 'rotate('+d+'deg)'
});
}
AKS's answer has what's wrong with your syntax, but the way you're attempting to use the transition property is incorrect. You need to have the transition defined first, and then perform some css change to trigger the transition. From what you've shown us, you have the trigger part only.
Some basic CSS you could use is
.fab {
-webkit-transition-duration: 1s;
transition-duration: 1s;
}
And your JavaScript becomes
var Rotate = function(d){
$(".fab").css({
'-moz-transform':'rotate('+d+'deg)',
'-webkit-transform':'rotate('+d+'deg)',
'-o-transform':'rotate('+d+'deg)',
'-ms-transform':'rotate('+d+'deg)',
'transform': 'rotate('+d+'deg)'
});
}
Note that this will perform the transition for any property that can use a transition, so you may want to be more specific using transition: transform 1s; as your CSS instead.
You can read up about transitions more here. Also here is a working fiddle
var Rotate = function(d){
$(".fab").css({
'-webkit-transition-duration': 1s,
'transition-duration': 1s,
'-moz-transform':'rotate('+d+'deg)',
'-webkit-transform':'rotate('+d+'deg)',
'-o-transform':'rotate('+d+'deg)',
'-ms-transform':'rotate('+d+'deg)',
'transform': 'rotate('+d+'deg)'
});
}
So were using a string
'-webkit-transition-duration: 1s; /* Safari */',
'transition-duration: 1s;',
instead use key value pair like you used for transform or rotate:
'-webkit-transition-duration': 1s,
'transition-duration': 1s,

Dynamically set css transform before transition

I am trying to simulate a mouse animation. I would like to dynamically set the position, then move it with a css transition. So far I am able to get a program that moves the mouse. However, I am having trouble setting the initial position dynamically with javascript. My code looks like this:
Here is the CSS
.cursorDiv {
width: 30px;
height: 30px;
transform: translate(0px,0px);
transition: 2s ease;
}
.cursorDivMoved {
transform: translate(100px,200px);
}
Here is the javascript:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro- style/512/cursor.png";
document.body.appendChild(cursorDiv);
setTimeout(function() {
$(".cursorDiv").toggleClass("cursorDivMoved");
}, 1000);
//cursorDiv.style.transform="translate(100px,50px)";
When I run this it works fine. However, when I try to change the initial position with javascript (uncomment last line), then the transition doesn't occur anymore.
Here is a Demo:
https://jsfiddle.net/fmt1rbsy/5/
If you programmatically set the style.transform property directly on your element (which you need if you want to move it to an arbitrary position through JS), it will override any transform specified in classes. Hence adding "cursorDivMoved" class later on does not transform (translate / move) it.
You have to continue moving it by specifying its style.transform property, or simply remove it: cursorDiv.style.transform = null
Demo: https://jsfiddle.net/fmt1rbsy/9/
You may also want to have the very first translate being transitioned. In that case, you have to wait for the browser to make an initial layout with your element at its start position, otherwise it will see no transition (it will see it directly after the transform is applied, i.e. at its final position). You can either:
Use a small (but non zero) setTimeout to give some time for the browser to do its initial layout.
Force a browser layout by trying to access some property that require the browser to compute the page layout (e.g. document.body.offsetWidth).
Use 2 nested requestAnimationFrame's before applying your transform.
Demo: https://jsfiddle.net/fmt1rbsy/8/
Is this what you are looking for? Tell me if it can be improved. Open your console and change the class name to cursorDivMoved.
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.id = 'cursorDiv';
cursorDiv.src = "https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
#cursorDiv {
width:30px;
height:30px;
-o-transition: 2s ease;
-moz-transition: 2s ease;
-webkit-transition: 2s ease;
-ms-transition: 2s ease;
transition: 2s ease;
}
.cursorDivMoved {
-o-transform:translate(100px, 200px);
-moz-transform:translate(100px, 200px);
-webkit-transform:translate(100px, 200px);
-ms-transform:translate(100px, 200px);
transform:translate(100px, 200px);
}
You can define initial postion (x,y), and then when user click the position will increase and set to the 'cursorDiv', such as:
var cursorDiv = document.createElement("img");
cursorDiv.className = "cursorDiv";
cursorDiv.src="https://cdn2.iconfinder.com/data/icons/windows-8-metro-style/512/cursor.png";
document.body.appendChild(cursorDiv);
var x = 100, y = 50;
setTimeout(function() {
cursorDiv.style.transform="translate(100px,50px)";
}, 1000);
$(document).click(function () {
x+= 20;
y += 50;
var str = "translate(" + x + "px," + y + "px)";
cursorDiv.style.transform=str;
});
Here is Demo

jQuery equivalent for css selector progress::-webkit-progress-value

I need to adjust the transition time for a HTML5 <progress>-Bar with JS (jQuery) but I cannot find the right selector in jQuery doing this.
My current tries:
CSS:
progress::-webkit-progress-value {
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-o-transition: all 0.5s;
-ms-transition: all 0.5s;
transition: all 0.5s; /* Works like a charm */
}
JavaScript (with no success):
// These lines do nothing when the progress value changes:
$(".progressSelectorClass[progress-value]").css({"-webkit-transition" : "all 6s"});
$(".progressSelectorClass > *").css({"-webkit-transition" : "all 6s"});
$(".progressSelectorClass").css({"-webkit-transition" : "all 6s"});
// This gets an error:
$(".progressSelectorClass::-webkit-progress-value").css({"-webkit-transition" : "all 6s"});
Is there any chance to select the progress::-webkit-progress-value in JavaScript (with or without jQuery)?
In this jsFiddle you will see more clearly what I try to do:
http://jsfiddle.net/rD5Mc/1/
Update:
I got the effect with an ugly workaround by adding/change a data-animation-time parameter to the <progress>-element and created several css-classes like this:
progress[data-animation-time="5"]::-webkit-progress-value { -webkit-transition: all 5s; }
progress[data-animation-time="10"]::-webkit-progress-value { -webkit-transition: all 10s; }
progress[data-animation-time="15"]::-webkit-progress-value { -webkit-transition: all 15s; }
progress[data-animation-time="20"]::-webkit-progress-value { -webkit-transition: all 20s; }
progress[data-animation-time="25"]::-webkit-progress-value { -webkit-transition: all 25s; }
...
It works, but I'm very unhappy with my solution. There must be a better way...
You can use the javascript to modify the css rules!
var rule;
$(".animationtimeFirst").change(function() {
time = $(this).val();
// Write out out full CSS selector + declaration
s = '.progressselector::-webkit-progress-value { -webkit-transition: all ' + time + 's; }';
// Check the rules
// If there's no rules,
if ((!rule && rule !== 0) || !document.styleSheets[0].cssRules.length) {
// Make one! -- Insert our CSS string into the page stylesheet
rule = document.styleSheets[0].insertRule(s, 0);
// I think this code is different in IE, beware!
console.log('Our rule is #' + rule);
} else {
// If we already have a rule we can change the style we've implement for the psuedo class
document.styleSheets[0].rules[rule].style.webkitTransitionDuration = time.toString() + 's';
}
});
Here's an updated fiddle: http://jsfiddle.net/trolleymusic/MHYY8/3/ -- hope it helps :)
progress::-webkit-progress-value is not a DOM-Element (it's part of the Shadow DOM, though). So you cannot acccess it with jQuery or any DOM method.
It all comes down to a workaround like yours.
EDIT:
It turns out that in recent versions of Chrome you actually can access the Shadow DOM with the webkitShadowRoot property. Unfortunately it does not work for the <progress /> element.

Categories