CSS Marquee speed - javascript

Using CSS for a marquee effect, the code is running perfect. My only issue is speed.
When the text is short the marquee takes longer. When the text is long the marquee runs very quickly. I know the above is because of the animation time animation: marquee 15s linear infinite;
Is there a way to run the marquee at a consistent speed no matter the text length?
I am open to use Javascript if needed (I have tried but not succeeded.)
Here is my current CSS code:
<style>
/* Make it a marquee */
.marquee {
width: 100%;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
background-color: #000000;
bottom: 0px;
color: white;
}
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
animation: marquee 15s linear infinite;
animation-delay: 10s;
background-color: #000000;
color: white;
bottom: 0px;
}
/* Make it move */
#keyframes marquee {
0% {
transform: translate(10%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
/* Make it pretty */
.scroll {
padding-left: 1.5em;
position: fixed;
font: 50px 'Verdana';
bottom: 0px;
color: white;
left: 0px;
height: 10%;
}
</style>
HTML
<div class="marquee">
<p class="scroll marquee"><span id="scrolltext"></span></p>
</div>

Right, this is more of a math problem than anything.
We can do a simple Time = Distance/Speed calculation like this
function calcSpeed(speed) {
// Time = Distance/Speed
var spanSelector = document.querySelector('.marquee span');
var spanLength = spanSelector.offsetWidth;
var timeTaken = spanLength / speed;
spanSelector.style.animationDuration = timeTaken + "s";
}
calcSpeed(100);
function calcFastSpeed(speed) {
// Time = Distance/Speed
var spanSelector = document.querySelector('.fast.marquee span');
var spanLength = spanSelector.offsetWidth;
var timeTaken = spanLength / speed;
spanSelector.style.animationDuration = timeTaken + "s";
}
calcFastSpeed(500);
/* Make it a marquee */
.marquee {
width: 100%;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
background-color: #000000;
bottom: 0px;
color: white;
}
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
animation: marquee linear infinite;
animation-delay: 5s;
background-color: #000000;
color: white;
bottom: 0px;
}
/* Make it move */
#keyframes marquee {
0% {
transform: translate(10%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
/* Make it pretty */
.scroll {
padding-left: 1.5em;
position: fixed;
font: 50px'Verdana';
bottom: 0px;
color: white;
left: 0px;
height: 10%;
}
<div class="marquee">
<span>Lots of text, written in a long sentence to make it go off the screen. Well I hope it goes off the screen</span>
</div>
<br />
<div class="fast marquee">
<span>Lots of text, written in a long sentence to make it go off the screen. Well I hope it goes off the screen</span>
</div>
Of course, this is a simple example that doesn't take into account how long the 'track' is, but now you know the basics I'm sure you can work it out :-)
Here is another example with 2 different lengths of text traveling at the same speed
function calcSpeed(speed) {
// Time = Distance/Speed
var spanSelector = document.querySelectorAll('.marquee span'),
i;
for (i = 0; i < spanSelector.length; i++) {
var spanLength = spanSelector[i].offsetWidth,
timeTaken = spanLength / speed;
spanSelector[i].style.animationDuration = timeTaken + "s";
}
}
calcSpeed(100);
/* Make it a marquee */
.marquee {
width: 100%;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
background-color: #000000;
bottom: 0px;
color: white;
}
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
animation: marquee linear infinite;
animation-delay: 5s;
background-color: #000000;
color: white;
bottom: 0px;
}
/* Make it move */
#keyframes marquee {
0% {
transform: translate(10%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
/* Make it pretty */
.scroll {
padding-left: 1.5em;
position: fixed;
font: 50px'Verdana';
bottom: 0px;
color: white;
left: 0px;
height: 10%;
}
<div class="marquee">
<span>Lots of text, written in a long sentance to make it go off the screen. Well I hope it goes off the screen</span>
</div>
<br />
<div class="marquee">
<span>Well I hope it goes off the screen</span>
</div>

You can give your sliding element the same width, then they should scroll with the same speed. But it´s not really dynamic.
Or you can calculate the speed depending on the width of the element. See my small demo.
// your time for 10 px in seconds
var timeFor10Px = 0.2;
var animationSettings = 'marquee linear infinite';
var $marque = $('.marque');
$marque.each( function() {
var outerWidth = $(this).outerWidth();
var calc = outerWidth / 10 * timeFor10Px;
$(this).css('animation', animationSettings + ' ' + calc + 's');
});
.holder {
background: black;
width: 100%;
color: white;
}
.marque {
/* removed, see js tab */
/*animation: marquee 15s linear infinite; */
display: inline-block;
}
#keyframes marquee {
from {
transform: translate( 0%);
}
to {
transform: translate( 100%);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="holder">
<span class="marque marqu1">
Some nice Text
</span>
<br>
<span class="marque marqu2">
Some nice Text Lorem Ipsum dolor sit amet.....
</span>
</div>
edit: #Andrew Bones was a little bit faster, with the similar solution

hi here is the example you are trying to do Example
and more if you can provide proper HTML code Details with the question
body { margin: 20px; }
.marquee {
height: 25px;
width: 420px;
overflow: hidden;
position: relative;
}
.marquee div {
display: block;
width: 200%;
height: 30px;
position: absolute;
overflow: hidden;
animation: marquee 5s linear infinite;
}
.marquee span {
float: left;
width: 50%;
}
#keyframes marquee {
0% { left: 0; }
100% { left: -100%; }
}
<div class="marquee">
<div>
<span>You spin me right round, baby. Like a record, baby.</span>
<span>You spin me right round, baby. Like a record, baby.</span>
</div>
</div>
Hii it's look like it's working proper with
#keyframes marquee {
0% {
transform: translate(10%, 0);
}
100% {
transform: translate(-100%, 0);
}
}
-------- i used belowed one that works fine for me ----------
------------------ you can try thisss---------------------
#keyframes marquee {
0% {
transform: translate(0%, 0);
}
100% {
transform: translate(-100%, 0);
}
}

Related

Looping parallax effect on full-width element keeps jumping in CSS / JS

My preferred end goal is to have a performance friendly background that smoothly loops without jumping. All the resources that I have found online either are not very performance friendly or they only work with elements that have a set width.
Currently everything looks okay, but the background scales poorly on different screens, and will make large jumps occasionally. I assume the jumping is due to an error in the translation of the elements, but I haven't yet seen a good solution. Setting the width of the elements to 200% and translating them over -50% seems like a hacky solution, and I feel as if there should be a much better way of doing it.
I would prefer to find an all CSS solution, but if nothing else is feasible, resorting to JS is fine.
Fiddle: https://jsfiddle.net/r4fz0Lot/3/
Code:
* { box-sizing: border-box; }
html, body, #container { width: 100%; height: 100%; }
body { margin: 0; }
#container {
background-color: rgba(0, 0, 0, 0.9);
image-rendering: pixelated;
overflow: hidden;
position: fixed;
}
#stars {
background: url('https://i.imgur.com/Ym03Zkf.png') repeat 0 0;
animation: loop 25s linear infinite;
z-index: 1;
}
#mountains {
background: url('https://i.imgur.com/jfef1r3.png') repeat-x 0 bottom;
animation: loop 20s linear infinite;
z-index: 2;
}
#ground {
background: url('https://i.imgur.com/P13CzUo.png') repeat-x 0 bottom;
animation: loop 15s linear infinite;
z-index: 3;
}
#stars, #mountains, #ground {
width: 200%; height: 100%;
background-size: 30%;
bottom: 0; left: 0;
position: fixed;
}
#keyframes loop {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
<div id="container">
<div id="ground"></div>
<div id="mountains"></div>
<div id="stars"></div>
</div>
You set background-size to 30% so you need to translate some multiple of 30% to translate "one image unit"
* { box-sizing: border-box; }
html, body, #container { width: 100%; height: 100%; }
body { margin: 0; }
#container {
background-color: rgba(0, 0, 0, 0.9);
image-rendering: pixelated;
overflow: hidden;
position: fixed;
}
#stars {
background: url('https://i.imgur.com/Ym03Zkf.png') repeat 0 0;
animation: loop 8s linear infinite;
z-index: 1;
}
#mountains {
background: url('https://i.imgur.com/jfef1r3.png') repeat-x 0 bottom;
animation: loop 6s linear infinite;
z-index: 2;
}
#ground {
background: url('https://i.imgur.com/P13CzUo.png') repeat-x 0 bottom;
animation: loop 5s linear infinite;
z-index: 3;
}
#stars, #mountains, #ground {
width: 200%; height: 100%;
background-size: 30%;
bottom: 0; left: 0;
position: fixed;
}
#keyframes loop {
from { transform: translateX(0); }
to { transform: translateX(-30%); }
}
<div id="container">
<div id="ground"></div>
<div id="mountains"></div>
<div id="stars"></div>
</div>

Js/jQuery - This code sets a size to a variable, any way to make it responsive?

A non-programmer here, looking for help. :)
I've been searching for a way to make two circles spin inside a larger circle, in a very particular fashion, and I found some code which I managed to tweak to get exactly the effect I wanted:
However, the full width of it is 400px (I need it to be so), and the problem is that the code defines the radius and positioning values in absolute, so if the browser goes below 400px width, it can't be adjusted:
var r = 101;
var xcenter = 100;
var ycenter = 100;
var newLeft = Math.floor(xcenter + (r * Math.cos(t)));
var newTop = Math.floor(ycenter + (r * Math.sin(t)));
Now, I would be content if I could simply scale this whole thing for browsers < 400px down to
var r = 71;
var xcenter = 70;
var ycenter = 70;
var newLeft = Math.floor(xcenter + (r * Math.cos(t)));
var newTop = Math.floor(ycenter + (r * Math.sin(t)));
But I haven't the slightest clue how to go about implementing that responsiveness, or even if it's possible to do in real time (without having to refresh the browser, cos I'd like it to be resize-proof).
Here is the full fiddle of what I have: http://jsfiddle.net/29or8u76/3/
So... can someone help me out? Cos I don't really speak javascript at all :) Thanksss!
This does not directly answer your question, but here's an example using only CSS.
I've used percentages to keep everything responsive to the container width.
The inner circles rotate around their origins by using animation, which uses transform.
The pulsing of the outer circle is just for demonstration purposes, to show how the size of the inner circles are relative to their container.
#container {
position: relative;
height: 0;
border: 1px solid #000;
border-radius: 50%;
margin: 0 auto;
animation: pulse 5s 0s linear infinite;
}
.circle {
position: absolute;
width: 50%;
height: 50%;
border-radius: 50%;
animation: spin 3s 0s linear infinite;
}
#blue {
top: 0;
left: 25%;
transform-origin: center bottom;
background-color: #00f;
}
#red {
bottom: 0;
left: 25%;
transform-origin: center top;
background-color: #f00;
}
#keyframes spin {
100% {
transform: rotate(360deg);
}
}
#keyframes pulse {
0% {
width: 25%;
padding-bottom: 25%;
}
50% {
width: 10%;
padding-bottom: 10%;
}
100% {
width: 25%;
padding-bottom: 25%;
}
}
<div id="container">
<div class="circle" id="blue"></div>
<div class="circle" id="red"></div>
</div>
EDIT:
To ensure that the contents of the circles don't rotate, I've used a slightly different method that animates the circles in orbit around the container's center.
This method is based on a tutorial by Zoltan Howryluk.
#container {
position: relative;
height: 0;
border: 1px solid #000;
border-radius: 50%;
margin: 0 auto;
animation: pulse 5s 0s linear infinite;
}
.circle {
position: absolute;
width: 50%;
height: 50%;
top: 25%;
left: 25%;
border-radius: 50%;
transform-origin: center;
display: flex;
justify-content: center;
align-items: center;
}
.circle span {
font-size: 10px;
color: white;
}
#blue {
background-color: #00f;
transform: translateY(-50%);
animation: orbit1 3s 0s linear infinite;
}
#red {
background-color: #f00;
transform: translateY(50%);
animation: orbit2 3s 0s linear infinite;
}
#keyframes orbit1 {
from {
transform: rotate(0deg) translateX(50%) rotate(0deg);
}
to {
transform: rotate(360deg) translateX(50%) rotate(-360deg);
}
}
#keyframes orbit2 {
from {
transform: rotate(0deg) translateX(-50%) rotate(0deg);
}
to {
transform: rotate(360deg) translateX(-50%) rotate(-360deg);
}
}
#keyframes pulse {
0% {
width: 25%;
padding-bottom: 25%;
}
50% {
width: 10%;
padding-bottom: 10%;
}
100% {
width: 25%;
padding-bottom: 25%;
}
}
<div id="container">
<div class="circle" id="blue"><span>BLUE</span></div>
<div class="circle" id="red"><span>RED</span></div>
</div>
Before deciding on this method, I recommend considering browser compatibility and vendor prefixes for various CSS3 functionality. For simplicity, I haven't included any vendor prefixes here.

Overriding position of CSS Keyframes not working

I want to override a previous CSS #keyframe animation.
First, the word comes in from the right and stays in the middle.
As soon as you click on the button, the same word should be animated to move from it's current position to the top.
However, the word doesn't move at all or simply makes a quick jump to that position.
Here's a fiddle: https://jsfiddle.net/vpfd672g/10/
<button type="button" class="test-button">Click Me!</button>
<div id="window">
<div class="container">
<div class="word">Hello</div>
</div>
</div>
#window {
overflow: hidden;
}
.container {
text-align: center;
position: absolute;
width: 221px;
height: 50px;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
font-family: helvetica;
font-size: 20px;
z-index: 10;
}
.word {
position: relative;
animation: slide-in-right 2s ease-out forwards;
animation-delay: 0s;
opacity: 0;
}
#keyframes slide-in-right {
0% {
right: -100px;
}
100% {
right: 0px;
opacity: 1;
}
}
#keyframes slide-out-top {
100% {
top: -100px;
opacity: 0;
}
}
<script>
let word = document.querySelector(".word");
let tstB = document.querySelector(".test-button");
tstB.addEventListener('click', doStuff);
function doStuff() {
word.style.opacity = 1;
word.style.animation = "slide-out-top 2s forwards ease-out"
}
</script>
What is it that's causing the issue or what am I missing out?
You need to add below style to slide-out-top.
0% {
top: 0px;
}
Here is the updated fiddle.

Smoothly animate background color opacity after underlying image loads

I have a div with a black background. When my page loads, I make a call for an image and then load that image into a div behind the main div. Then I want to smoothly fade the overlaying div to have an opacity so that the image underneath is displayed, but without impacting the opacity of content in the overlaying div.
What I have isn't really working at all: https://jsfiddle.net/n7t2xmha/3/
The animation is not smooth
The opacity is not accurate
The text does not stay solid
Code:
<div class="outerdiv">
<div class="innerdiv">
</div>
<p>
content - should remain solid white
</p>
</div>
.outerdiv {
background-color: black;
position: relative;
display: block;
height: 500px;
width: 500px;
color: white;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
-webkit-transition: all 1s linear;
transition: all 1s linear;
}
.outerdiv-opaque {
opacity: 0.9 !important;
}
.innerdiv {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index=-1;
}
JS
var innerDiv = $('.innerdiv');
setTimeout(function() {
innerDiv.css('background-image', 'url(http://i.stack.imgur.com/MxR09.png)');
var outerdiv = $('.outerdiv');
setTimeout(function() {
outerdiv.addClass('outerdiv-opaque');
}, 500);
}, 1000)
Separate the timeouts functions.
modify the .outerdiv-opaque class
.outerdiv-opaque {
background-color: white;
}
your timeOut functions after separating would look like this
var innerDiv = $('.innerdiv');
setTimeout(function() {
innerDiv.css('background-image', 'url(http://i.stack.imgur.com/MxR09.png)');
}, 1000)
var outerdiv = $('.outerdiv');
setTimeout(function() {
outerdiv.addClass('outerdiv-opaque');
}, 500);
I would use a pseudo, like this, which will keep your markup as is and as the opacity is on the pseudo it won't effect any other element.
Instead of a script, I used an extra step on the animation, where I told it to keep its opacity at 1 up until 60% of the animation time before it should start to fade.
.outerdiv {
position: relative;
height: 500px;
width: 500px;
color: white;
background: url(http://i.stack.imgur.com/MxR09.png);
}
.outerdiv::before {
content: '';
background-color: black;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.5;
animation: fade 2s linear;
}
.innerdiv {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
p {
position: relative;
}
#keyframes fade {
0% { opacity:1 }
60% { opacity:1 }
100% { opacity:0.5 }
}
<div class="outerdiv">
<div class="innerdiv">
</div>
<p>
content - should remain solid white
</p>
</div>
There are literally a dozen ways to do this. Here are four basic examples which work smoothly.
Using CSS Transitions
HTML:
<div class="container">
<div class="outerdiv">
</div>
<div class="innerdiv">
</div>
<p>
content - should remain solid white
</p>
</div>
CSS:
.container,.outerdiv {
background-color: black;
position: relative;
display: block;
height: 500px;
width: 500px;
color: white;
}
.outerdiv,.innerdiv {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.outerdiv{
z-index:1;
transition: .5s opacity linear;
}
.innerdiv{
background-image: url(http://i.stack.imgur.com/MxR09.png);
}
.outerdiv.fadeout{
opacity:0
}
.container p{
position:relative;
z-index:3;
}
JS:
// wait 1 second, add the fadeout class, let the CSS do the rest
setTimeout(function(){
document.querySelector('.outerdiv').classList.add('fadeout')
},1000);
See it in action: https://jsfiddle.net/kmm8e0x7/8/
Using CSS Animation
HTML: same as above
CSS:
.container,.outerdiv {
background-color: black;
position: relative;
display: block;
height: 500px;
width: 500px;
color: white;
}
.outerdiv,.innerdiv {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.outerdiv{
z-index:1;
}
.innerdiv{
background-image: url(http://i.stack.imgur.com/MxR09.png);
}
.outerdiv{
animation: fadeout .5s linear forwards 1s;
/*
Which is shorthand for:
animation-name: fadeout
animation-duration: .5s;
animation-timing-function: linear
animation-fill-mode:forwards;
animation-delay: 1s
*/
}
.container p{
position:relative;
z-index:3;
}
#keyframes fadeout{
from{opacity:1}
to{opacity:0}
}
JS: none (animation-delay property removes the need for setTimeout)
See it in action: https://jsfiddle.net/kmm8e0x7/7/
Using JavaScript
HTML: as above
CSS:
.container,.outerdiv {
background-color: black;
position: relative;
display: block;
height: 500px;
width: 500px;
color: white;
}
.outerdiv,.innerdiv {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.outerdiv{
z-index:1;
transition: .5s opacity linear;
}
.innerdiv{
background-image: url(http://i.stack.imgur.com/MxR09.png);
}
.container p{
position:relative;
z-index:3;
}
JS:
var el = document.querySelector('.outerdiv');
function fadeout(){
el.style.opacity -= 0.01;
if(el.style.opacity !== 0){
requestAnimationframe(fadeout);
// this could just as easily be setTimeout(fadeout,t) where t = an increment of time after which to call the next frame
}
}
// just use setTimeout to wait for 1 second before starting the fadeout
setTimeout(fadeout,1000);
See it in action: https://jsfiddle.net/kmm8e0x7/6/
Using jQuery
HTML: same as above
CSS: same as above
JS:
$('.outerdiv').animate({
'opacity': '0'
}, 500);
See it in action: https://jsfiddle.net/kmm8e0x7/5/

How can i trigger hover effect on element using pure javascript?

Was goofing around with css3 animation
check it up http://codepen.io/rokki_balboa/pen/eNVEyq
<section>
<div></div>
<div></div>
</section>
Change
#import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300);
* {
margin: 0;
padding: 0;
}
html {
overflow: hidden;
}
body {
height: 100vh;
width: 100vw;
background-color: #000;
position: relative;
}
section {
width: 100%;
height: 100%;
position: relative;
perspective: 500px;
}
section:hover {
transform-style: preserve-3d;
animation: cool 5s ease-in-out forwards;
}
#keyframes cool {
0% {
transform: perspective(1000px) translateZ(0px);
}
45% {
transform: perspective(1000px) translateZ(-400px);
}
55% {
transform: perspective(1000px) translateZ(-400px) rotateY(.5turn);
}
100% {
transform: perspective(1000px) translateZ(-400px) rotateY(.5turn) translateZ(-400px);
}
}
div {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
div:nth-child(1) {
background: url(http://i.imgur.com/dLBSLQu.jpg) top center no-repeat;
background-size: cover;
}
div:nth-child(2) {
background: url(http://i.imgur.com/uL0mXb6.jpg) top center no-repeat;
background-size: cover;
transform: rotateY(.5turn);
backface-visibility: hidden;
}
#trigger {
position: absolute;
bottom: 10px;
left: 10px;
color: #fff;
font-size: 14px;
}
.ghoster {
display: none;
}
As you can see it works when hovering section. But my goal is to trigger hovering on section when you click an anchor.
1. you click on change anchor
2. animation comes on section element
3. click again
4. animations comes again
I have no idea how to achieve such a result. Can you please help me.
p.s. It would be better if you do it on pure javascript.
CSS
<style>
section.activateHover
{
transform-style: preserve-3d;
animation: cool 5s ease-in-out forwards;
}
</style>
HTML
<section id="sectionToChange">
<div></div>
<div></div>
</section>
Change
Javascript
<script type="text/javascript">
var trigger = document.getElementById('trigger');
var sectionToChange = document.getElementById('sectionToChange');
trigger.onclick = function(e)
{
//toggle hover
sectionToChange.className = (sectionToChange.className == 'activateHover') ? '' : 'activateHover';
//restart animation
if(sectionToChange.className != 'activateHover')
{
sectionToChange.className = 'activateHover';
}
}
</script>

Categories

Resources