Q: is there a way to set different scroll margins at the top and bottom of a window?

The variable scroll-margin (defined in the C source code) sets how many lines of text that Emacs displays, at a minimum, at the top and bottom of a window:

Number of lines of margin at the top and bottom of a window. Recenter the window whenever point gets within this many lines of the top or bottom of the window.

I'd like to use scroll-margin for the bottom of the window, but don't want it at the top (e.g., a positive value at the bottom, but 0 at the top). Is there a way to do so?

  • I don't know the answer, but in all likelihood scroll-margin is not the right tool for the job. You may need some function to put on post-command-hook to determine whether to scroll the window. Jan 19, 2015 at 15:29
  • To follow up on my previous comment, finding out how many lines are visible around point seems highly nontrivial, considering wrapped lines, hidden text and the like. I suspect the necessary information is easily available only inside the display code. You could try submitting a feature request to allow (for example) a cons (top . bottom) for scroll-margin. Jan 19, 2015 at 17:25
  • You might be interested in playing with the window-scroll-functions hook (which takes two arguments) and putting a recenter command into a function attached to that hook and then use a setting of (setq scroll-conservatively 101) -- in essence, you define when recentering occurs and turn off the built-in auto-scroll. Something like (when (and (>= (point) (window-end nil t)) (not (pos-visible-in-window-p (point) (get-buffer-window (current-buffer) (selected-frame))))) (recenter))
    – lawlist
    Jan 19, 2015 at 18:41
  • @lawlist: thanks for the suggestion, but the end of the docstring reads "Warning: Do not use this feature to alter the way the window is scrolled. It is not designed for that, and such use probably won't work."
    – Dan
    Jan 19, 2015 at 19:17
  • Interesting question, I am wondering why there is no comments/vote on the answer provided by PythonNut.
    – Name
    Jul 19, 2015 at 7:36

2 Answers 2


The following works for me:

(defun my-define-scroll-margins (&rest _args)
    (let ((computed-margin
            (if (> (cdr (nth 6 (posn-at-point)))
                  (/ (window-body-height) 2)) 5 0)))
        scroll-margin computed-margin
        smooth-scroll-margin computed-margin))))

(add-hook 'post-command-hook #'my-define-scroll-margins)

Note that this is theoretically inefficient, but performance on my lame computer seems unaffected.


Edit: Oh hey heads up. I just realized that this wasn't exactly answer to the original question. I just arrived her via search looking for a way to calculate the scroll-margin based on window height. Hope it's useful to somebody though.

Thanks to @PythonNut, I was able to take their answer to this question and improve it closer to my preferences.

Just change the minimum-window-height and percent-margin variables to your preferences, and stick this in your config.

If you're using Doom Emacs like me, it can go into your config.el file.

(defun my/define-scroll-margins ()
  "Set the scroll margins dynamically based on the current window height."
  (let ((minimum-window-height 14))
    (let ((percent-margin 0.1))
      (setq scroll-margin
            (if (<= (window-body-height) minimum-window-height)
              (floor (* (window-body-height) (* percent-margin 2))))))))
(add-hook 'window-configuration-change-hook #'my/define-scroll-margins)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.