diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index f1c5f8b5..190ae3b9 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -450,10 +450,11 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
         return;
     }
 
-    let scrolloff = PADDING; // min(user pref, half win width/height)
+    let scrolloff = PADDING.min(view.area.height as usize / 2); // TODO: user pref
 
     // cursor visual offset
-    let cursor_off = cursor.row - view.first_line;
+    // TODO: only if dragging via mouse?
+    // let cursor_off = cursor.row - view.first_line;
 
     view.first_line = match direction {
         Forward => view.first_line + offset,
@@ -461,14 +462,19 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
     }
     .min(doc_last_line);
 
+    // recalculate last line
+    let last_line = view.last_line(doc);
+
     // clamp into viewport
-    let line = (view.first_line + cursor_off)
-        .max(view.first_line + scrolloff)
-        .min(last_line.saturating_sub(scrolloff));
+    let line = cursor.row.clamp(
+        view.first_line + scrolloff,
+        last_line.saturating_sub(scrolloff),
+    );
 
     let text = doc.text().slice(..);
     let pos = pos_at_coords(text, Position::new(line, cursor.col)); // this func will properly truncate to line end
 
+    // TODO: only manipulate main selection
     doc.set_selection(view.id, Selection::point(pos));
 }
 
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index 93bb005e..1bf7c370 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -81,26 +81,28 @@ impl View {
         let pos = coords_at_pos(doc.text().slice(..), cursor);
         let line = pos.row;
         let col = pos.col;
-        let last_line = self.first_line + (self.area.height as usize).saturating_sub(2);
+        let last_line = self.last_line(doc);
+
+        let scrolloff = PADDING.min(self.area.height as usize / 2); // TODO: user pref
 
         // TODO: not ideal
         const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
         let last_col = self.first_col + (self.area.width as usize - OFFSET);
 
-        if line > last_line.saturating_sub(PADDING) {
+        if line > last_line.saturating_sub(scrolloff) {
             // scroll down
-            self.first_line += line - (last_line.saturating_sub(PADDING));
-        } else if line < self.first_line + PADDING {
+            self.first_line += line - (last_line.saturating_sub(scrolloff));
+        } else if line < self.first_line + scrolloff {
             // scroll up
-            self.first_line = line.saturating_sub(PADDING);
+            self.first_line = line.saturating_sub(scrolloff);
         }
 
-        if col > last_col.saturating_sub(PADDING) {
+        if col > last_col.saturating_sub(scrolloff) {
             // scroll right
-            self.first_col += col - (last_col.saturating_sub(PADDING));
-        } else if col < self.first_col + PADDING {
+            self.first_col += col - (last_col.saturating_sub(scrolloff));
+        } else if col < self.first_col + scrolloff {
             // scroll left
-            self.first_col = col.saturating_sub(PADDING);
+            self.first_col = col.saturating_sub(scrolloff);
         }
     }