Continuous scrolling ticker/marquee with multiple messages - JS plugin needed? - javascript

A good example of what I'm trying to achieve would be the ticker effect on https://aboutface.com
Based on another example I saw a while back I came up with this. But as you can see, the message crops and you don't see the 2nd message coming into the screen. The scrolling/visible area should span the width of the white box - or 12px from each side with the left/right padding.
https://jsfiddle.net/ho34yvtL/1/
Also, I guess this will be problematic on desktop as you'd need several more duplicate messages. Right now, if I could just display 1 message continuously that'd be great. But ideally I'd like to support multiple.
So basically I want text to scroll continuously across the screen with set spacing between each item. So you see multiple messages at the same time if space allows, unlike the old school marquee tag.
If what I'm trying to achieve isn't possible, is there a preferred method for this, a plugin or will it require complex/custom javascript?

Apply width:100% to .msg. If we want to apply a 12px padding on the left and right, we can use CSS calc() to subtract 24px from 100%.
Additionally, margin-left:50px can be applied to the messages to get that 50px spacing between the two.
The following example preserves the 12px padding in the container whilst maintaining 50px spacing between each item.
body {
background: red;
}
.page-head {
background: white;
box-sizing: border-box;
padding: 0;
position: fixed;
top: 0;
width: 375px;
}
/**
* Ticker
*/
.page-head__ticker {
display: flex;
align-items: center;
justify-content: center;
font-family: "Arial";
font-size: 11px;
font-weight: Bold;
height: 36px;
line-height: 1;
padding: 0 12px;
text-transform: uppercase;
}
.msg {
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
position: absolute;
width:calc(100% - 24px);
}
.msg span {
animation: marquee 6s linear infinite;
display: inline-block;
padding-left: calc(100% - 24px);
margin-left:50px;
}
.msg--two span {
animation-delay:3s;
margin-left:50px;
}
#keyframes marquee {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-100%, 0);
}
}
<header class="page-head">
<div class="page-head__ticker">
<p class="msg"><span>Free Shipping on orders over $50</span></p>
<p class="msg msg--two"><span>Free Shipping on orders over $50</span></p>
</div>
</header>

One simple way to get a continuous scrolling effect is to have two copies of your messages and scroll with an animation just 50% of the total width. That way it is smooth - all the messages have gone through and it starts again, 'overwriting' the second copy.
Here's a snippet - it has 24px between the messages but of course such styling can be altered to suit what you want.
body {
background: red;
}
.page-head {
background: white;
box-sizing: border-box;
padding: 0;
position: fixed;
top: 0;
width: 375px;
}
/**
* Ticker
*/
.page-head__ticker {
font-family: "Arial";
font-size: 11px;
font-weight: Bold;
height: 36px;
line-height: 1;
padding: 0 12px;
text-transform: uppercase;
overflow: hidden;
}
.msg {
rmargin: 0 auto;
white-space: nowrap;
overflow: hidden;
animation: marquee 6s linear infinite;
display: inline-block;
}
span {
padding-left: 24px;
/* to give a gap between messages */
}
#keyframes marquee {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-50%, 0);
/* changed from 100% */
}
}
<header class="page-head">
<div class="page-head__ticker">
<p class="msg"><span>Free Shipping on orders over $50</span><span>And here is the second message</span><span>Free Shipping on orders over $50</span><span>And here is the second message</span></p>
</div>
</header>
If your messages are collectively too short to cover the window allocated to the marquee you may want to increase the gap between eg. with a bit of JS.

Related

ReactJS show element on hover

What's the best approach to achieving a lasting effect like in this gif?
I thought the framer-motion whileHover attribute would be my best chance, but I misunderstood how it works, I thought its possible to enter from and to parameters like in CSS animation.
I want to reveal the 'footer' either while the cursor hovers on it or when reaching a certain viewport height.
What's in the gif was made with keyframes animation in css.
I'd appreciate any hint, guide, link to a video on how to build such things.
Thanks in advance
I believe that you can achieve that exact effect using CSS only. This is often preferable, since javascript would bloat your code and be slower to execute.
You can see a way of achieving this effect in this fiddle
Basically, you can use the "hover" pseudoclass to make the aesthetic changes, and then use the "transition" property to animate them.
In the fiddle above, this is the code that actually does the trick:
/* setting base styles for the footer element */
footer {
margin: 0 auto;
width: 200px;
transform: translateY(60px);
transition: width 1s, transform 1s;
}
/* having an inner child will give that "truncated border radius" effect you see in the gif */
footer .inner {
background-color: lightblue;
padding: 3em;
border-radius: 50%;
transition: border-radius 1s;
}
/* Make changes using the "hover" pseudoclass */
footer:hover {
transform: translateY(0px);
width: 100%;
}
footer:hover .inner {
border-radius: 0%;
}
Please be aware that the fiddle I posted is just a hint on how to build this component, but it still miss some features, like the handling of the footer text content itself (right now it won't work well if it's multiline) and accessibility.
See this solution using only css:
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
font-family: Segoe UI, sans-serif;
}
.container {
width: 100vw;
height: 100vh;
}
.container main {
width: 80%;
height: 400px;
margin: auto;
border-radius: 30px;
display: flex;
justify-content: center;
align-items: center;
font-size: 3em;
font-weight: 800;
color: white;
background: rgb(70, 100, 52);
}
.container footer {
width: 100%;
display: flex;
justify-content: center;
}
.container footer .expand {
width: 200px;
height: 50px;
background: royalblue;
border-radius: 40px 40px 0 0;
position: fixed;
bottom: 0px;
display: flex;
justify-content: center;
font-size: 1em;
color: white;
transition: 1000ms;
}
.container footer .expand:hover {
width: 100%;
animation-name: resize;
animation-duration: 700ms;
height: 150px;
border-radius: 0;
}
#keyframes resize {
0% {
height: 50px;
border-radius: 60px 60px 0 0;
}
50% {
height: 160px;
border-radius: 90px 90px 0 0;
}
100% {height: 150px;}
}
<div class="container">
<main>
this is your main feed
</main>
<footer>
<div class="expand">^^^</div>
</footer>
</div>

Stuck on trying to replicate a certain CSS-Transition (CTA-Button that moves to the bottom corner of the page when scrolling down and gets fixed)

So here is a simple fiddle (http://jsfiddle.net/t1xywroc/2/) I created to show you the animation I'm trying to replicate (from this website: https://paperpillar.com/).
I'm still fairly new to Javascript/Jquery and have only been doing HTML and CSS for a couple months.
The problem about my animation is that (as far I know) there is no transition from an absolute position to a fixed position, which I believe causes that small jump, right after triggering the animation (or transition if you will). The second problem is, that the content of the ::before element can't be transitioned either. How can I fix these things using jQuery?
I tried to get it work by using mostly CSS but I keep coming across new problems. I guess it's inevitable to use JavaScript, which is what I need help with. I'd really appreciate it.
Note: not a native speaker.
HTML
<div class="section">
<div class="button"></div>
</div>
CSS
.section {
height: 2000px;
width: auto;
}
.button {
position: absolute;
transform: translateX(50%);
right: 50%;
display: inline-block;
color: white;
line-height: 60px;
height: 60px;
width: auto;
padding-left: 25px;
padding-right: 25px;
background-color: blue;
border-radius: 25px;
vertical-align: middle;
top: 15rem;
}
.button::before{
content: 'Button Text';
}
.floating {
padding-left: 0px;
padding-right: 0px;
position: fixed;
right: 15px;
top: calc(100vh - 120px);
transform: none;
height: 80px;
width: 80px;
transition: all 1.5s ease-in-out;
background-color: red !important;
border: none;
border-radius: 50%;
justify-content: center;
text-align: center;
}
.floating::before{
content:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24px' height='24px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
}
JS
$(document).ready(function() {
$(window).on('scroll', function() {
if ($(window).width() <= 768) {
var scrollTop = $(this).scrollTop();
$('.button').each(function() {
var topDistance = $(this).offset().top;
if ((topDistance - 30) < scrollTop) {
$(this).addClass('floating');
// Haven't put much thought into this part yet
} else if ((topDistance - 30) >= scrollTop){
}
});
}
});
});
A couple of problems have been highlighted in the question: the 'jump' when the transition moves between absolute and fixed and the fact that pseudo elements' content can not be transitioned.
To get round the absolute to fixed jump problem we can set the button to fixed as soon as the transition is to start and then transition. This is possible by introducing CSS animations rather than transitions.
To appear to transition between content we use before pseudo element to hold the initial text (as in the code given) and introduce an after pseudo element that holds the svg. To give the appearance of transitioning between the two we animate opacity.
Note: in the website which is to be emulated the button initially has a white background over the page's white background. This means the change in shape as the initial button fades away is less obvious. With a contrasting blue background the change in shape is much more obvious. That may or may not be the effect required.
Here's a snippet with animations instead of transitions and moving to fixed immediately the animation starts.
$(document).ready(function() {
$(window).on('scroll', function() {
if ($(window).width() <= 2500) {
var scrollTop = $(this).scrollTop();
$('.button').each(function() {
var topDistance = $(this).offset().top;
if ((topDistance - 30) < scrollTop) {
$(this).addClass('floating');
} else if ((topDistance - 100) >= scrollTop){
}
});
}
});
});
.section {
height: 2000px;
width: auto;
position: relative;
}
.button, .button::before, .button::after {
animation-duration: 1.5s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
position: absolute;
}
.button {
transform: translateX(50%);
right: 50%;
line-height: 60px;
height: 60px;
width: auto;
color: transparent; /* do this to ensure the button has dimensions so it can be clicked */
display: inline-block;
vertical-align: middle;
top: 15rem;
}
.button.floating {
position: fixed;
top: 30px;
animation-name: floatdown;
}
.button::before {
content: 'Button\00a0 Text';
opacity: 1;
color: white;
line-height: 60px;
height: 60px;
width: auto;
padding-left: 25px;
padding-right: 25px;
background-color: blue;
border-radius: 25px;
}
.button::after {
content: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24px' height='24px' fill='white'><path d='M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z' /></svg>");
opacity: 0;
padding-left: 0px;
padding-right: 0px;
height: 80px;
width: 80px;
margin-left: -50%;
background-color: red;
border: none;
border-radius: 50%;
justify-content: center;
text-align: center;
}
div.button.floating::before {
animation-name: fadeout;
}
div.button.floating::after {
animation-name: fadein;
}
#keyframes fadeout {
100% {
opacity: 0;
}
}
#keyframes fadein {
100% {
opacity: 1;
}
}
#keyframes floatdown {
100% {
top: calc(100vh - 120px);
right: 95px; /* 80+15px */
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section">
<div class="button">Button text</div>
</div>
Note also that if you want the downarrow to fill the circle more you could put it as a background-image with size contain rather than as content.

How to activate parent animation on focus (tab over to) child

While trying to describe it, I think it would be easiest to simply show the code.
<div class="cdm-animated-card">
<div class="cardTitle">
<h5 class="cardHeader">Collection Title</h5>
</div>
<img class="cardImage" src="collection/thumbnail.jpg" alt="alt text">
<div class="cardDescriptionDiv">
<div class="cardDescriptionText">
<a class="cardLink" href="link/to/collection">this is my clickable description</a>
</div>
</div>
</div>
Obstacle 1: Get the description div to "fade in" on hover. Here's my CSS for that, minus some stuff for the header and other non-relevant parts.
.cardsWrapper {
display: flex;
flex-wrap: wrap;
margin: 0px 10px 10px 10px;
justify-content: center;
}
.cdm-animated-card {
position: relative;
display: flex;
overflow: hidden;
/*other css*/
}
.cardDescriptionText a {
text-decoration: none;
color: #E6AA3C;
font-weight: 400;
padding: 5px;
font-size: 18px;
}
.cdm-animated-card .cardDescriptionDiv {
opacity: 0;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
color: #fff;
padding: 15px;
-webkit-transition: all 0.4s ease-in-out 0s;
transition: all 0.4s ease-in-out 0s;
}
.cdm-animated-card .cardDescriptionText {
text-align: center;
font-size: 18px;
display: inline-block;
position: absolute;
top: 50%;
left: 50%;
width: 75%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.cdm-animated-card:hover .cardDescriptionDiv, .cdm-animated-card.active .cardDescriptionDiv {
opacity: 1;
}
Now when I hover over these cards, the description div fades in. Everything looks centered.. all is well.. but when I tab from elements higher up in the page, I can see [if I'm already hovering over a card], the description text gets that little blue border around it.
Problem is...
When I tab to the anchor [and I'm not already hovering] the animation never happens and basically, if I was unable to use a mouse, I'd never be able to see the description.
I've tried
.cdm-animated-card .cardLink:focus, .cdm-animated-card .cardDescriptionDiv:focus, .cdm-animated-card, .cardDescriptionText:focus {
opacity: 1;
}
basically the darts method... and also tried
.cdm-animated-card:focus .cardDescriptionDiv {
opacity: 1;
}
Because from what I understand, when you tab to an element, it is now "focused," I tried to say, 'when the description is focused via tab, change the opacity of the .cardDescriptionDiv element to 1 so that I can see it.'
tldr: when tabbing to a child, I would like its parent to change opacity.
--face palm--
I missed the ".parent:focus-within" pseudo-class.
.cardDescriptionDiv:focus-within {
opacity: 1;
}
Fixed

Is there any way to smoothly animate the colour of text on hover?

The design I'm working with includes a button hover that fills in the button with colour. Over this is text that on initial state is the same colour as the fill. As the fill proceeds, the colour of the text changes to a contrasting colour, but smoothly. Here is a still of the video the designer gave me that illustrates the issue:
You can see on the letter 'a' that it is two different colours. So I can't change the colour of the text letter-by-letter.
Is there any method (JS/Jquery/whatever/CSS), to achieve this? I'm thinking not, but maybe there is some way of animating a sharp gradient across the text? I don't know.
I actually did something similar for another question a while ago.
This can be achieved with mix-blend-mode. I also slowed the timing down to 5s so that you can clearly see how it works. Change that to 0.25s or whatever meets your needs when in use.
a {
position: relative;
text-decoration: none;
display: inline-block;
padding: 15px 30px;
border: 3px solid #f16251;
background: white;
color: black;
font-size: 30px;
font-family: arial;
mix-blend-mode: normal;
overflow:hidden;
z-index: 1;
}
a:before {
content: '';
position: absolute;
top: 0; bottom: 0; right: 0;
width: 100%; height: 100%;
background: white;
mix-blend-mode: difference;
transform-origin:0 0 ;
transform:translateX(100%);
transition: transform 5s;
z-index: 3;
}
a:hover:before {
transform: translateX(0);
}
a:after{
content: '';
display:block;
top: 0;
left:0;
bottom:0;
right:0;
position: absolute;
z-index: 100;
background: #f16251;
mix-blend-mode: screen;
}
WoOoOoOoT

Animation cuts off multiple lines of text in <p>

This CSS makes the text appear with a typewriter effect. However the issue is that because of the white-space: nowrap in the CSS it only shows the top line.
So if I have text in a single <p> element that covers 4 lines, only the top line gets shown.
See the codepen for example.
p{
color: lime;
font-family: "Courier";
font-size: 20px;
margin: 10px 0 0 10px;
white-space: nowrap;
overflow: hidden;
width: 100%;
animation: type 4s steps(60, end);
}
#keyframes type{
from { width: 0; }
}
Are there any JS based solutions if it is not possible with pure CSS? I would like to not have to try to break up a paragraph into several <p> especially since the point at which there is a line break would get messed up when the width changed.
So if I have text in a single <p> element that covers 4 lines, only the top line gets shown.
Based on the above statement, I assume that the question is about text spanning multiple lines even when the maximum possible width is given to the element (that is, changing just the width is not an option).
As I had mentioned in my comment, the thing with animations like this is that if you remove the white-space: nowrap, it won't work like a typewriter effect because the full text will start getting typed at the same time (as only the width is being animated) and it will result in a weird animation because when the width is small the text will wrap-around and when it increases the text will also move to previous lines.
The text needs to be restricted to a single line or it should be split into multiple p tags like in the below snippet. If neither of these can be done then you should look at using JavaScript (or any library).
body {
background: #000;
padding-top: 10px;
width: 500px;
border: solid white 1px;
}
p {
color: lime;
font-family: "Courier";
font-size: 20px;
margin: 10px 0 0 10px;
white-space: nowrap;
overflow: hidden;
width: 0;
animation: type 4s steps(60, end) forwards;
}
p:nth-child(2) {
animation-delay: 4s;
}
p:nth-child(3) {
animation-delay: 8s;
}
p a {
color: lime;
text-decoration: none;
}
span {
animation: blink 1s infinite;
}
#keyframes type {
to {
width: 100%;
}
}
#keyframes blink {
to {
opacity: .0;
}
}
::selection {
background: black;
}
<p>hi folks, this is typing animation using</p>
<p>CSS. But on the second line it never</p>
<p>shows up. The other lines get cut off.</p>
The below is what would happen if you just remove white-space: nowrap. You can see how it does not work like a typewriter anymore.
body{
background: #000;
padding-top: 10px;
width: 500px;
border: solid white 1px;
}
p{
color: lime;
font-family: "Courier";
font-size: 20px;
margin: 10px 0 0 10px;
overflow: hidden;
width: 100%;
animation: type 4s steps(60, end);
}
p:nth-child(2){
animation: type2 8s steps(60, end);
}
p a{
color: lime;
text-decoration: none;
}
span{
animation: blink 1s infinite;
}
#keyframes type{
from { width: 0; }
}
#keyframes type2{
0%{width: 0;}
50%{width: 0;}
100%{ width: 100; }
}
#keyframes blink{
to{opacity: .0;}
}
::selection{
background: black;
}
<p>hi folks, this is typing animation using CSS But on the second line it never shows up. The other lines get cut off.</p>
If you are open to using a fully JS based approach for achieving this animation then you could follow the method used in this Fiddle. It is a customized version of the Fiddle contributed by Akshay. It uses a loop (based on setInterval) and then modifies the content of the element in every iteration. First it fetches only the first character of the content, then the first two, first three and so-on till the content is fully printed. The looping and the interval makes it look as though it is being typed out.
You can control the speed of the typing, the delay that is added between the typing of lines by passing the required values in the function call.
Try changing the the width of the body from 500px to 100%. Something like this below:
body{
background: #000;
padding-top: 10px;
width: 100%;
border: solid white 1px;
}
You can try this one
body{
background: #000;
padding-top: 10px;
width: 100%;
border: solid white 1px;
}
p{
color: lime;
font-family: "Courier";
font-size: 20px;
margin: 10px 0 0 1px;
white-space: nowrap;
overflow: hidden;
width: 100%;
animation: type 4s steps(60, end);
}
DEMO HERE

Categories

Resources