8
    <p class="example">i want to split this paragraph into 
words and fade them in one by one</p>

the jquery/js:

$(document).ready(function() {

    var $txt = $(".example")
       ,$words = $txt.text()
       ,$splitWords = $words.split(" ");

    $txt.hide();

    for(i = 0; i < $splitWords.length; i++){
     // i want fade in each $splitWords[i]
     //$splitWords[i].fadeIn(....  - i tried this doesnt work

   }
  });

im trying to split the paragraph into words, and fade them in one by one, thier might be an easier way to do this without splitting the words, please shed some light on this. thanks

unknown
  • 846
  • 3
  • 15
  • 38
  • 7
    Text by itself can't have an opacity, therefore you must wrap the text with an element that can have opacity (such as a span). You can then fade in those spans. – Kevin B Jul 24 '12 at 19:04

3 Answers3

15

Text by itself can't have an opacity, therefore you must wrap the text with an element that can have opacity (such as a span). You can then fade in those spans.

Try this:

http://jsfiddle.net/6czap/

var $el = $(".example:first"), text = $el.text(),
    words = text.split(" "), html = "";

for (var i = 0; i < words.length; i++) {
    html += "<span>" + words[i] + " </span>";
}

$el.html(html).children().hide().each(function(i){
  $(this).delay(i*500).fadeIn(700);
});

Update for benekastah: http://jsfiddle.net/6czap/3/

var $el = $(".example:first"), text = $.trim($el.text()),
    words = text.split(" "), html = "";

for (var i = 0; i < words.length; i++) {
    html += "<span>" + words[i] + ((i+1) === words.length ? "" : " ") + "</span>";
};
$el.html(html).children().hide().each(function(i){
  $(this).delay(i*200).fadeIn(700);
});
$el.find("span").promise().done(function(){
    $el.text(function(i, text){
       return $.trim(text);
    });            
});
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Does that leave unknown amouts of spans in the DOM? – Bergi Jul 24 '12 at 19:33
  • I would suggest removing the span off each word as soon as it is done animating. This could be done by creating an empty span at the beginning of the `

    ` and appending each word to it as it finishes animating, and then deleting the word-specific span altogether. (Although I'm not sure if that would result in any choppiness while animating -- seems like it should work).

    – benekastah Jul 24 '12 at 19:50
  • @benekastah: See my answer for a cleaner solution – Bergi Jul 24 '12 at 20:18
  • Thank you for this. It's a lifesaver. I used the first version with the spans left in as I needed to add a class to specific words also so this helped a lot. Thanks – Emma Dalby Feb 07 '19 at 10:13
3

You will need to fade in elements, text nodes can't have a opacity.

See demo at jsfiddle.net

var p = $("p.example").hide(); // possible flash! You should add some script
                               // to the <head> that writes a stylesheet
                               // to hide them right from the start
(function oneParagraph(i) {
    if (p.length <= i)
        return;
    var cur = p.eq(i),
        words = cur.text().split(/\s/),
        span = $("<span>"),
        before = document.createTextNode("");
    cur.empty().show().append(before, span);
    (function oneWord(j) {
        if (j < words.length) {
            span.hide().text(words[j]).fadeIn(200, function() {
                span.empty();
                before.data += words[j]+" ";
                oneWord(j+1);
            });
        } else {
            span.remove();
            before.data = words.join(" ");
            setTimeout(function(){
                oneParagraph(i+1);
            }, 500);
        }
    })(0);
})(0);

If you need only one paragraph, you can leave out all the things beloning to the oneParagraph function - just make cur the selected element.

If you want to have a smoother animation, you'd need to animate multiple words at the same time (demo), or dont fade but append letterwise like in here. Alternatively you could make the fading-time dependent on the length of the current word.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Good call on appending the text to a text node instead of a span. Although I'm curious, after appending each word to `before.data` individually, why do you reset the whole thing: `before.data = words.join(" ");`? It seems like all that does is get rid of a trailing space. – benekastah Jul 24 '12 at 20:32
  • Yes, it was supposed to do exactly that :-) Of course you can remove the line, the space won't be displayed anyway. – Bergi Jul 24 '12 at 20:34
0

You'll have a couple problems with the suggestions mentioned so far.

First, splitting and then hiding the text in Javascript will result in a Flash of Unstyled Content. Second, the number of reflows is going to be pretty bad for long text.

Rather than hiding the text, consider setting the foreground and background to the same color, and then changing it back.

Jason
  • 3,021
  • 1
  • 23
  • 25