Grow your CSS skills. Land your dream job.

Make a Select’s Options Printable

Published by Chris Coyier

When printing a web page with <select> elements on it, the select dropdown prints just like it looks.

This is of course borderline useless on a printed page. It may even be hiding important details vital to understanding what the printed page is about (e.g. options for a product).

Unfortunately I don't know of any really simple and clean ways of handling this. One option is to succeed all select HTML elements with an unordered lists duplicating the same content. Hide the unordered lists in your regular display CSS, but then reveal it with your print stylesheet. This is a reasonable approach I think, except for the fact that is a big ol' pain in the butt to deal with all the time.

As we so often do around here, let's lean on jQuery to do the heavy lifting instead:

  1. Loop through each select on the page
  2. Insert a DIV after it with an UL for the options.
  3. Loop through each option in that select and append LI's to the UL
  4. Make sure the DIV is hidden in general (display: none is fine) and shown in the print sylesheet
$(function(){
        
     $("select").each(function(i){
     
         var $el = $(this);
         var $options = $el.find("option");
         
         $el.after("<div class='print-select'>Options: <ul id=sel"+i+"></ul></div>");
         
         var $curPrintBox = $("#sel"+i);
                         
         $options.each(function() {
             
             $curPrintBox.append("<li>"+$(this).text()+"</li>");
             
         });    
     
     });

 });

 

View Demo

View source of the demo page to see all the JavaScript, CSS, and HTML together.

With MooTools

David Walsh, as always, is right there with the same technique only in MooTools.

Comments

  1. Permalink to comment#

    Hey, I’ve been looking for something like this!

    Thanks Chris (and David)!

  2. Permalink to comment#

    ooo k thanks ill try it layer

    check out my site to see it

  3. Permalink to comment#

    Nice feature, as allways! One thing which could do it even more useful, is to add another id to the li element representing the selected option. :-)

  4. Permalink to comment#

    wow, that’s really useful. thanks

  5. I’ve modified example to print all options, but the one that is selected is bold (other ones are italic). Maybe for someone this example will be useful. To try, follow these instructions:

    Add this to style for screen:

    .selected	   { font-weight: bold; font-style: normal}

    Add this to style for print (.selected class must be duplicated):

    .selected	   { font-weight: bold; font-style: normal}
    select 		   { display: none; }

    Javascript function is modified like this:

    $(function(){
            
                $("select").each(function(i){
                
                    var $el = $(this);
                    var $options = $el.find("option"); 
    				var $sel = $el.find(":selected");
    				
                    $el.after("");								
                    				
                    var $curPrintBox = $("#sel"+i);
                    
    				$el.change(function(){
    					var txt = $(this).val();
    					var prev_sel_li = $("#sel"+i).find("li.selected");
    					prev_sel_li.removeClass("selected");
    					var sel_li = $("#sel"+i).find("li:contains("+txt+")");
    					sel_li.addClass("selected");					
    				});
                    
                    $options.each(function() {
    					var appendStyle = "";
                        if ($(this).val() == $sel.val()) {
    						appendStyle = 'class=\"selected\"';
    					}
                        $curPrintBox.append(""+$(this).text()+"");                    
                    });    
                
                });
    						
            }); 
  6. Permalink to comment#

    I would use PHP to do that rather then jQuery.
    Create an array of the options, generate the and s, then generate the hidden .

    • Permalink to comment#

      And once again I am forgetting that I can’t write tags.
      so my message:
      I would use PHP to do that rather then jQuery.
      Creat an array of the options, generate the select and options, then generate the hidden div.

    • Permalink to comment#

      Yes, but that would mean you have duplicates in the HTML whereas the jQuery solution only changes the loaded DOM.

      It’s a bit of a dilemma: semantic HTML or a JavaScript-free solution.

    • Permalink to comment#

      Matti, if you calculate the total download size (and number of requests) you’ll know that PHP is superior. Assuming you won’t make an internal script sheet (which you probably won’t…), you’ll need another request for it. Plus if you take the size of the jquery code vs just the HTML the PHP generates (because PHP code isn’t downloaded), you’ll see that the PHP is definitely smaller.

    • Permalink to comment#

      I would personally use the PHP solution because if you use javascript/jQuery the user only has to disable javascript in their browser and BOOM there goes all your hard work.

    • Permalink to comment#

      Yes I agree with you. I also do it with PHP :)

    • Spencer
      Permalink to comment#

      I would be for the server-side option myself, but the “minified” version is only 55KB (or am I missing something), and if you’re already using jQuery or “just tacking it on,” it’s an easy and elegant solution. And lets face it, JS is part of the web and sacrificing a little print isn’t the worst of your martyrdom/fear.

      Using jQuery is not bad habit-forming.

  7. Ben B
    Permalink to comment#

    This seems like it could be really useful technique.

    However, what’s getting me to comment this time is something I noticed on your demo’s source code.

    Specifically:

    google.load("jquery", "1.3.2");

    This seems like a really useful tool when creating concept pages. Where can I find more info on this?

    • Ben B
      Permalink to comment#

      I notice that after I clicked submit that it ignored the code tags and is only showing the one line, unless that part is pending approval? Anyway let me try again this time fudging the tags

      (script src="http://www.google.com/jsapi" type="text/javascript")
      (/script)

      (script type="text/javascript")
      google.load("jquery", "1.3.2");
      (/script)

      Replaced standard tag open/close with ( & ) save for the google.load line, that’s like that in the code

    • Permalink to comment#

      @Ben B: You can find info on the Google AJAX Libraries API here: http://code.google.com/apis/ajaxlibs/

  8. Permalink to comment#

    Maybe we can use the size attribute?

    function printpage() {
    var s = document.getElementsByTagName('select');
    for (var i=0; i<s.length; i++) {
    s[i].size = s[i].options.length;
    }
    window.print();
    }

    I haven’t had success getting it back to normal after the print though.

  9. Permalink to comment#

    I’ve made a slight change that can make this really useful as well.

    If you change the line

    var $options = $el.find("option");

    to

    var $options = $el.find("option:selected");

    you print ONLY the selected item.

  10. Permalink to comment#

    Good idea, but if you wont create div.print-select in non-printable version, you will do some correct:
    1)In print version: select{display:none}
    2)In script: $(“select:hidden”).each(function(i)…

    sorry for my eng (:

  11. My only gripe with this is that you’re taxing the user’s system (no matter how slightly) EVERY time the page is loaded, regardless of whether or not they will be printing the page (because if they don’t print, the affect of this code is useless.

    I wonder what percentage of every web page loaded per given time period is actually printed. My guess would be a minuscule amount.

  12. Permalink to comment#

    Very nice. I like the jquery solution, especially considering maybe 1% would print it.

  13. Permalink to comment#

    I have to hand it to you, you come up with some very different ways of using JavaScript/jQuery, I don’t think I ever would have thought off doing this.

  14. Permalink to comment#

    Why not just use jQuery to set the ‘multiple’ attribute?

    [ select multiple="multiple" ]

    ( Brackets would be < and > )

    Automatically revealing all options

    • This is a good idea, probably the cleanest way to do it. I think in order to have it come out perfect you’d have to make sure that you set the width of the select to be wide enough that you don’t get any cut-off though (probably 100%).

  15. Blue
    Permalink to comment#

    I think a Nice addition would be to hide the select menu in the print verison of the stylesheet as well.

  16. DougS
    Permalink to comment#

    this is nice, Chris. I’ve been looking at several sites that use different techniques to actually style the tags. Does anyone have any tips on this topic? It seems to get pretty heavy based on the sites I’ve looked at…..I wanted to use a single image in the background and CSS scroll…no luck yet….

    cheers :D

This comment thread is closed. If you have important information to share, you can always contact me.

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