--- a/src/ui_utils.c
+++ b/src/ui_utils.c
@@ -55,6 +55,7 @@
 #include "main.h"
 #include "stash.h"
 #include "keyfile.h"
+#include "gtkcompat.h"
 
 
 GeanyInterfacePrefs	interface_prefs;
@@ -1312,7 +1313,7 @@
 	GtkWidget *vbox = gtk_vbox_new(FALSE, 12);	/* need child vbox to set a separate border. */
 
 	gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
-	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), vbox);
+	gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), vbox, TRUE, TRUE, 0);
 	return vbox;
 }
 
@@ -1465,7 +1466,7 @@
  * @param combo_entry .
  * @param text Text to add, or @c NULL for current entry text.
  * @param history_len Max number of items, or @c 0 for default. */
-void ui_combo_box_add_to_history(GtkComboBoxEntry *combo_entry,
+void ui_combo_box_add_to_history(GtkComboBoxText *combo_entry,
 		const gchar *text, gint history_len)
 {
 	GtkComboBox *combo = GTK_COMBO_BOX(combo_entry);
@@ -1484,7 +1485,7 @@
 	{
 		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
 	}
-	gtk_combo_box_prepend_text(combo, text);
+	gtk_combo_box_text_prepend_text(combo_entry, text);
 
 	/* limit history */
 	path = gtk_tree_path_new_from_indices(history_len, -1);
@@ -1496,18 +1497,18 @@
 }
 
 
-/* Same as gtk_combo_box_prepend_text(), except that text is only prepended if it not already
+/* Same as gtk_combo_box_text_prepend_text(), except that text is only prepended if it not already
  * exists in the combo's model. */
-void ui_combo_box_prepend_text_once(GtkComboBox *combo, const gchar *text)
+void ui_combo_box_prepend_text_once(GtkComboBoxText *combo, const gchar *text)
 {
 	GtkTreeModel *model;
 	GtkTreeIter iter;
 
-	model = gtk_combo_box_get_model(combo);
+	model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo));
 	if (tree_model_find_text(model, &iter, 0, text))
 		return;	/* don't prepend duplicate */
 
-	gtk_combo_box_prepend_text(combo, text);
+	gtk_combo_box_text_prepend_text(combo, text);
 }
 
 
@@ -1911,7 +1912,7 @@
 	g_object_unref(left);
 	g_object_unref(right);
 
-	gtk_paned_set_position(GTK_PANED(pane), pane->allocation.width
+	gtk_paned_set_position(GTK_PANED(pane), gtk_widget_get_allocated_width(pane)
 		- gtk_paned_get_position(GTK_PANED(pane)));
 }
 
@@ -2160,10 +2161,30 @@
 
 static void init_custom_style(void)
 {
+#if GTK_CHECK_VERSION(3, 0, 0)
+	gchar *css_file = g_build_filename(app->datadir, "geany.css", NULL);
+	GtkCssProvider *css = gtk_css_provider_new();
+	GError *error = NULL;
+
+	if (! gtk_css_provider_load_from_path(css, css_file, &error))
+	{
+		g_warning("Failed to load custom CSS: %s", error->message);
+		g_error_free(error);
+	}
+	else
+	{
+		gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
+			GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+	}
+
+	g_object_unref(css);
+	g_free(css_file);
+#else
 	gchar *gtkrc_file = g_build_filename(app->datadir, "geany.gtkrc", NULL);
 
 	gtk_rc_parse(gtkrc_file);
 	g_free(gtkrc_file);
+#endif
 }
 
 
@@ -2263,7 +2284,7 @@
 {
 	GeanyAutoSeparator *autosep = user_data;
 
-	if (GTK_WIDGET_VISIBLE(widget))
+	if (gtk_widget_get_visible(widget))
 		autosep->show_count++;
 	else
 		autosep->show_count--;
@@ -2277,7 +2298,7 @@
 
 	autosep->item_count--;
 	autosep->item_count = MAX(autosep->item_count, 0);
-	/* GTK_WIDGET_VISIBLE won't work now the widget is being destroyed,
+	/* gtk_widget_get_visible() won't work now the widget is being destroyed,
 	 * so assume widget was visible */
 	autosep->show_count--;
 	autosep->show_count = MAX(autosep->item_count, 0);
@@ -2296,7 +2317,7 @@
 		g_signal_connect(autosep->widget, "destroy",
 			G_CALLBACK(gtk_widget_destroyed), &autosep->widget);
 
-	if (GTK_WIDGET_VISIBLE(item))
+	if (gtk_widget_get_visible(item))
 		autosep->show_count++;
 
 	autosep->item_count++;