There is a running line

body { margin: 0; padding: 0; } #quotes-container { width: 100%; height: 51px; background-color: rgba(0, 0, 0, 0.8); overflow: hidden; white-space: nowrap; } #quotes { display: inline-block; font-family: "Tahoma"; padding: 1em 1em 1em 100%; margin: 0; animation: scroll 30s infinite linear; } #quotes li { display: inline-block; margin-right: 40px; font-weight: bold; list-style: none; color: #fff; width: 210px; } #quotes li span { margin: 0 10px; font-weight: normal; color: #aab9d1; } #quotes li span:nth-child(odd) { position: relative; } #quotes li span:nth-child(odd):after { position: absolute; top: 0; right: -14px; content: "|"; } #quotes li.up span:nth-child(odd) { position: relative; margin-left: 20px; } #quotes li.up span { color: #00ca51; } #quotes li.up span:nth-child(odd):before { position: absolute; left: -14px; top: 6px; content: ' '; border-width: 0 5px 9px 5px; border-style: solid; border-color: #00ca51 transparent; } #quotes li.down span:nth-child(odd) { position: relative; margin-left: 20px; } #quotes li.down span { color: #f12424; } #quotes li.down span:nth-child(odd):before { position: absolute; left: -14px; top: 6px; content: ' '; border-width: 9px 5px 0 5px; border-style: solid; border-color: #f12424 transparent; } #quotes li.round span:nth-child(odd) { position: relative; margin-left: 20px; } #quotes li.round span:nth-child(odd):before { position: absolute; left: -14px; top: 7px; width: 8px; height: 8px; border-radius: 8px; background-color: #aab9d1; content: ' '; } -webkit-keyframes scroll 0% { -webkit-transform: translate(0, 0); -ms-transform: translate(0, 0); transform: translate(0, 0) } -webkit-keyframes scroll 100% { -webkit-transform: translate(-100%, 0); -ms-transform: translate(-100%, 0); transform: translate(-100%, 0) } @-webkit-keyframes scroll { 0% { -webkit-transform: translate(0, 0); transform: translate(0, 0) } 100% { -webkit-transform: translate(-100%, 0); transform: translate(-100%, 0) } } @keyframes scroll { 0% { -webkit-transform: translate(0, 0); transform: translate(0, 0) } 100% { -webkit-transform: translate(-100%, 0); transform: translate(-100%, 0) } } 
 <div id="quotes-container"> <ul id="quotes"> <li id="Ripple" class="down">Ripple<span id="bidRipple">0.6297</span><span id="askRipple">0.6314</span></li> <li id="Litecoin" class="round">Litecoin<span id="bidLitecoin">159.06</span><span id="askLitecoin">161.25</span></li> <li id="Ethereum" class="up">Ethereum<span id="bidEthereum">518.4</span><span id="askEthereum">522.21</span></li> <li id="USDCHF" class="round">USDCHF<span id="bidUSDCHF">0.9467</span><span id="askUSDCHF">0.9468</span></li> <li id="USDJPY" class="round">USDJPY<span id="bidUSDJPY">104.903</span><span id="askUSDJPY">104.911</span></li> <li id="EURCAD" class="round">EURCAD<span id="bidEURCAD">1.59199</span><span id="askEURCAD">1.592</span></li> <li id="Dash" class="round">Dash<span id="bidDash">407.87</span><span id="askDash">410.39</span></li> <li id="AUDUSD" class="round">AUDUSD<span id="bidAUDUSD">0.77241</span><span id="askAUDUSD">0.77249</span></li> <li id="Bitcoin" class="round">Bitcoin<span id="bidBitcoin">8436</span><span id="askBitcoin">8456.1</span></li> <li id="NZDUSD" class="round">NZDUSD<span id="bidNZDUSD">0.72707</span><span id="askNZDUSD">0.72717</span></li> <li id="EURUSD" class="round">EURUSD<span id="bidEURUSD">1.23742</span><span id="askEURUSD">1.23762</span></li> <li id="AUDCAD" class="round">AUDCAD<span id="bidAUDCAD">0.9937</span><span id="askAUDCAD">0.9942</span></li> <li id="GBPUSD" class="round">GBPUSD<span id="bidGBPUSD">1.41651</span><span id="askGBPUSD">1.41656</span></li> </ul> </div> 

I just can’t figure out how to make sure that there is not such a big gap between going off the screen and going out, i.e. make it so that the string is still not completely gone beyond the limits of the screen on the left, and already appears on the right.

And also: it happens that the animation starts to slow down after a while. How to deal with this?

Thank!

  • The easiest option is to use two #quotes blocks one after another at the required distance, and just at the right moment to launch the second one. As for slowdowns, the browser itself optimizes the frame rate with a good graphics card and system optimization, there will not be any slowdowns. - Vasiliy Rusin
  • Possible duplicate question: How to create a vertical continuous running line? - Air

2 answers 2

With the approach - "each element has its own ID" - I do not agree and I would like to clarify.

ID is a unique identifier for a specific item. The key word here is “unique” and it means that such an ID will be only one per page. When using this attribute, "flexibility" is lost in manipulations with elements (for example, cloning or creating an element with the same ID value). The appearance of elements with the same identifier may lead to unpredictable results - somewhere only the first element can be processed, and somewhere the code may turn out to be completely unworkable. Therefore, the use of ID should be where it is really justified and / or necessary.

In most cases, you can and should use other ways to access the elements:

  • by user attributes ( data-attr );
  • by class names and other CSS selectors using querySelector ;
  • by child, using children[] .

In the code from the question, the ID values ​​of the nested elements differ from the parent identifier, only by the prefixes ( bid and ask ) and are not carried any more payload. At the same time, the structure of all items is the same. In this case, we change the id attribute to the user attribute data-curr , and further, we refer to the descendants with the help of children[n] , since these elements are always in the same order. Thus, it will be possible to clone and create elements without fear of ID duplication.

I have already described the algorithm here and the most common error of the "running line" with the help of animation , t.ch. I will not repeat. I will only add that for the correct operation of this approach, there is a mandatory condition - the width (height, for a vertical line) of the scrollable element must be twice as large as the maximum width (height) of the container in which the element is scrolled.

 window.onload = function() { var oQuotes = document.querySelector('#quotes-container ul.quotes'); /* Функция дублирования пунктов */ function fDoublingQuotes() { let nElem = oQuotes.children.length; for (let i = 0; i < nElem; i++) { oQuotes.appendChild(oQuotes.children[i].cloneNode(true)); } oQuotes.style.animationDuration = '1s,' + (nElem * 2) + 's'; } /* Функция для изменения значений пунктов */ function fSetQuote(sId, sClass, sBid, sAsk) { let aQuotes = oQuotes.querySelectorAll('li[data-curr="' + sId + '"]'); aQuotes.forEach(function(item) { item.className = sClass || item.className; item.children[0].innerText = sBid || item.children[0].innerText; item.children[1].innerText = sAsk || item.children[1].innerText; }); } document.querySelector('button').addEventListener('click', function() { fSetQuote('Ripple', '', '0', '1'); }); fDoublingQuotes(); } 
 body { margin: 0; padding: 0; } #quotes-container { position: relative; height: 51px; width: 100%; overflow: hidden; white-space: nowrap; background-color: rgba(0, 0, 0, 0.8); } #quotes-container:before, #quotes-container:after { content: ''; position: absolute; height: 51px; width: 25px; top: 0; z-index: 1; background: linear-gradient(90deg, rgba(0, 0, 0, 1.0), rgba(0, 0, 0, 0.0)); } #quotes-container:after { right: 0; transform: scaleX(-1); } .quotes { display: inline-block; margin: 0; padding: 0; font-size: 0; /* Важно! */ animation: begin 1s ease forwards, scroll 30s linear 1s infinite; } .quotes li { display: inline-block; margin: 1em 40px 1em 0; font: bold 16px 'Tahoma'; list-style: none; color: #fff; } .quotes li span { margin: 0 10px; font-weight: normal; color: #aab9d1; } .quotes li span:nth-child(odd) { position: relative; } .quotes li span:nth-child(odd):after { content: '|'; position: absolute; right: -14px; top: -1; } .quotes li.up span:nth-child(odd), .quotes li.down span:nth-child(odd), .quotes li.round span:nth-child(odd) { margin-left: 20px; } .quotes li.round span:nth-child(odd):before { content: '⚫'; position: absolute; left: -16px; top: 0px; } .quotes li.up span { color: #00ca51; } .quotes li.up span:nth-child(odd):before { content: '▲'; position: absolute; left: -18px; top: 1px; } .quotes li.down span { color: #f12424; } .quotes li.down span:nth-child(odd):before { content: '▼'; position: absolute; left: -18px; top: 1px; } @keyframes scroll { 0% { transform: translateX(0%); } 100% { transform: translateX(-50%); } } @keyframes begin { 0% { transform: scaleY(0); } 100% { transform: scaleY(1); } } 
 <div id="quotes-container"> <ul class="quotes"> <li data-curr="Ripple" class="down">Ripple<span>0.6297</span><span>0.6314</span></li> <li data-curr="Litecoin" class="round">Litecoin<span>159.06</span><span>161.25</span></li> <li data-curr="Ethereum" class="up">Ethereum<span>518.4</span><span>522.21</span></li> <li data-curr="USDCHF" class="round">USDCHF<span>0.9467</span><span>0.9468</span></li> <li data-curr="USDJPY" class="round">USDJPY<span>104.903</span><span>104.911</span></li> <li data-curr="EURCAD" class="round">EURCAD<span>1.59199</span><span>1.592</span></li> <li data-curr="Dash" class="round">Dash<span>407.87</span><span>410.39</span></li> <li data-curr="AUDUSD" class="round">AUDUSD<span>0.77241</span><span>0.77249</span></li> <li data-curr="Bitcoin" class="round">Bitcoin<span>8436</span><span>8456.1</span></li> <li data-curr="NZDUSD" class="round">NZDUSD<span>0.72707</span><span>0.72717</span></li> <li data-curr="EURUSD" class="round">EURUSD<span>1.23742</span><span>1.23762</span></li> <li data-curr="AUDCAD" class="round">AUDCAD<span>0.9937</span><span>0.9942</span></li> <li data-curr="GBPUSD" class="round">GBPUSD<span>1.41651</span><span>1.41656</span></li> </ul> </div> <button>Изменить "Ripple"</button> 

If something is incomprehensible by code and logic, then we ask in the comments - I will answer or supplement the answer.

  • one
    Super ........... - Air
  • @Air well, you need to generate content for ruSO)) Not everything should be done for me) - UModeL
  • As a question, I read the thought at once, I realized it was implemented like that of a ... Well, I scrolled down a little and found your answer))) - Air
  • By the way, I would implement without pseudo-elements. it would just be possible to clone the parent, and the code would be smaller, and if suddenly something needs to be changed, it would be much easier. - Air
  • @Air I have pretty much cut off the source code)) And so, of course, there is something to smooth more. - UModeL

As an option ...

 * { list-style: none; } .wrapper { width: 100%; overflow: hidden } ul { display: flex; justify-content: space-around; position: relative; width: 200%; animation: scroll 10s infinite linear; } li { text-align:center; background:#fbfbfb; } @keyframes scroll { 0% { left: 0%; } 100% { left: -110%; } } 
 <div class="wrapper"> <ul> <li>item1</li> <li>item2</li> <li>item3</li> <li>item4</li> <li>item5</li> <li>item6</li> <li>item7</li> <li>item8</li> <li>item9</li> <li>item10</li> </ul> </div> 

either this option: https://codepen.io/topicstarter/pen/OvxxXP?editors=1100