diff --git a/src/App.vue b/src/App.vue
index 343ccfe54930b931fc6bc1111399d9ee6d749a6a..940e4ea9c7ee80e27d188c66d6a644d4be5a1ef1 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -151,6 +151,11 @@
             </div>
           </div>
         </div>
+        <div :class="{ active: loader.isLoading }" class="ui inverted dimmer">
+          <div class="ui text loader">
+            {{ loader.message }}
+          </div>
+        </div>
         <router-view />
         <!-- //* Les views sont injectées ici -->
       </div>
@@ -194,6 +199,7 @@ export default {
       "USER_LEVEL_PROJECTS",
       "configuration",
       "messages",
+      "loader",
     ]),
     ...mapGetters(["project"]),
     APPLICATION_NAME: function () {
@@ -256,6 +262,11 @@ body {
   flex-direction: column;
 }
 
+/* to display loader between header and footer */
+main {
+  position: relative;
+}
+
 footer {
   margin-top: auto;
 }
@@ -269,28 +280,32 @@ footer {
   background: white !important;
 }
 
+.flex {
+  display: flex;
+}
+
+/* keep above loader */
+#menu-dropdown {
+  z-index: 1001;
+}
+
 @media screen and (min-width: 560px) {
   .mobile {
     display: none !important;
   }
-
   .header-menu {
     min-width: 560px;
   }
-
   .menu.container {
     width: auto !important;
     margin-left: 1em !important;
     margin-right: 1em !important;
   }
-
   .push-right-desktop {
     margin-left: auto;
   }
 }
-.flex {
-  display: flex;
-}
+
 @media screen and (max-width: 560px) {
   .desktop {
     display: none !important;
diff --git a/src/store/index.js b/src/store/index.js
index eef57b2b52cbdccab9fc2c740888b4b501b446f8..32d4576741a6c5929f78c99ab0771919b8ad2a92 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -48,12 +48,11 @@ export default new Vuex.Store({
     USER_LEVEL_PROJECTS: null,
     user_permissions: null,
     messages: [],
-    events: null
-    // events: {
-    //   'events': null,
-    //   'features': null,
-    //   'comments': null
-    // }
+    events: null,
+    loader: {
+      isLoading: false,
+      message: "En cours de chargement"
+    },
   },
 
   mutations: {
@@ -108,7 +107,16 @@ export default new Vuex.Store({
     },
     CLEAR_MESSAGES(state) {
       state.messages = [];
-    }
+    },
+    DISPLAY_LOADER(state, message) {
+      state.loader = { isLoading: true, message }
+    },
+    DISCARD_LOADER(state) {
+      state.loader = {
+        isLoading: false,
+        message: "En cours de chargement"
+      };
+    },
   },
 
   getters: {
diff --git a/src/views/feature/Feature_list.vue b/src/views/feature/Feature_list.vue
index 79b7f1342d4563e29850e5e7793f52d0eaa0c0b7..9c148830cfcbae757bf028edd70a1caa1cf04cd0 100644
--- a/src/views/feature/Feature_list.vue
+++ b/src/views/feature/Feature_list.vue
@@ -1,6 +1,5 @@
 <template>
   <div class="fourteen wide column">
-    <div class="ui dimmer" :class="[{ active: featureLoading }]"></div>
     <script
       type="application/javascript"
       :src="
@@ -233,7 +232,6 @@ export default {
       },
 
       geojsonFeatures: [],
-      featureLoading: false,
       filterStatus: null,
       filterType: null,
       baseUrl: this.$store.state.configuration.BASE_URL,
@@ -369,15 +367,18 @@ export default {
         this.loadFeatures(this.$store.state.map.geojsonFeatures);
       } else {
         const url = `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/feature/?output=geojson`;
-        this.featureLoading = true;
+        this.$store.commit(
+          "DISPLAY_LOADER",
+          "Récupération des signalements en cours..."
+        );
         axios
           .get(url)
           .then((response) => {
             this.loadFeatures(response.data.features);
-            this.featureLoading = false;
+            this.$store.commit("DISCARD_LOADER");
           })
           .catch((error) => {
-            this.featureLoading = false;
+            this.$store.commit("DISCARD_LOADER");
             throw error;
           });
       }
@@ -429,6 +430,11 @@ export default {
   mounted() {
     this.initMap();
   },
+
+  destroyed() {
+    //* allow user to change page if ever stuck on loader
+    this.$store.commit("DISCARD_LOADER");
+  },
 };
 </script>
 
diff --git a/src/views/project/Project_members.vue b/src/views/project/Project_members.vue
index a838d755e80c0131efa9de35a3b5b1c63955eea9..dd1fc1c606342a8a6240da3d574f75852a5dca56 100644
--- a/src/views/project/Project_members.vue
+++ b/src/views/project/Project_members.vue
@@ -132,7 +132,12 @@ export default {
     },
 
     async populateMembers() {
+      this.$store.commit(
+        "DISPLAY_LOADER",
+        "Récupération des membres en cours..."
+      );
       await this.fetchMembers().then((members) => {
+        this.$store.commit("DISCARD_LOADER");
         this.projectMembers = members.map((el) => {
           return {
             userLevel: { name: el.level.display, value: el.level.codename },
@@ -149,5 +154,10 @@ export default {
     }
     this.populateMembers();
   },
+
+  destroyed() {
+    //* allow user to change page if ever stuck on loader
+    this.$store.commit("DISCARD_LOADER");
+  },
 };
 </script>
\ No newline at end of file