Grow your CSS skills. Land your dream job.

Last updated on:

Shuffle DOM Elements

This is from James Padolsey. Check out his article for a pure JavaScript technique as well.

Plugin

(function($){
 
    $.fn.shuffle = function() {
 
        var allElems = this.get(),
            getRandom = function(max) {
                return Math.floor(Math.random() * max);
            },
            shuffled = $.map(allElems, function(){
                var random = getRandom(allElems.length),
                    randEl = $(allElems[random]).clone(true)[0];
                allElems.splice(random, 1);
                return randEl;
           });
 
        this.each(function(i){
            $(this).replaceWith($(shuffled[i]));
        });
 
        return $(shuffled);
 
    };
 
})(jQuery);

Usage

Target elements, call shuffle.

$('ul#list li').shuffle();

Comments

  1. Thank you for this post – it’s useful. I’m going to read again jQuery docs about map, get and replaceWith, and about native js splice as well.

  2. Alexandre Cárdenas
    Permalink to comment#

    Your web design is awesome. I love it. Congratulations!

    Alex

  3. Great piece. Thank You.

  4. Nitin
    Permalink to comment#

    Great plugin. Thanks a million.

  5. Trevor
    Permalink to comment#

    Anyone have an idea how to make this work if you want to randomize say two different lists on the same page? Yes I could assign a different ID to each list then suffle them like so:

    $(‘ul#list1 li’).shuffle();
    $(‘ul#list2 li’).shuffle();

    But what I’d like to be able to do is just go:
    $(‘ul.randlist li’).shuffle();

    And that would then randomize just the list items within that UL, even if I had multiple lists on a page. Right now what it does it randomizes all the list items across ALL the ul’s with that class. Which is not what I want as the list items need to stay with their parent.

  6. Jesse

    Trevor, this is simple using each()

    $('ul.randlist').each(function(){
    $(this).find('li').shuffle()
    })

  7. Jesse

    Also, I noticed that this plugin will break references to the original elements (since it actually copies them). I wrote a version that actually shuffles the original elements.

    “`
    (function($){

    $.fn.shuffle = function() {
    
      var elements = this.get()
      var copy = [].concat(elements)
      var shuffled = []
      var placeholders = []
    
      // Shuffle the element array
      while (copy.length) {
        var rand = Math.floor(Math.random() * copy.length)
        var element = copy.splice(rand,1)[0]
        shuffled.push(element)
      }
    
      // replace all elements with a plcaceholder
      for (var i = 0; i < elements.length; i++) {
        var placeholder = document.createTextNode('')
        findAndReplace(elements[i], placeholder)
        placeholders.push(placeholder)
      }
    
      // replace the placeholders with the shuffled elements
      for (var i = 0; i < elements.length; i++) {
        findAndReplace(placeholders[i], shuffled[i])
      }
    
      return $(shuffled)
    
    }
    
    function findAndReplace(find, replace) {
      find.parentNode.replaceChild(replace, find)
    }
    

    })(jQuery)
    “`

  8. Andrew Van Wart

    Excellent tip! I would just add that if you have nested list items (ul ul li) within your parent ul#list, in order to only randomize the parent list items, use this code to initialize:

    $('ul#list > li').shuffle();
  9. Trevor

    Thanks Jesse! Wow, that was an easy fix, I clearly need to learn jQuery better. And good stuff with your updated shuffle function!

    I just wondered what exactly you meant by the function “will break references to the original elements”?

  10. Permalink to comment#

    license?

  11. Rahul
    Permalink to comment#

    What is the minimum number of item required?

  12. Nice solution :)
    I’ve made a small change to make a plugin to randomly remove some items:
    (function($) {
    $.fn.randomRemove = function(n) {
    var allElems = this.get(),
    getRandom = function(max) {
    return Math.floor(Math.random() * max);
    };
    if (allElems.length > n) {
    while (n > 0) {
    var random = getRandom(allElems.length);
    $(allElems[random]).remove();
    allElems.splice(random, 1);
    n–;
    }
    }
    return $(allElems);
    };
    })(jQuery);

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".