25

I am looking for a way to select and display a list of countries, preferably with flags. Any suggestions?

I started of by trying this jQuery plugin http://www.graphicpush.com/website-language-dropdown-with-jquery, but as the list of countries I have is quite large it turned out that the performance was really bad (too many http requests to images). Also the list is bulky when it is larger than 50 elements.

Mr.B
  • 917
  • 1
  • 11
  • 20
  • 5
    did you google it? or try anything first? we are not going to do all the work for u :-p – Naftali Mar 23 '11 at 18:18
  • 1
    See [Writing the Perfect Question](http://msmvps.com/blogs/jon_skeet/archive/2010/08/29/writing-the-perfect-question.aspx) – gideon Mar 23 '11 at 18:26
  • Maybe try downloading all the flags and use a batch image converter to reduce their size ? – Pepe Mar 23 '11 at 18:44
  • Try populating a select element with the country names, and then displaying a small flag icon when the `onchange` event is triggered. You can also use a flag "sprite" (think many images in one) and manipulate the `background-position` instead. –  Mar 23 '11 at 18:45
  • I've looked into the sprite solution, but it would be a tedious job converting the ~80 images into a sprite.. – Mr.B Mar 23 '11 at 18:51
  • There also appear to be some CSS sprite generators online. You might want to give those a try. –  Mar 23 '11 at 18:55
  • Here is a gist that use select2 plugin to populate a combo box with country and there flag https://gist.github.com/starx/eed701c8c84e0a475ce5 – Starx Oct 14 '15 at 11:00

5 Answers5

37

Just wanted to suggest a (imho) smarter way of doing the flags sprite.

The idea is to save the flags in a grid according to the country iso2 code.

1st letter -> vertical position
2nd letter -> horizontal position

Examples (for 16x11px flags + 4x4px spacing):

Austria = AT
A = 1   => vertically 1st row       => y = (1-1)*(11+4)  = 0
T = 20  => horizontally 20th column => x = (20-1)*(16+4) = 380

United States = US
U = 21  => vertically 21st row      => y = (21-1)*(11+4) = 300
S = 19  => horizontally 19th column => x = (19-1)*(16+4) = 360

This way I can calculate the flag location with a very easy function on the client side without the need of 200+ extra style definitions.

Sample jQuery plugin:

(function($) {
    // size = flag size + spacing
    var default_size = {
        w: 20,
        h: 15
    };

    function calcPos(letter, size) {
        return -(letter.toLowerCase().charCodeAt(0) - 97) * size;
    }

    $.fn.setFlagPosition = function(iso, size) {
        size || (size = default_size);

        return $(this).css('background-position',
            [calcPos(iso[1], size.w), 'px ', calcPos(iso[0], size.h), 'px'].join(''));
    };
})(jQuery);

Demo Usage:

$('.country i').setFlagPosition('es');

http://jsfiddle.net/roberkules/TxAhb/

And here my flag sprite:

enter image description here

roberkules
  • 6,557
  • 2
  • 44
  • 52
31

Note from the future: jQuery UI autocomplete now supports custom rendering by default, see http://api.jqueryui.com/autocomplete/#method-_renderItem.

It's pretty easy. Things you need:

  1. jQuery UI auto-complete
  2. UI auto-complete html extension
  3. A list of country names/codes
  4. A CSS sprite with all flags

Remember, Google is your friend. Blend the ingredients well, carefully whisk some javascript in, and it's done - in 7 lines of code:

var countries = [["Argentina", "ar"], ...];

var countryNames = countries.map(function(country){
  return {
      label: '<div class="flag '+country[1].toLowerCase()+'">'+country[0]+'</div>',
      value: country[0]
  }
});

$('#country').autocomplete({
  source: countryNames,
  html: true
});

Here's this code in action

Ricardo Tomasi
  • 34,573
  • 2
  • 55
  • 66
1

As mentioned by commenters, a CSS sprite is the proper solution here. Fortunately, there are many CSS sprites of flags freely available. This one looks pretty good.

We will have to tweak the dropdown code to accomodate that pre-made CSS sprite. I've gone ahead and done that for you. Here's a live demo.

languageswitcher.js

@@ -44,10 +44,11 @@
        source.removeAttr("autocomplete");
        var selected = source.find("option:selected");
        var options = $("option", source);
-       $("#country-select").append('<dl id="target" class="dropdown"></dl>')
-       $("#target").append('<dt class="' + selected.val() + '"><a href="#"><span class="flag"></span><em>' + selected.text() + '</em></a></dt>')
-       $("#target").append('<dd><ul></ul></dd>')
+        $("#country-select").append('<dl id="target" class="dropdown f16"></dl>')
+        $("#target").append('<dt><a href="#"><em class="flag ' + selected.val().toLowerCase() + '">' + selected.text() + '</em></a></dt>');
+        $("#target").append('<dd><ul></ul></dd>');
+        var $drop = $("#target dd ul");
        options.each(function(){
-           $("#target dd ul").append('<li class="' + $(this).val() + '"><a href="' + $(this).attr("title") + '"><span class="flag"></span><em>' + $(this).text() + '</em></a></li>');
+            $drop.append('<li><a href="' + $(this).attr("title") + '"><em class="flag ' + $(this).val().toLowerCase() + '">' + $(this).text() + '</em></a></li>');
            });
    }

languageswitcher.css

@@ -45,6 +45,8 @@

 .dropdown dd { position: relative; }

+.dropdown ul { max-height:350px; overflow-y:auto; overflow-x:hidden; }
+
 .dropdown a {
    text-decoration: none;
    outline: 0;
@@ -52,6 +54,7 @@
    display: block;
    width: 130px;
    overflow: hidden;
+    white-space:nowrap;
    }

 .dropdown dt a {
@@ -107,23 +110,6 @@
        padding: 2px 10px;
        }

-   .dropdown dd ul li a span,
-   .dropdown dt a span {
-       float: left;
-       width: 16px;
-       height: 11px;
-       margin: 2px 6px 0 0;
-       background-image: url(flags.png);
-       background-repeat: no-repeat;
-       cursor: pointer;
-       }
-
-       .us a span { background-position: 0 0 }
-       .uk a span { background-position: -16px 0 }
-       .fr a span { background-position: -32px 0 }
-       .de a span { background-position: -48px 0 }
-       .nl a span { background-position: -64px 0 }
-
    .dropdown dd ul li a em,
    .dropdown dt a em {
        font-style: normal;
@@ -138,3 +124,5 @@

        .dropdown dd ul li a:hover { background-color: rgba(255,255,255,.1); }
        .dropdown dd ul li a:hover em { color: #fff; }
+
+.flag { padding-left:18px; }

The CSS changes I made were Q&D hacks; you'll probably want to spend some time polishing them. I removed all of the flag-specific stuff from languageswitcher.css since we're using flag16.css.

Also, if the country code doesn't exist in the CSS sprite, the flag shown will default to the African Union's flag since it is the first image in the sprite. In the demo, several of the countries in my example list don't have a sprite image. Watch out for that.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
josh3736
  • 139,160
  • 33
  • 216
  • 263
  • Thanks for the elaborate solution! I was a bit intimidated at first by looking at the code here, but when I saw the live demo I saw that it wasn't as complicated as a thought. I went with the autocomplete solution this time. But I will keep this solution in mind for the future. Thanks again Josh! – Mr.B Mar 24 '11 at 17:15
  • @Mr.B: The code as presented above is just a [udiff](http://en.wikipedia.org/wiki/Diff), which makes it easy to see exactly what changes I made to the original code from your [link](http://www.graphicpush.com/demos/languageswitcher/). – josh3736 Mar 24 '11 at 18:10
0

You can also use flags from http://www.famfamfam.com/lab/icons/flags/ and simply use CSS for positioning the appropriate flag.

----EDITED----

If i need to show flag of my country then i would do mapping from CSS like

<span class='np'></span>

.np {
background: url(./flags_preview_large.png) -172px -397px no-repeat;
width: 14px;
height: 20px;
}

Anil Prz
  • 1,099
  • 10
  • 14
0

Here's a file with the list of countries and links to their flags (some of the links might not be working though but most of them are) Excel File

Pepe
  • 6,360
  • 5
  • 27
  • 29