diff --git a/assets/voxygen/i18n/en/gameinput.ron b/assets/voxygen/i18n/en/gameinput.ron
index 2b749924e7..bdec336735 100644
--- a/assets/voxygen/i18n/en/gameinput.ron
+++ b/assets/voxygen/i18n/en/gameinput.ron
@@ -62,6 +62,8 @@
         "gameinput.sneak": "Sneak",
         "gameinput.swimdown": "Swim downwards",
         "gameinput.swimup": "Swim upwards",
+        "gameinput.mapzoomin": "Increase map zoom",
+        "gameinput.mapzoomout": "Decrease map zoom",
     },
 
 
diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs
index 2ff05ead41..20fa060b02 100644
--- a/voxygen/src/hud/minimap.rs
+++ b/voxygen/src/hud/minimap.rs
@@ -81,8 +81,6 @@ impl<'a> MiniMap<'a> {
 
 pub struct State {
     ids: Ids,
-
-    zoom: f64,
 }
 
 pub enum Event {
@@ -90,22 +88,13 @@ pub enum Event {
 }
 
 impl<'a> Widget for MiniMap<'a> {
-    type Event = Option<Event>;
+    type Event = Vec<Event>;
     type State = State;
     type Style = ();
 
     fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
         State {
             ids: Ids::new(id_gen),
-
-            zoom: {
-                let min_world_dim = self.world_map.1.reduce_partial_min() as f64;
-                min_world_dim.min(
-                    min_world_dim
-                        * (TerrainChunkSize::RECT_SIZE.reduce_partial_max() as f64 / 32.0)
-                        * (16.0 / 1024.0),
-                )
-            },
         }
     }
 
@@ -113,8 +102,10 @@ impl<'a> Widget for MiniMap<'a> {
     fn style(&self) -> Self::Style { () }
 
     fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
+        let mut events = Vec::new();
+
         let widget::UpdateArgs { state, ui, .. } = args;
-        let zoom = state.zoom;
+        let mut zoom = self.global_state.settings.interface.minimap_zoom;
         const SCALE: f64 = 1.5; // TODO Make this a setting
         let show_minimap = self.global_state.settings.interface.minimap_show;
         let is_facing_north = self.global_state.settings.interface.minimap_face_north;
@@ -185,8 +176,7 @@ impl<'a> Widget for MiniMap<'a> {
                 && can_zoom_out
             {
                 // Set the image dimensions here, rather than recomputing each time.
-                let zoom = min_zoom.max(zoom / ZOOM_FACTOR);
-                state.update(|s| s.zoom = zoom);
+                zoom = min_zoom.max(zoom / ZOOM_FACTOR);
                 // set_image_dims(zoom);
             }
             if Button::image(self.imgs.mmap_plus)
@@ -200,8 +190,7 @@ impl<'a> Widget for MiniMap<'a> {
                 .was_clicked()
                 && can_zoom_in
             {
-                let zoom = max_zoom.min(zoom * ZOOM_FACTOR);
-                state.update(|s| s.zoom = zoom);
+                zoom = min_zoom.max(zoom * ZOOM_FACTOR);
                 // set_image_dims(zoom);
             }
 
@@ -227,11 +216,10 @@ impl<'a> Widget for MiniMap<'a> {
             .set(state.ids.mmap_north_button, ui)
             .was_clicked()
             {
-                return Some(Event::SettingsChange(MinimapFaceNorth(!is_facing_north)));
+                events.push(Event::SettingsChange(MinimapFaceNorth(!is_facing_north)));
             }
 
-            // Reload zoom in case it changed.
-            let zoom = state.zoom;
+            events.push(Event::SettingsChange(MinimapZoom(zoom)));
 
             // Coordinates
             let player_pos = self
@@ -502,7 +490,7 @@ impl<'a> Widget for MiniMap<'a> {
         .set(state.ids.mmap_button, ui)
         .was_clicked()
         {
-            return Some(Event::SettingsChange(MinimapShow(!show_minimap)));
+            events.push(Event::SettingsChange(MinimapShow(!show_minimap)));
         }
 
         // TODO: Subregion name display
@@ -534,6 +522,6 @@ impl<'a> Widget for MiniMap<'a> {
                 .set(state.ids.mmap_location, ui),
         }
 
-        None
+        events
     }
 }
diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs
index 009dca6909..4f2524cf74 100644
--- a/voxygen/src/hud/mod.rs
+++ b/voxygen/src/hud/mod.rs
@@ -2182,7 +2182,7 @@ impl Hud {
         .set(self.ids.popup, ui_widgets);
 
         // MiniMap
-        match MiniMap::new(
+        for event in MiniMap::new(
             client,
             &self.imgs,
             &self.rot_imgs,
@@ -2193,10 +2193,11 @@ impl Hud {
         )
         .set(self.ids.minimap, ui_widgets)
         {
-            Some(minimap::Event::SettingsChange(interface_change)) => {
-                events.push(Event::SettingsChange(interface_change.into()));
-            },
-            None => {},
+            match event {
+                minimap::Event::SettingsChange(interface_change) => {
+                    events.push(Event::SettingsChange(interface_change.into()));
+                },
+            }
         }
 
         if let Some(prompt_dialog_settings) = &self.show.prompt_dialog {
@@ -3094,6 +3095,28 @@ impl Hud {
             }
         }
 
+        fn handle_map_zoom(
+            factor: f64,
+            world_size: Vec2<u32>,
+            show: &Show,
+            global_state: &mut GlobalState,
+        ) -> bool {
+            let max_zoom = world_size.reduce_partial_max() as f64;
+
+            if show.map {
+                let new_zoom_lvl = (global_state.settings.interface.map_zoom * factor)
+                    .clamped(1.25, max_zoom / 64.0);
+
+                global_state.settings.interface.map_zoom = new_zoom_lvl;
+            } else if global_state.settings.interface.minimap_show {
+                let new_zoom_lvl = global_state.settings.interface.minimap_zoom * factor;
+
+                global_state.settings.interface.minimap_zoom = new_zoom_lvl;
+            }
+
+            show.map && global_state.settings.interface.minimap_show
+        }
+
         let cursor_grabbed = global_state.window.is_cursor_grabbed();
         let handled = match event {
             WinEvent::Ui(event) => {
@@ -3220,6 +3243,12 @@ impl Hud {
                         self.show.ingame = !self.show.ingame;
                         true
                     },
+                    GameInput::MapZoomIn if state => {
+                        handle_map_zoom(2.0, self.world_map.1, &self.show, global_state)
+                    },
+                    GameInput::MapZoomOut if state => {
+                        handle_map_zoom(0.5, self.world_map.1, &self.show, global_state)
+                    },
                     // Skillbar
                     input => {
                         if let Some(slot) = try_hotbar_slot_from_input(input) {
diff --git a/voxygen/src/session/settings_change.rs b/voxygen/src/session/settings_change.rs
index d72fc26c35..c560ca6007 100644
--- a/voxygen/src/session/settings_change.rs
+++ b/voxygen/src/session/settings_change.rs
@@ -99,6 +99,7 @@ pub enum Interface {
     //Minimap
     MinimapShow(bool),
     MinimapFaceNorth(bool),
+    MinimapZoom(f64),
     //Map settings
     MapZoom(f64),
     MapDrag(Vec2<f64>),
@@ -413,6 +414,9 @@ impl SettingsChange {
                     Interface::MinimapFaceNorth(state) => {
                         settings.interface.minimap_face_north = state;
                     },
+                    Interface::MinimapZoom(minimap_zoom) => {
+                        settings.interface.minimap_zoom = minimap_zoom;
+                    },
                     Interface::MapZoom(map_zoom) => {
                         settings.interface.map_zoom = map_zoom;
                     },
diff --git a/voxygen/src/settings/control.rs b/voxygen/src/settings/control.rs
index df9472a059..b70e30ebe2 100644
--- a/voxygen/src/settings/control.rs
+++ b/voxygen/src/settings/control.rs
@@ -166,6 +166,8 @@ impl ControlSettings {
             GameInput::Select => KeyMouse::Key(VirtualKeyCode::Y),
             GameInput::AcceptGroupInvite => KeyMouse::Key(VirtualKeyCode::U),
             GameInput::DeclineGroupInvite => KeyMouse::Key(VirtualKeyCode::I),
+            GameInput::MapZoomIn => KeyMouse::Key(VirtualKeyCode::Plus),
+            GameInput::MapZoomOut => KeyMouse::Key(VirtualKeyCode::Minus),
         }
     }
 }
diff --git a/voxygen/src/settings/interface.rs b/voxygen/src/settings/interface.rs
index 41abc6c148..63cf55ee11 100644
--- a/voxygen/src/settings/interface.rs
+++ b/voxygen/src/settings/interface.rs
@@ -37,6 +37,7 @@ pub struct InterfaceSettings {
     pub map_show_trees: bool,
     pub minimap_show: bool,
     pub minimap_face_north: bool,
+    pub minimap_zoom: f64,
 }
 
 impl Default for InterfaceSettings {
@@ -70,6 +71,7 @@ impl Default for InterfaceSettings {
             map_show_trees: true,
             minimap_show: true,
             minimap_face_north: false,
+            minimap_zoom: 10.0,
         }
     }
 }
diff --git a/voxygen/src/window.rs b/voxygen/src/window.rs
index 2bacb2758f..e6c1581402 100644
--- a/voxygen/src/window.rs
+++ b/voxygen/src/window.rs
@@ -76,6 +76,8 @@ pub enum GameInput {
     Select,
     AcceptGroupInvite,
     DeclineGroupInvite,
+    MapZoomIn,
+    MapZoomOut,
 }
 
 impl GameInput {
@@ -138,6 +140,8 @@ impl GameInput {
             GameInput::Select => "gameinput.select",
             GameInput::AcceptGroupInvite => "gameinput.acceptgroupinvite",
             GameInput::DeclineGroupInvite => "gameinput.declinegroupinvite",
+            GameInput::MapZoomIn => "gameinput.mapzoomin",
+            GameInput::MapZoomOut => "gameinput.mapzoomout",
         }
     }
 
@@ -200,6 +204,8 @@ impl GameInput {
             GameInput::Select,
             GameInput::AcceptGroupInvite,
             GameInput::DeclineGroupInvite,
+            GameInput::MapZoomIn,
+            GameInput::MapZoomOut,
         ]
         .iter()
         .copied()