diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index e1eb5858da9b42150f75c31f762d0bc720a0a335..6c994a9fe983c8034630abc1bb8fb239f3c48379 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -95,6 +95,8 @@ class Person(ExtensibleModel):
         verbose_name = _("Person")
         verbose_name_plural = _("Persons")
 
+    icon_ = "person"
+
     SEX_CHOICES = [("f", _("female")), ("m", _("male"))]
 
     user = models.OneToOneField(
@@ -227,6 +229,8 @@ class Group(ExtensibleModel):
         verbose_name = _("Group")
         verbose_name_plural = _("Groups")
 
+    icon_ = "group"
+
     name = models.CharField(verbose_name=_("Long name of group"), max_length=255, unique=True)
     short_name = models.CharField(verbose_name=_("Short name of group"), max_length=255, unique=True, blank=True, null=True)
 
diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js
index f3439d2a573a93a094e189c142e0d9fc6ee41cf8..275e3ae6e7765823308ba3f4bc91c2c462211b16 100644
--- a/aleksis/core/static/js/main.js
+++ b/aleksis/core/static/js/main.js
@@ -64,4 +64,8 @@ $(document).ready( function () {
             "paging": false
         });
     });
+
+    // Initialise auto-completion for search bar
+    window.autocomplete = new Autocomplete({});
+    window.autocomplete.setup();
 });
diff --git a/aleksis/core/static/js/search.js b/aleksis/core/static/js/search.js
new file mode 100644
index 0000000000000000000000000000000000000000..304f7f639010bba61b84479088c9a2da6a3db0d6
--- /dev/null
+++ b/aleksis/core/static/js/search.js
@@ -0,0 +1,63 @@
+/*
+ * Based on: https://django-haystack.readthedocs.io/en/master/autocomplete.html
+ *
+ * © Copyright 2009-2016, Daniel Lindsley
+ * Licensed under the 3-clause BSD license
+ */
+
+var Autocomplete = function(options) {
+  this.form_selector = options.form_selector || '.autocomplete';
+  this.url = options.url || Urls.searchbarSnippets();
+  this.delay = parseInt(options.delay || 300);
+  this.minimum_length = parseInt(options.minimum_length || 3);
+  this.form_elem = null;
+  this.query_box = null;
+}
+
+Autocomplete.prototype.setup = function() {
+  var self = this;
+
+  this.form_elem = $(this.form_selector);
+  this.query_box = this.form_elem.find('input[name=q]');
+
+  // Watch the input box.
+  this.query_box.on('keyup', function() {
+    var query = self.query_box.val();
+
+    if(query.length < self.minimum_length) {
+      return false;
+    }
+
+    self.fetch(query);
+  });
+
+  // On selecting a result, remove result box
+  this.form_elem.on('click', '#search-results', function(ev) {
+    $('#search-results').remove();
+    return true;
+  });
+
+  // Disable browser's own autocomplete
+  // We do this here so users without JavaScript can keep it enabled
+  this.query_box.attr('autocomplete', 'off');
+}
+
+Autocomplete.prototype.fetch = function(query) {
+  var self = this;
+
+  $.ajax({
+    url: this.url
+  , data: {
+      'q': query
+    }
+  , success: function(data) {
+      self.show_results(data);
+    }
+  })
+}
+
+Autocomplete.prototype.show_results = function(data) {
+  $('#search-results').remove();
+  var results_wrapper = $('<div id="search-results">' + data + '</div>');
+  this.query_box.after(results_wrapper);
+}
diff --git a/aleksis/core/static/style.scss b/aleksis/core/static/style.scss
index d36fd43423b85d8e29a5e7630ee165311aa2f0c8..4f91d3a3dfae93bc8672cefb6c987b183942a809 100644
--- a/aleksis/core/static/style.scss
+++ b/aleksis/core/static/style.scss
@@ -168,7 +168,7 @@ li.active > a > .sidenav-badge {
   box-shadow: none;
 }
 
-.sidenav li.search .search-wrapper i.material-icons {
+.sidenav li.search .search-wrapper > i.material-icons {
   position: absolute;
   top: 21px;
   right: 10px;
@@ -532,3 +532,12 @@ main .alert p:first-child, main .alert div:first-child {
   width: 100%;
 }
 
+div#search-results {
+  position: absolute;
+  width: 100%;
+}
+
+.search-result-icon {
+  position: absolute;
+  right: 10px;
+}
diff --git a/aleksis/core/templates/core/base.html b/aleksis/core/templates/core/base.html
index ef8d9c77f90b549c1d8b0ec732caaa81c4900c09..491cc0b8689e8232d66fd83faeaa68fdbf3dbb17 100644
--- a/aleksis/core/templates/core/base.html
+++ b/aleksis/core/templates/core/base.html
@@ -32,6 +32,8 @@
   {# Include jQuery to provide $(document).ready #}
   {% include_js "jQuery" %}
 
+  <script type="text/javascript" src="{% static 'js/search.js' %}"></script>
+
   {% block extra_head %}{% endblock %}
 </head>
 <body>
@@ -70,10 +72,12 @@
       </a>
     </li>
     <li class="search">
-      <div class="search-wrapper">
-        <input id="search" placeholder="{% trans "Search" %}">
-        <i class="material-icons">search</i>
-      </div>
+      <form method="post" action="#" class="autocomplete">
+        <div class="search-wrapper">
+          <input id="search" name="q" placeholder="{% trans "Search" %}">
+          <i class="material-icons">search</i>
+        </div>
+      </form>
     </li>
     <li class="no-padding">
       {% include "core/sidenav.html" %}
diff --git a/aleksis/core/templates/search/searchbar_snippet.html b/aleksis/core/templates/search/searchbar_snippet.html
index 88c8411bf2fd14f0ab9f120cb3dc0b3788df5f7d..c191317a3596a97d3f87d1f2c617be8c4f75d33a 100644
--- a/aleksis/core/templates/search/searchbar_snippet.html
+++ b/aleksis/core/templates/search/searchbar_snippet.html
@@ -1,7 +1,4 @@
 <a href="{{ result.object.get_absolute_url|default:"#" }}" class="collection-item">
-  <span class="secondary-content">
-    <i class="material-icons">{{ result.object.icon }}</i>
-  </span>
   {{ result.object }}
+  <i class="material-icons secondary-content search-result-icon">{{ result.object.icon_ }}</i>
 </a>
-  
\ No newline at end of file