randomize number (on a range) on css transform: translateX - css

I have this animation, I would like to randomize the translateX value with a specific range.
#peperone{
position: relative;
z-index: 7;
animation: droppepper 4s linear forwards;
animation-iteration-count: infinite ;
}
#keyframes droppepper{
from {
transform: translateY(-400px) translateX(-90%) rotate(0deg);
}
to {
transform : translateY(1000%) translateX(-30%) rotate(180deg);
}
}
I saw a lot of answers here on stackoverflow and other pages as well, but I can't put it to work..
I tried with
.random(#min, #max) {
#random: `Math.round(Math.random() * (#{max} - #{min}) + #{min})`;
}
and adding .random(-100, -20); into #peperone, but then I don't know how to use that number inside the transform translateX().
Is this doable or am I pretending too much? :P
If so, can you help me out?
Thanks

You can generate a random number with Javascript and update a set css variable, I included an example below.
const randomInt = Math.floor(Math.random() * (100 - 20 + 1) + 20)
console.log('translateX will animate to: ',randomInt*-1 + "%");
const root = document.documentElement;
root.style.setProperty('--random-int', randomInt*-1 + "%");
document.getElementById('guide').style.width = randomInt + "%";
document.getElementById('guide').textContent = randomInt + "%";
:root {
--random-int: -50%;
}
html, body {
margin: 0;
}
#peperone{
position: relative;
z-index: 7;
animation: droppepper 4s linear forwards;
animation-iteration-count: infinite;
width: 100px;
line-height: 100px;
background: #333;
color: #fff;
font-size: 0.9rem;
position: relative;
margin: 2rem 0;
height: 100px;
}
#guide {
position: absolute;
top: 0;
left: 0;
background: red;
height: 100%;
}
#keyframes droppepper{
from {
transform: translateX(100%);
}
to {
transform: translateX(var(--random-int));
}
}
<div id="peperone"><div id="guide"></div></div>

Related

Adding 3D Hover Over Effect on Image with Custom CSS?

Trying to achieve this effect when hovering over the images, can this be achieved with just CSS?
https://mansun.co.uk/music/
Thanks in advance!
}
.product_med img:hover {
-webkit-transform: rotate(360deg);
transform: rotate3d(3, 3, 1, 360deg);
-webkit-transform-style: preserve-3d;
}
.product_med img {
border-radius: 50%;
transition: all 0.4s cubic-bezier(0.12,0.65,0.4,1);
-webkit-transition: all 2.27s ease-out;
}
To create such a tilting 3D effect, you might want to use transform and perspective.
Since tilting on mousemove cannot be solved using CSS alone, use JavaScript:
const element = document.querySelector('.pane');
const tiltDeg = 15;
element.addEventListener('mousemove', ({
clientX,
clientY
}) => {
const bcr = element.getBoundingClientRect();
const rotX = ((clientY - bcr.top) / bcr.height * 2 - 1) * tiltDeg;
const rotY = ((clientX - bcr.left) / bcr.width * 2 - 1) * -tiltDeg;
element.firstElementChild.style.transform = `rotateX(${rotX}deg) rotateY(${rotY}deg)`;
});
element.addEventListener('mouseleave', () => {
element.firstElementChild.style.transform = `rotateX(0deg) rotateY(0deg)`;
});
* {
margin: 0;
box-sizing: border-box;
}
.pane {
width: 200px;
height: 200px;
left: 50px;
top: 50px;
position: relative;
perspective: 600px;
}
.pane-tilt {
position: relative;
width: 100%;
height: 100%;
backface-visibility: hidden;
transition: 0.1s;
display: flex;
transform-style: preserve-3d;
}
.pane-tilt-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.pane-tilt-desc {
position: relative;
margin: auto;
color: #fff;
transition: 0.3s;
transform: translateZ(0px);
scale: 0.6;
opacity: 0;
}
.pane:hover .pane-tilt-desc {
transform: translateZ(60px);
scale: 1;
opacity: 1;
}
<div class="pane">
<div class="pane-tilt">
<img class="pane-tilt-image" src="https://placekitten.com/300/287">
<h3 class="pane-tilt-desc">Lorem ipsum</h3>
</div>
</div>

SCSS particles animation - create at random position, but move all particles in the same direction

I'm fairly new to SCSS so hopefully someone can help me out.
I'm trying to move particles in the same direction (down), but because all the particles are placed randomly their destination also ends up random.
I would like to keep random placement, but once they are placed I want them all going in the same direction (down) and not in the random direction. I don't know how to do that without loosing random positioning generated with steps.
I know how to do this in CSS, but that would require specifying every path manually, which will be my final solution if I can get it to work with SCSS, unless someone can help me out?
Here is JSFiddle to show how it's behaving, but this is the part where random steps are created:
SCSS
#for $i from 1 through $dot-count {
&:nth-of-type(#{$i}) {
animation-name: move-path-#{$i};
&:before {
animation-duration: random(5000) + 5000ms, random(1000) + 7000ms;
animation-delay: random(6000) + 500ms, 0s;
}
}
$steps: random(15) + 10;
#keyframes move-path-#{$i} {
#for $step from 0 through $steps {
#{$step / $steps * 100%} {
transform: translateX(random(100) - 50vw)
translateY(random(100) - 50vh)
scale(random(70) / 100 + 0.3);
}
}
}
}
You could define a random variable common to all your particles, use it to position your particles and then move them according to their step number and not randomly.
html {
font-size: 30vmax / 1920 * 100;
font-family: "Quicksand", sans-serif;
background-color: #000;
margin: 0;
padding: 0;
#media (max-width: 768px) {
font-size: 50px;
}
}
// Stars
$dot-color: #fff;
$dot-count: 35;
#milky-way {
width: 100%;
}
.sky {
position: fixed;
width: 100%;
height: 100%;
z-index: 10;
pointer-events: none;
}
.dot {
position: absolute;
width: 0.08rem;
height: 0.08rem;
top: 50%;
left: 50%;
animation: 160s ease both infinite alternate;
&:before {
content: "";
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: $dot-color;
transform-origin: -1rem;
animation: lighting ease both infinite, auto-rotating ease both infinite;
}
#for $i from 1 through $dot-count {
// Random variable common to all particles
$random: random(100);
&:nth-of-type(#{$i}) {
animation-name: move-path-#{$i};
&:before {
animation-duration: random(5000) + 5000ms, random(1000) + 7000ms;
animation-delay: random(6000) + 500ms, 0s; // less than max duration
}
}
$steps: random(15) + 10;
#keyframes move-path-#{$i} {
#for $step from 0 through $steps {
#{$step / $steps * 100%} {
// first translation is depending on a common random, second is depending on the step number
transform: translateX($random - 50vw) translateX($step * $step * 150px)
translateY($random - 50vh) translateY($step * $step * 150px)
scale(random(70) / 100 + 0.3);
}
}
}
}
}
#keyframes lighting {
0%,
30%,
100% {
opacity: 0;
}
5% {
opacity: 1;
box-shadow: 0 0 0.3rem 0.05rem $dot-color;
}
}
#keyframes auto-rotating {
to {
transform: rotate(0deg);
}
}

Why does my CSS variable remain unused when trying to use it in an animation?

I'm trying to animate a falling object, with translateX being random. Everything about the code works, apart from my variable transX.
The part of changing the value via JavaScript works perfectly fine, however the value just isn't used.
Why will it not work?
setInterval(function() {
var e = document.createElement("li");
e.style.setProperty("--transX", (Math.random() * 50 - 25).toFixed(0) + "px");
document.getElementById("list").appendChild(e);
}, 100);
li {
display: inline-block;
position: absolute;
background-color: #1eb500;
top: 50px;
left: 200px;
height: 10px;
width: 2px;
animation-name: fall;
animation-duration: 1.5s;
animation-timing-function: cubic-bezier(.66, -0.06, .77, .12);
opacity: 0%;
list-style-type: none;
transform: rotate(0deg);
--transX: 100px;
}
#keyframes fall {
0% {
opacity: 100%;
}
100% {
transform: translateY(2000px) translateX(var(--transX)) rotate(720deg);
opacity: 0%;
}
}
<ul id="list"></ul>
where are you applying the animation? Variables in CSS should be declared within a CSS selector that defines its scope. For a global scope you can use either the :root or the body selector
:root {
--transX: 100px;
}

CSS animation - revert on mouseout

I'm sure this must have been asked before and I've found related questions but I can't quite seem to crack this.
I have an element which receives a class and, on doing so, expands. Later, when that class is removed, it should revert (animate) back to its original width.
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: red;
position: fixed;
left: 0;
top: 0;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
to {
width: 75px;
}
}
<div id='side-bar' class='contracted'></div>
The expansion animation works fine. But the reversion animation doesn't happen; it just snaps back to its original properties, no anim.
Fiddle
What am I doing wrong?
[ EDIT ]
OK I should obviously have mentioned why I'm not doing this with transition. This is part of a wider set of dependent animations which run in a sequence, one after another. My understanding is that this sort of chronologically non-trivial situation is better for animation rather than transition.
UPDATE: (Removing the animation at the beginning)
let init = 0,
el = document.querySelector('#side-bar');
el.addEventListener('click', function() {
if (init < 1) {
init++;
el.classList.remove("init");
el.classList.add('contracted');
}
el.classList.toggle('contracted');
});
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.init) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
from {
width: 350px;
}
}
<div id='side-bar' class='init'>Click me</div>
Just change to to from in side-bar-contract
#keyframes side-bar-expand { to { width: 350px; } }
#keyframes side-bar-contract { from { width: 350px; } }
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
from {
width: 350px;
}
}
<div id='side-bar' class='contracted'>Click me</div>
Why not just use a transition animation:
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 350px; /* have width at 350px when not contracted */
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
transition: width .5s; /* animate the width */
}
#side-bar.contracted {
width: 75px;
}
<div id='side-bar' class='contracted'>Click me</div>
If you need to use keyframes then you need to start the second one off at 350px - you start it at 75 to 75 which is why it doesn't animate:
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
0% {
width: 350px;
}
100% {
width: 75px;
}
}
<div id='side-bar' class='contracted'>Click me</div>
First, I would recommend you do this with hover styles and css transition instead of an animation for something as simple as animating a single property.
.class {
width: 400px;
transition: width 1500ms ease-in-out;
}
.class:hover {
width: 100px;
}
CSS transition will actually stop part way through the transition and reverse to the initial size for you.
Second, I would recommend that you do not animate or transition the width property in CSS. Here's a great article about what properties you should avoid animating.
If you need to delay a transition from happening on other elements, you can use the transition-delay property. This property can also be applied in hover effects... including with hover effects on parent elements. So you may potentially have multiple hover effects in play at a given time to accomplish your desired effect.

why does this css3 animation look great in chrome and IE, but terrible in firefox?

I saw this in user King King's profile, and at a cursory glance the code does appear nearly identical for all browsers. So why is this Css3 animation rendered very smoothly in chrome and IE, but choppy as heck in FF? Here is a fiddle (http://jsfiddle.net/viphalongpro/GEnUU/) below find the JS+CSS
HTML
<div class='flag'>
</div>
JS
var h = $('.flag').width();
for(var i = 0; i < h; i++){
var flagElement = $("<div class='flag-element'>");
flagElement.css('background-position', -i + "px 0");
flagElement.css('-webkit-animation-delay', i * 10 + 'ms');
flagElement.css('-moz-animation-delay', i * 10 + 'ms');
flagElement.css('-ms-animation-delay', i * 10 + 'ms');
flagElement.css('animation-delay', i * 10 + 'ms');
$('.flag').append(flagElement);
}
CSS
.flag {
width:300px;
height:200px;
margin:50px;
}
.flag-element {
-webkit-animation:oscill 1s ease-in-out infinite alternate;
-moz-animation:oscill 1s ease-in-out infinite alternate;
-ms-animation:oscill 1s ease-in-out infinite alternate;
animation:oscill 1s ease-in-out infinite alternate;
background: url('http://i.imgur.com/8VSL8Ve.gif');
background-size: 300px 100%;
position:relative;
height:100%;
width:1px;
display:inline-block;
box-shadow:0 1px grey, 0 -1px gray;
}
#-webkit-keyframes oscill {
0% {
top: 5%;
}
100% {
top: -5%;
}
}
#-moz-keyframes oscill {
0% {
top: 5%;
}
100% {
top: -5%;
}
}
#-ms-keyframes oscill {
0% {
top: 5%;
}
100% {
top: -5%;
}
}
#keyframes oscill {
0% {
top: 5%;
}
100% {
top: -5%;
}
}

Resources