I am trying to make a box with a nice looking animated gradient. I can not use the animate function to change the gradient so I try to do it with JavaScript. I would use the jQuery.css() function, but I can not address the :before and :after selectors with jQuery.
So what I am trying to do is to change the CSS code in #js-style every 100ms in an infinite loop. But what happens is that it does update the CSS code, but it only applies it when the loop breaks.
Is there a way to tell the browser to check and apply the code every time it changes during the JavaScript loop?
$(document).ready(function() {
// Settings
var steps_per_color = 100;
var timeout = 100;
var colors = [
[255, 0, 158],
[0, 205, 255],
[42, 0, 255],
[168, 0, 253]
];
var cur_base_colors = [
0,
1,
2,
3
];
var cur_goal_colors = [
1,
2,
3,
0
];
var cur_colors = [
colors[0],
colors[1],
colors[2],
colors[3]
];
var def_colors = [
[255, 0, 158],
[0, 205, 255],
[42, 0, 255],
[168, 0, 253]
];
var step = 0;
var step_size, goal, base, text, cur_color;
while (true) {
cur_base_colors.unshift(cur_base_colors[3]);
cur_base_colors.pop();
cur_goal_colors.unshift(cur_goal_colors[3]);
cur_goal_colors.pop();
cur_colors.forEach(function(color, color_index) {
cur_colors[color_index] = colors[cur_base_colors[color_index]];
});
while (step < steps_per_color) {
cur_colors.forEach(function(color, color_index) {
color.forEach(function(item, index) {
base = colors[cur_base_colors[color_index]][index];
goal = colors[cur_goal_colors[color_index]][index];
step_size = (goal - base) / steps_per_color;
cur_color = item + step_size
cur_colors[color_index][index] = cur_color;
def_colors[color_index][index] = Math.round(cur_color);
});
});
text = ".shadow:before, .shadow:after{background: linear-gradient(135deg";
def_colors.forEach(function(item, index) {
text += ", rgb(" + item[0] + ", " + item[1] + ", " + item[2] + ")";
});
text += ");}";
console.log(text);
$('#js-style').html(text);
sleep(timeout);
step += 1;
}
break;
step = 0;
}
});
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
* {
padding: 0;
box-sizing: border-box;
}
body {
background: #555;
margin: 0;
height: 100vh;
width: 100vw;
padding: 20px;
}
.block {
position: relative;
width: 100%;
height: 100%;
color: #f2f2f2;
display: flex;
flex-direction: column;
justify-content: center;
border-radius: 5px;
}
.shadow:before,
.shadow:after {
content: '';
position: absolute;
top: -2px;
left: -2px;
width: calc(100% + 4px);
height: calc(100% + 4px);
background-size: 100%;
z-index: -1;
border-radius: 5px;
}
.shadow:after {
top: -4px;
left: -4px;
width: calc(100% + 10px);
height: calc(100% + 10px);
filter: blur(4px);
opacity: 1;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div class="block shadow"></div>