最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Word change in phase, CSS vertical animation loop - Stack Overflow

programmeradmin0浏览0评论

I guess that's nothing better to explain than this:


I almost acplished what I want with pure CSS, but...

  • I have to manually set the "location" of each word
  • If another word is appended, I have to calculate everything again
  • I can't set the 1 sec time of each word, just the total animation time
  • Responsive? Just if I calculate everything again

The code is a div with overflow: hidden and a child with negative margin-top (and animation).

Live demonstration:

body {
  font-size: 2em;
  font-family: sans-serif;
 }
 
 .animation {
    vertical-align: sub;
    height: 1em;
    overflow: hidden;
    display: inline-block;
    line-height: 2em;
 }
 
ul {
  animation: animation 10s infinite;
  padding: 0;
  margin-top: -0.55em;
  list-style: none;
}

@keyframes animation {
    0%        { margin-top: -0.55em }
    12.5%     { margin-top: -2.54em }
    25%       { margin-top: -4.55em }
    37.5%     { margin-top: -6.55em }
    50%       { margin-top: -8.5em }
    62.5%     { margin-top: -6.55em }
    75%       { margin-top: -4.55em }
    87.5%     { margin-top: -2.54em }
    100%      { margin-top: -0.55em }
}
 Lorem ipsum dolor sit
 
    <div class="animation">
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit. 

I guess that's nothing better to explain than this:


I almost acplished what I want with pure CSS, but...

  • I have to manually set the "location" of each word
  • If another word is appended, I have to calculate everything again
  • I can't set the 1 sec time of each word, just the total animation time
  • Responsive? Just if I calculate everything again

The code is a div with overflow: hidden and a child with negative margin-top (and animation).

Live demonstration:

body {
  font-size: 2em;
  font-family: sans-serif;
 }
 
 .animation {
    vertical-align: sub;
    height: 1em;
    overflow: hidden;
    display: inline-block;
    line-height: 2em;
 }
 
ul {
  animation: animation 10s infinite;
  padding: 0;
  margin-top: -0.55em;
  list-style: none;
}

@keyframes animation {
    0%        { margin-top: -0.55em }
    12.5%     { margin-top: -2.54em }
    25%       { margin-top: -4.55em }
    37.5%     { margin-top: -6.55em }
    50%       { margin-top: -8.5em }
    62.5%     { margin-top: -6.55em }
    75%       { margin-top: -4.55em }
    87.5%     { margin-top: -2.54em }
    100%      { margin-top: -0.55em }
}
 Lorem ipsum dolor sit
 
    <div class="animation">
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit. 


So...

I think that I can't solve my problems because they are CSS limitations, so... It is possible to get this with jQuery?

Share Improve this question edited Jun 9, 2016 at 1:56 Quentin Roy 7,8872 gold badges33 silver badges52 bronze badges asked Jun 8, 2016 at 21:52 ProgrammeurProgrammeur 1,5314 gold badges22 silver badges33 bronze badges 4
  • This is possible with jQuery. Just append the first item to the (inline-block) list to make an infinite loop. Animation can be added afterwards. – Mr. Hugo Commented Jun 8, 2016 at 22:06
  • @JoostS The problem with this approach is that, on almost every screen, the (real) text have 2 lines, so this causes a that "animation bug". I can't explain exactly, but the result is not smooth. – Programmeur Commented Jun 8, 2016 at 22:10
  • I know that you can put an element in an href and it'll bring it into focus on click... does that help at all? – JackHasaKeyboard Commented Jun 9, 2016 at 0:28
  • i really can't understand people that down-vote a working solution and do not leave a ment. It is really sad. Probably it must have been just a mean fool. :) – user2560539 Commented Jun 9, 2016 at 9:31
Add a ment  | 

4 Answers 4

Reset to default 3

Here's a shot at a CSS solution. Not entirely sure what aspects of the reference image are important, so I tried match it as closely as possible. However, I did need to duplicate the list in the mark-up to get it to shift color from lightgray to black as it scrolls through the view box.

Also note the animation frames and timing is tightly coupled with how many items are in the list. If the number of items is expected to be dynamic, there'll probably need to be some JavaScript intervention.

body {
  font-size: 2em;
  font-family: sans-serif;
  line-height: 1.2
}

.animation {
  display: inline-block;
  vertical-align: top;
  text-align: center;
  border: 1px solid;
  overflow: visible;
  white-space: nowrap;
  color: lightgray;
  position: relative;
}

.animation ul {
  list-style: none;
  padding: 0 .5ex;
  margin: 0;
  height: 1.2em;
}

.animation li {
  position: relative;
  animation: cycle-5-items 5s ease-in-out alternate infinite;
}

.animation ul.mask {
  color: black;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}

@keyframes cycle-5-items {
  0%, 10% {
    transform: translateY(0%);
  }
  
  15%, 35% {
    transform: translateY(-100%);
  }
  
  40%, 60% {
    transform: translateY(-200%);
  }
  
  65%, 85% {
    transform: translateY(-300%);
  }
  
  90%, 100% {
    transform: translateY(-400%);
  }
}
Lorem ipsum dolor sit
 
    <div class="animation">
      <ul class="mask">
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit.

You don't need jQuery. Here is a simple pure js solution using css transition.

function createWordListAnimation(animNode, delay){
  // Fetch the DOM elements.
  var animWindow = animNode.querySelector(".animation-window");
  var ul = animWindow.querySelector("ul");
  var lis = ul.querySelectorAll("li");

  // Copy the animation's window to create the gray list.
  var grayList = animWindow.cloneNode(true);
  var grayUl = grayList.querySelector("ul");
  grayList.classList.remove("animation-window");
  grayList.classList.add("animation-gray-list");
  animNode.insertBefore(grayList, animWindow);

  // This function shows the li number `liNum`.                     
  function goTo(liNum){
    var li = lis[liNum];
    var liTop = li.getBoundingClientRect().top;
    var ulTop = ul.getBoundingClientRect().top;
    var liOffset = liTop - ulTop;
    ul.style.top = -liOffset + "px";
    grayUl.style.top = -liOffset + "px";
  }

  // Set up an interval that changes the current li every `delay` ms.
  var current = 0;
  // We need a boolean to know if the animation is going up or down.
  var ascending = true;
  // Create the interval.
  return setInterval(function(){
    ascending = ascending && current + 1 < lis.length || current === 0;
    current = ascending ? current + 1: current - 1;
    goTo(current);
  }, delay);
}

createWordListAnimation(document.querySelector(".animation"), 1000 /* (ms) */);
body {
  font-size: 2em;
  font-family: sans-serif;
}

.animation {
  vertical-align: sub;
  display: inline-block;
  margin-top: -.1em;
  margin-bottom: -.1em;
  border-style: solid;
  border-color: lightgray;
  border-width: 1px;
  height: 1.2em;
}

.animation-window {
  position: relative;
  height: 100%;
  overflow: hidden;
  background-color: white;
}

.animation-gray-list {
  position: absolute;
  color: lightgray;
}

.animation ul {
  position: relative;
  list-style: none;
  top: 0;
  padding: 0;
  margin: 0;
  transition: top 300ms;
}

.animation li {
  margin: 0 .2em;
  text-align: center;
}
Lorem ipsum dolor sit
 
    <div class="animation">
      <div class="animation-window">
        <ul>
          <li>golfish</li>
          <li>dog</li>
          <li>cat</li>
          <li>hamster</li>
          <li>fox</li>
        </ul>
      </div>
    </div>,

consectetur adipiscing elit.

The drawback of this solution is that the window cannot be transparent (it has to hide the gray list). It is still possible to make it transparent, but you'll have to create two gray lists – one above, one below – and it starts to be a bit plicated.

Use jQuery animate() for what you want to achieve. You can check the below example.

var length = $("li").length;
var p = 0;
var u = 0;
while(u<10000) {
for(i=0;i<length;i++){
  $( "ul" ).animate({
    marginTop: "-"+(i*2)+".55em"
  }, 1000 );
  p = i+1;
}

if(p==length){
for(j=p-1;j>=0;j--){
  $( "ul" ).animate({
    marginTop: "-"+(j*2)+".55em"
  }, 1000 );
}
}
u++;
}
body {
  font-size: 2em;
  font-family: sans-serif;
 }
 
 .animation {
    vertical-align: sub;
    height: 1em;
    overflow: hidden;
    display: inline-block;
    line-height: 2em;
   border: 1px solid #eee;
 }
 
ul {
  padding: 0;
  margin-top: -0.55em;
  list-style: none;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>

 
 Lorem ipsum dolor sit
 
    <div class="animation">
      <ul>
        <li>golfish</li>
        <li>dog</li>
        <li>cat</li>
        <li>hamster</li>
        <li>fox</li>
      </ul>
    </div>
    
, consectetur adipiscing elit. 

Here is a fiddle with more elements.

Here is the code without animation, using $('ul > li:first-child').appendTo('ul');: http://codepen.io/anon/pen/BzjyBZ.

Here it is with the animation added: http://codepen.io/anon/pen/qNbrva

发布评论

评论列表(0)

  1. 暂无评论