Trouble making Marquee text continous in HTML - javascript

I'm trying to make my marquee text continuous, but can't figure out how too. This is what I've right now in my HTML:
.marquee2 {
position: relative;
overflow: hidden;
--offset: 20vw;
--move-initial: calc(-20% + var(--offset));
--move-final: calc(-40% + var(--offset));
}
.marquee__inner2 {
width: fit-content;
display: flex;
position: relative;
transform: translate3d(var(--move-initial), 0, 0);
animation: marquee 12s linear infinite;
animation-play-state: play;
color: #1a1a1a;
font-family: 'Noctis Bold';
}
.marquee2 span {
font-size: 5vh;
padding: 0 2vw;
}
.marquee2:hover .marquee__inner2 {
animation-play-state: paused;
}
#keyframes marquee2 {
0% {
transform: translate3d(var(--move-initial), 0, 0);
}
100% {
transform: translate3d(var(--move-final), 0, 0);
}
}
<div class="bg33">
<div class="marquee2" id="showScroll2">
<div class="marquee__inner2" aria-hidden="true">
<span>HTML</span>
<span>CSS</span>
<span>SASS</span>
<span>JAVASCRIPT</span>
<span>JQUERY</span>
<span>VUE.JS</span>
<span>PYTHON</span>
<span>JAVA</span>
<span>REACT</span>
<span>GIT</span>
<span>NPM</span>
<span>RSTUDIO</span>
<span>JIRA</span>
<span>AGILE</span>
<span>FIGMA</span>
<span>PS</span>
<span>ILLUSTRATOR</span>
<span>BALSAMIQ</span>
</div>
</div>
</div>
The text doesn't seem to be continuous and it break and starts off again, which is annoying and doesn't show all the text. I want this text to loop over to see appears continuous and full for viewing by the audience. Can anyone help me with this?

A simple way of doing this - if you know the text will at least cover the viewport width - is to have a second copy. Then you animate by moving the whole thing left by half its width and starting again.
Here's the altered snippet, note you don't need initial setup conditions to center anything.
.marquee2 {
position: relative;
overflow: hidden;
--offset: 20vw;
--move-initial: calc(-20% + var(--offset));
--move-final: calc(-40% + var(--offset));
}
.marquee__inner2 {
width: fit-content;
display: flex;
position: relative;
transform: translate3d(0, 0, 0);
animation: marquee2 12s linear infinite;
animation-play-state: play;
color: #1a1a1a;
font-family: 'Noctis Bold';
}
.marquee2 span {
font-size: 5vh;
padding: 0 2vw;
}
.marquee2:hover .marquee__inner2 {
animation-play-state: paused;
}
#keyframes marquee2 {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-50%, 0, 0);
}
<div class="bg33">
<div class="marquee2" id="showScroll2">
<div class="marquee__inner2" aria-hidden="true">
<span>HTML</span>
<span>CSS</span>
<span>SASS</span>
<span>JAVASCRIPT</span>
<span>JQUERY</span>
<span>VUE.JS</span>
<span>PYTHON</span>
<span>JAVA</span>
<span>REACT</span>
<span>GIT</span>
<span>NPM</span>
<span>RSTUDIO</span>
<span>JIRA</span>
<span>AGILE</span>
<span>FIGMA</span>
<span>PS</span>
<span>ILLUSTRATOR</span>
<span>BALSAMIQ</span>
<span>HTML</span>
<span>CSS</span>
<span>SASS</span>
<span>JAVASCRIPT</span>
<span>JQUERY</span>
<span>VUE.JS</span>
<span>PYTHON</span>
<span>JAVA</span>
<span>REACT</span>
<span>GIT</span>
<span>NPM</span>
<span>RSTUDIO</span>
<span>JIRA</span>
<span>AGILE</span>
<span>FIGMA</span>
<span>PS</span>
<span>ILLUSTRATOR</span>
<span>BALSAMIQ</span>
</div>
</div>
</div>

Related

Using CSS to slide text from right to left until the end the text string

I am trying to create a slider component that slides text from right to left, and if the length of the text is longer than the width of the div element keep moving the text until the end of the text is reached.
The code I have just slides until the beginning of the text hits the left end of the div element, and I am trying to have it move until the end of the string hits the right side of the div. The slider component will have both strings which are shorter than the width, in which case the text should move until the left side of the div, if it is longer than the width it should move the end of the string hits the right side of the div.
Any pointers or suggestions on how I can move this text until the end of the text hits the right side of the div?
code:
.slider {
width: 100%;
overflow: hidden;
margin-left: 300px;
background-color: aqua;
}
.slider h2 {
animation: slide-left 10s;
}
#keyframes slide-left {
from {
margin-left: 100%;
}
to {
margin-left: 0%;
}
}
#keyframes slide-right {
to {
transform:translateX(0);
}
}
<div className="slider">
<h2>Hello world, I need a very long text to show how the text will move</h2>
</div>
UPDATE
Using a timer I managed to have an animation that stops when a condition is hit. I sense that the animation speeds-up at the end, so I will try a bit further.
.slider {
width: 100%;
overflow: hidden;
margin-left: 300px;
background-color: aqua;
}
.slider h2 {
animation: slide-left 30s;
animation-play-state: paused;
}
#keyframes slide-left {
from {
margin-left: 0%;
}
to {
margin-left: -1000%;
}
}
#keyframes slide-right {
to {
transform:translateX(0);
}
}
useEffect(() => {
if(executeTimer){
let interval = setInterval(() => {
let sliderElement = document.getElementById('slider');
let sliderWidth = sliderElement.clientWidth;
setCounter(counter + 1);
if(counter === 100){
document.getElementById("slider").style.animationPlayState = "running";
}
if(sliderWidth >= sliderElement.scrollWidth) {
setExecuteTimer(false);
document.getElementById("slider").style.animationPlayState = "paused";
}
},10);
return () => clearInterval(interval);
}
}, [executeTimer, counter]);
return (
<div className="slider" id="slider-container">
<h2 id="slider">Hello world, this is just a little bit longer; no it needs to be just a little bit longer</h2>
</div>
);
I have a similar need so here's the solution I've came up with.
transform: translateX(calc(-100% + 200px));
This did the trick for me.
Only issue is that the speed of the scrolling depends on the length of the text. It doesn't bother me so I won't be trying to 'fix' it.
:root {
--slider-width: 400px;
}
body {
background-color: gray;
}
.slider {
width: var(--slider-width);
height: 40px;
overflow: hidden;
background-color: blue;
white-space: nowrap;
}
.text {
font-size:26px;
display: inline-block;
animation: slide 20s linear infinite;
}
#keyframes slide {
0% {
transform: translateX(0%);
}
50% {
transform: translateX(calc(-100% + var(--slider-width)));
}
100% {
transform: translateX(0%);
}
}
<div class="slider">
<div class="text">
Hello world, I need a very long text to show how the text will move
</div>
</div>
I hope this will help you.
You could change the
margin-left: 0%;
to
margin-left: -200%;
Or some other value which at the very least is -100% or below. If the text may be 3x as wide as the screen then -300% would be needed.

issue with line through animation

I want to create a simple line through animation and so far I'm here:
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
As you see everything works fine except two things:
Now we can see the line at first then it hides and starts the animation, I want to see only the animated line.
I want to initiate the animation using javascript... but with this pseudo-element (after) it seems complicated!
You can fix your animation using animation-fill-mode:
animation-fill-mode: backwards;
To trigger your animation, just add the strikethrough class. The thing where I think this won't work is when you have a multiline text, as your ::after won't cover that.
document.querySelector( '.strikethrough' ).addEventListener( 'click', event => { event.target.classList.toggle( 'strikethrough' ); });
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
animation-fill-mode: backwards;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
Personally, I would take this simpler tack to reduce the amount of actual objects on screen, and the amount of code, by using a background image to scale. If cleverly set up, you could even multi-line this (by making the background the line height and having a middle pixel in it - and with SVGs you could ensure it was only 1px regardless of the stretching etc...).
document.querySelector( 'p' ).addEventListener( 'click', event => {
event.target.classList.toggle( 'strikethrough' );
})
#keyframes stretch {
to { background-size: 100% var(--line-height); }
}
:root {
--line-height: 1.2em;
}
p {
line-height: var(--line-height);
}
.strikethrough {
line-height: 1.2em;
background: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><line x1="0" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="1px" /></svg>') repeat-y 0 0 / 0 var(--line-height);
animation: stretch 4s;
animation-fill-mode: forwards;
}
<p>Hello World!<br />Another line, does it work?</p>

How to create running text (marquee) using CSS

I face quite big stuck while studying CSS animation.
I'm going to make a "transform: translate" animation which shows text that overflow content width like below situation.
How it works?: (Youtube video link)
var div1 = document.getElementById("div1");
var cont = document.getElementById("content");
var inf = document.getElementById("inf");
inf.innerHTML = "<p> Does the text inside h1 cut off? : " + (cont.offsetWidth < cont.scrollWidth) +
"<br><b>Length of text overflow</b>: " + (cont.offsetWidth - cont.scrollWidth) +
"<br> h1 width: " + (cont.offsetWidth) + ", h1's text length: " + (cont.scrollWidth) + "</p>";
div1.style.backgroundColor = "#A13DAF";
cont.style.webkitAnimationName = "moving";
cont.style.animationName = "moving";
cont.style.animationDuration = "3s";
cont.style.webkitAnimationDuration = "3s";
cont.style.animationTimingFunction = "linear";
cont.style.webkitAnimationTimingFunction = "linear";
#div1 {
margin: 10px;
width: 300px;
background: rgb(40, 40, 40);
white-space: nowrap;
overflow: hidden;
}
#content {
color: white;
width: 100%;
/* animation-name: moving;
animation-duration: 3s;
animation-timing-function: linear;
-webkit-animation-name: moving;
-webkit-animation-duration: 3s;
-webkit-animation-timing-function: linear; */
}
#keyframes moving {
0% {
transform: none;
-webkit-transform: none;
}
65% {
/*below code is pseudo code, It doesn't work,
It is an explanation of the direction I want but.. I can't find way to ...ㅠㅠ*/
transform: translate( calc(#content.scrollWidth - #content.offsetWidth), 0);
-webkit-transform: translate( calc(#content.scrollWidth - #content.offsetWidth), 0);
/*below value is caculated value of fixed text length and content width,
but if either of these changes, this code will not be available for my purpose.
Is there any way to specific values of CSS elements?*/
transform: translate( -668px, 0);
-webkit-transform: translate( -668px, 0);
}
100% {
transform: translate( -668px, 0);
-webkit-transform: translate( -668px, 0);
}
}
<div id="div1">
<h1 id="content">
The only thing that matters now is everything You think of me
</h1>
</div>
<div id="inf"></div>
Like Above code,
I want to make the text to move left in the content (h1), as much as the amount of the cut off cause of its overflow.
But, I can't find a way to refer values of content in CSS.
Is there any way to modify a CSS value by referring to a specific value of another element in the CSS without JavaScript?
I try to avoid the method of changing the keyframe using Javascript as much as possible, though it can be quite heavy.
Thank you very much.
You could animate both transform and simultaneously the margin-left so that the animation will end exactly at the text-end:
.marquee {
position: relative;
overflow: hidden;
background: rgb(161, 61, 175);
color: #fff;
}
.marquee span {
display: inline-block;
min-width: 100%; /* this is to prevent shorter text animate to right */
white-space: nowrap;
font-size: 2.5em;
animation: marquee 4s ease-in-out forwards;
}
#keyframes marquee {
from {transform: translateX(0); margin-left: 0;}
to {transform: translateX(-100%); margin-left: 100%; }
}
<h1 class="marquee">
<span>The only thing that matters now is everything You think of me</span>
</h1>
<p class="marquee">
<span>Beware of short texts!</span>
</p>
Here is another idea with only transform used as animation:
.marquee {
overflow: hidden;
background: rgb(161, 61, 175);
color: #fff;
}
.marquee > span {
display:block;
animation: marquee 4s ease-in-out;
transform: translateX(100%);
}
.marquee > * > span {
display: inline-block;
min-width: 100%;
white-space: nowrap;
font-size: 2.5em;
animation:inherit;
transform: translateX(-100%);
}
#keyframes marquee {
from {
transform: translateX(0);
}
}
<h1 class="marquee">
<span>
<span>The only thing that matters now is everything You think of me</span>
</span>
</h1>
<h1 class="marquee">
<span>
<span>The only thing that matters now is everything</span>
</span>
</h1>
<p class="marquee">
<span>
<span>Beware of short texts!</span>
</span>
</p>

Unable to center a loader on a video

I have a video and i have a loader for the buffer. i cannot seem to center it. Iv tried countless methods iv found online and nothing seems to center it.
I have tried every single method from here: http://vanseodesign.com/css/vertical-centering/
I have tried every method from here: https://www.w3.org/Style/Examples/007/center.en.html
I have tried every method on here: https://www.w3schools.com/css/css_align.asp
No joke im not kidding. i have tried everything.
Nothing is working....
Also on mobile that blue loader ends up at the bottom of the video and not centered meaning i cannot use margins because it needs to be centered for every single screen size. Though the spinner class requires this margin margin: 100px auto; or the loader wont show up.....
It needs to have Position: absolute; on the parent div.
It also needs to have display: none; on the parent div so it is hidden until the javascript calls it. Now No matter what i do i keep getting this:
Desktop Problem image <--
Mobile problem image <--
The "Hello how are you" is centered. The blue loader is not. The blue loader needs to be centered.
It must work in a grid similar to what i made here: https://jsfiddle.net/9faxe587/2/
var video = document.getElementById("video_1");
var placeholder = document.getElementById("placeholder_1");
placeholder_1.style.top = video_1.offsetTop + "px";
placeholder_1.style.left = video_1.offsetLeft + "px";
video_1.onwaiting = function() {
showPlaceholder(placeholder_1, this);
};
video_1.onplaying = function() {
hidePlaceholder(placeholder_1, this);
};
function showPlaceholder(img, vid) {
img.style.height = vid.scrollHeight + "px";
img.style.width = vid.scrollWidth + "px";
img.style.display = "block";
}
function hidePlaceholder(img, vid) {
img.style.display = "none";
}
.spinner {
margin: 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner>div {
background-color: #0080ff;
height: 100%;
width: 5.5px;
display: inline-block;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
#-webkit-keyframes sk-stretchdelay {
0%,
40%,
100% {
-webkit-transform: scaleY(0.4)
}
20% {
-webkit-transform: scaleY(1.0)
}
}
#keyframes sk-stretchdelay {
0%,
40%,
100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
}
20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
.THG-placeholder {
display: none;
position: absolute;
z-index: 1;
}
.THG-video {
width: 100% !important;
height: auto !important;
max-height: 380px;
max-width: 512px;
z-index: 1;
}
<video class="THG-video" id="video_1" controls preload="none">
<source src="http://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4" />
</video>
<div id="placeholder_1" class="THG-placeholder">
<div class="spinner">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
I have updated #DanteTheSmith's fiddle with my solution using Flexbox.
Fiddle: https://jsfiddle.net/Ldhoo0f6/5/
.THG-placeholder {
top: 0;
left: 0;
width: 100%;
display: none; // show with display: flex;
align-items: center;
justify-content: center;
height: Calc(100% - 36px);
position: absolute;
z-index: 1;
}
video {
width: 100%;
}
.wrapper {
position: relative;
max-width: 460px; // or a percentage or whatever you like
}
Explanation
There is a wrapper div with position: relative around the whole thing, so the absolutely positioned element will be within that div's constraints.
The video is 100% width so it is responsive.
The wrapper div determines the size of the video with max-width
The placeholder element has display: flex added by js.
It is centred with Flexbox align-items and justify-content.
The height uses Calc to adjust for the height of the video controls - though this might differ depending on the browser (I used Chrome). You could just use 100% if you're not too pedantic.
Flexbox is pretty well supported these days: https://caniuse.com/#feat=flexbox
.spinner {
margin: 55px auto; // (video height / 2) - (spinner height / 2)
height: 40px;
text-align: center;
font-size: 10px;
}
If you wanna center the element in entire video box (including the controls)
.spinner {
margin: 32px auto; // (video height - controls height - 45px / 2) - (spinner height / 2)
height: 40px;
text-align: center;
font-size: 10px;
}
Working with second CSS:
fidd

jQuery direction-aware hover with CSS3 transition

I am struggling to get direction-aware hover and css transitions to work properly. Basically I am trying to have a grid of elements with a front and back face, and when on hover have a css transition to flip that element to show the back face.
Transition example (without direction-aware): fiddle
As you can see, no matter which way your mouse enters an element it always flips up. I want it to flip whichever way the mouse enters in/out.
Example:
And here is my attempt with direction-aware: fiddle
I am using jQuery to add classes relevant to the mouse in/out direction.
.hover-in-top {}
.hover-in-right {}
.hover-in-bottom {}
.hover-in-left {}
.hover-out-top {}
.hover-out-right {}
.hover-out-bottom {}
.hover-out-left {}
As you can see from the direction-aware example it kind of works but there are major glitches which I can't get my head round. (I've been overthinking this and my brain has just imploded.)
Anyway I hope this makes sense. Thanks.
I have a partial solution to your question.
But I needed to change some of the transitions to animations
$('.box-container .box').each(function() {
$(this).on('mouseenter mouseleave', function(e) {
var $this = $(this),
width = $this.width(),
height = $this.height();
var x = (e.pageX - $this.offset().left - (width / 2)) * (width > height ? (height / width) : 1),
y = (e.pageY - $this.offset().top - (height / 2)) * (height > width ? (width / height) : 1);
// top = 0, right = 1, bottom = 2, left = 3
var dir_num = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4,
directions = ['top', 'right', 'bottom', 'left'];
// If mouse enter
if (e.type === 'mouseenter') {
// Remove all hover out classes
$this.removeClass(function(index, css) {
return (css.match(/(^|\s)hover-out-\S+/g) || []).join(' ');
});
// Add in direction class
$this.addClass('hover-in-' + directions[dir_num]);
}
// If mouse leave
if (e.type === 'mouseleave') {
// Remove all hover in classes
$this.removeClass(function(index, css) {
return (css.match(/(^|\s)hover-in-\S+/g) || []).join(' ');
});
// Add out direction class
$this.addClass('hover-out-' + directions[dir_num]);
}
});
});
* {
box-sizing: border-box;
}
.box-container {
padding: 20px;
width: 600px;
}
.box-container:after {
content: '';
display: block;
clear: both;
}
.box-container .box {
float: left;
width: 50%;
height: 200px;
position: relative;
perspective: 600px;
border: 1px solid transparent;
}
.box-container .box .front, .box-container .box .back {
float: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
backface-visibility: hidden;
transition: all 1s ease-in-out;
color: white;
font-size: 60px;
}
.box-container .box .front {
background: blue;
transform: rotateX(0) rotateY(0);
z-index: 900;
}
.box-container .box .back {
background: red;
z-index: 800;
}
.box-container .box:hover .front {
z-index: 900;
}
.box-container .box:hover .back {
z-index: 1000;
transform: rotateX(180) rotateY(0);
}
.box-container .box.hover-in-top .front,
.box-container .box.hover-out-bottom .back {
transform: rotateX(-179deg) rotateY(0);
}
.box-container .box.hover-in-top .back,
.box-container .box.hover-out-bottom .front {
animation: Xminus 1s ease-in-out;
}
#keyframes Xminus {
from {transform: rotateX(179deg) rotateY(0);}
to {transform: rotateX( 0deg) rotateY(0);}
}
.box-container .box.hover-in-bottom .front,
.box-container .box.hover-out-top .back {
transform: rotateX(179deg);
}
.box-container .box.hover-in-bottom .back,
.box-container .box.hover-out-top .front {
animation: Xplus 1s ease-in-out;
}
#keyframes Xplus {
from {transform: rotateX(-179deg) rotateY(0);}
to {transform: rotateX( 0deg) rotateY(0);}
}
.box-container .box.hover-in-right .front,
.box-container .box.hover-out-left .back {
transform: rotateY(-179deg);
}
.box-container .box.hover-in-right .back,
.box-container .box.hover-out-left .front {
animation: Yminus 1s ease-in-out;
}
#keyframes Yminus {
from {transform: rotateX(0deg) rotateY(179deg);}
to {transform: rotateX(0deg) rotateY( 0deg);}
}
.box-container .box.hover-in-left .front,
.box-container .box.hover-out-right .back {
transform: rotateY(179deg);
}
.box-container .box.hover-in-left .back,
.box-container .box.hover-out-right .front {
animation: Yplus 1s ease-in-out;
}
#keyframes Yplus {
from {transform: rotateX(0deg) rotateY(-179deg);}
to {transform: rotateX(0deg) rotateY( 0deg);}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box-container">
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
</div>
The problem with animations if that if you leave the div before the animation has ended, the animation will break
But if move slowly, and stay on the divs until the animation ends, this will work ok.
I hope that somebody finds a better solution
I believe that the best way to approach the problem is not to use CSS transitions.
You can easily implement it using jQuery's animate, utilizing jQuery animations queue to keep all of your animations synced.
I modified your example to animate the transition in JavaScript.
Code example

Categories

Resources