diff --git a/keymap/vim.js b/keymap/vim.js
index 438e20547cdcdd44637e26d32735b87ef34ef82d..2efbf1b4ff3e020264522246ec6833ed945b73a1 100644
--- a/keymap/vim.js
+++ b/keymap/vim.js
@@ -604,6 +604,8 @@
           // executed in between.
           lastMotion: null,
           marks: {},
+          // fake cursor for visual mode
+          fakeCursor: null,
           insertMode: false,
           // Repeat count for changes made in insert mode, triggered by key
           // sequences like 3,i. Only exists when insertMode is true.
@@ -2467,6 +2469,9 @@
         cm.setCursor(clipCursorToContent(cm, selectionEnd));
       }
       CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+      if (vim.fakeCursor) {
+        vim.fakeCursor.clear();
+      }
     }
 
     // Remove any trailing newlines from the selection. For
@@ -4332,6 +4337,20 @@
       } else if (cm.doc.history.lastSelOrigin == '*mouse') {
         // Reset lastHPos if mouse click was done in normal mode.
         vim.lastHPos = cm.doc.getCursor().ch;
+      } else if (vim.visualMode) {
+        var from, head;
+        from = head = cm.getCursor('head');
+        var anchor = cm.getCursor('anchor');
+        var to = Pos(head.line, from.ch + (cursorIsBefore(anchor, head) ? -1 : 1));
+        if (cursorIsBefore(to, from)) {
+          var temp = from;
+          from = to;
+          to = temp;
+        }
+        if (vim.fakeCursor) {
+          vim.fakeCursor.clear();
+        }
+        vim.fakeCursor = cm.markText(from, to, {className: 'fake-fat-cursor'});
       }
     }
 
diff --git a/lib/codemirror.css b/lib/codemirror.css
index 098a317a229098e2c0dd9b6eaf98f723bfc876c8..5141666b46005d15b9d13becf89d68c0765b56f9 100644
--- a/lib/codemirror.css
+++ b/lib/codemirror.css
@@ -63,7 +63,45 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
   border-left: 1px solid #ccc;
   position: absolute;
 }
+.fake-fat-cursor {
+  width: auto;
+  border: 0;
+  background: #7e7;
+
+  -webkit-animation: blink 1s infinite;
+  -moz-animation: blink 1s infinite;
+  animation: blink 1s infinite;
+}
 
+@-moz-keyframes blink {  
+  0% { 
+    visibility: visible;
+   }
+  100% {
+   visibility: hidden;
+   background: white;
+   }
+}
+
+@-webkit-keyframes blink {  
+  0% { 
+    visibility: visible;
+   }
+  100% {
+   visibility: hidden;
+   background: white;
+   }
+}
+
+@keyframes blink {  
+  0% { 
+    visibility: visible;
+   }
+  100% {
+   visibility: hidden;
+   background: white;
+   }
+}
 /* DEFAULT THEME */
 
 .cm-s-default .cm-keyword {color: #708;}