diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py
index c46fa8fe627fac341b22801c832f606e6449434f..ad90929ef8f4332daf50ef3485b47383f79a9dea 100644
--- a/aleksis/core/preferences.py
+++ b/aleksis/core/preferences.py
@@ -3,6 +3,7 @@ from django.forms import EmailField, ImageField, URLField
 from django.forms.widgets import SelectMultiple
 from django.utils.translation import gettext_lazy as _
 
+from colorfield.widgets import ColorWidget
 from dynamic_preferences.preferences import Section
 from dynamic_preferences.types import (
     BooleanPreference,
@@ -53,6 +54,7 @@ class ColourPrimary(StringPreference):
     default = "#0d5eaf"
     required = False
     verbose_name = _("Primary colour")
+    widget = ColorWidget
 
 
 @site_preferences_registry.register
@@ -62,6 +64,7 @@ class ColourSecondary(StringPreference):
     default = "#0d5eaf"
     required = False
     verbose_name = _("Secondary colour")
+    widget = ColorWidget
 
 
 @site_preferences_registry.register
diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js
index 45fee5c5bde0eb54655b2fe556c05f9aee573c4f..afdc39508ff3f8dee89001fc86d435ca50eb7c8e 100644
--- a/aleksis/core/static/js/main.js
+++ b/aleksis/core/static/js/main.js
@@ -91,6 +91,11 @@ $(document).ready(function () {
     // Intialize Tabs [Materialize]
     $('.tabs').tabs();
 
+    // Sync color picker
+    $(".jscolor").change(function () {
+        $("#" + $(this).data("preview")).css("color", $(this).val());
+    });
+
     $('table.datatable').each(function (index) {
         $(this).DataTable({
             "paging": false
diff --git a/aleksis/core/static/style.scss b/aleksis/core/static/style.scss
index 032c28953a9de8c093f037191223c5ddc724faea..06db64f9613d3c4d6b840b7e2fcf5c68686349f7 100644
--- a/aleksis/core/static/style.scss
+++ b/aleksis/core/static/style.scss
@@ -686,3 +686,8 @@ main .alert p:first-child, main .alert div:first-child {
 .draggable {
   cursor: grab;
 }
+
+.jscolor {
+  background-color: inherit !important;
+  color: inherit !important;
+}
diff --git a/aleksis/core/templates/dynamic_preferences/form.html b/aleksis/core/templates/dynamic_preferences/form.html
index da3d608285c43673bd27932d0d19cef303b1cef7..692d25e90b3dd5cb6554fe23010f5cbc542c3c94 100644
--- a/aleksis/core/templates/dynamic_preferences/form.html
+++ b/aleksis/core/templates/dynamic_preferences/form.html
@@ -25,4 +25,6 @@
       {% include "core/partials/save_button.html" with caption=_("Save preferences") %}
     </form>
   </div>
+
+  {{ form.media.js }}
 {% endblock %}
diff --git a/aleksis/core/templates/material/fields/colorfield_colorwidget.html b/aleksis/core/templates/material/fields/colorfield_colorwidget.html
new file mode 100644
index 0000000000000000000000000000000000000000..ab8bc7f955126d365be64085b7be740ef70a398f
--- /dev/null
+++ b/aleksis/core/templates/material/fields/colorfield_colorwidget.html
@@ -0,0 +1,32 @@
+{% load material_form material_form_internal %}
+{% part bound_field.field %}
+  <div class="row">
+    <div class="input-field col s12{% if widget.attrs.required %} required{% endif %}">
+    <i class="material-icons prefix" id="{{ bound_field.html_name }}_preview" style="color: {% firstof bound_field.value field.widget.attrs.default '' %};">color_lens</i>
+      {% part field prefix %}{% endpart %}{% part field control %}
+        <input
+          type="text"
+          id="{{ bound_field.html_name }}"
+          class="form-control colorfield_field jscolor {% if bound_field.errors %}invalid{% endif %}"
+          name="{{ bound_field.html_name }}"
+          value="{% firstof bound_field.value field.widget.attrs.default '' %}"
+          placeholder="{% firstof bound_field.value field.widget.attrs.default '' %}"
+          data-jscolor="{hash:true,width:225,height:150,format:'{{ field.widget.attrs.format }}',required:{% if field.widget.attrs.required %}true{% else %}false{% endif %},paletteCols:4,paletteHeight:28,palette:'{{ field.widget.attrs.palette|safe }}'}"
+          data-preview="{{ bound_field.html_name }}_preview"
+          {% if field.widget.attrs.required %}required{% endif %}/>
+      {% endpart %}
+      {% part field label %}
+        <label{% attrs bound_field 'label' %}
+          for="{{ bound_field.id_for_label }}"
+          {% if bound_field.value != None and bound_field.value != '' %}class="active"{% endif %}
+        {% endattrs %}>{{ bound_field.label }}</label>
+      {% endpart %}
+      {% part field help_text %}{% if field.help_text %}
+        <div class="help-block">{{ bound_field.help_text|safe }}</div>
+      {% endif %}
+      {% endpart %}{% part field errors %}
+        {% if bound_field.errors %}{% include  'material/field_errors.html' %}{% endif %}
+      {% endpart %}{{ hidden_initial }}
+    </div>
+  </div>
+{% endpart %}