diff --git a/web/chat/chat-constants.js b/web/chat/chat-constants.js
--- a/web/chat/chat-constants.js
+++ b/web/chat/chat-constants.js
@@ -1,5 +1,10 @@
 // @flow
 
+import { messageKey } from 'lib/shared/message-utils.js';
+import type { MessageInfo } from 'lib/types/message-types.js';
+
+import type { ComposedMessageID } from './composed-message.react.js';
+
 export const tooltipStyle = {
   paddingLeft: 5,
   paddingRight: 5,
@@ -25,3 +30,26 @@
   tooltipTopOffset: 4,
   rowHeight: 40,
 };
+
+export const getComposedMessageID = (
+  messageInfo: MessageInfo,
+): ComposedMessageID => {
+  return `ComposedMessageBox-${messageKey(messageInfo)}`;
+};
+
+export const defaultMaxTextAreaHeight = 150;
+
+// The editBoxBottomRowHeight is the height of the bottom row in the edit box
+// which is the height of the buttons in the bottom row.
+export const editBoxBottomRowHeight = 22;
+
+// The editBoxHeight is a height of the all elements of the edit box
+// except for the textarea.
+// It consists of:
+// - 2 * 10px:  .editMessage padding (edit-text-message.css)
+// - 10px:      .bottomRow padding between the bottom row buttons
+//                and the textarea (edit-text-message.css)
+// - 2 * 8px:   .inputBarTextInput padding (chat-input-bar.css)
+// - 22px:      height of the bottom row in the edit box (explained above)
+// - textarea height which is NOT included here
+export const editBoxHeight: number = 3 * 10 + 2 * 8 + editBoxBottomRowHeight;
diff --git a/web/chat/chat-input-bar.css b/web/chat/chat-input-bar.css
--- a/web/chat/chat-input-bar.css
+++ b/web/chat/chat-input-bar.css
@@ -13,6 +13,7 @@
   display: flex;
   background: var(--text-input-bg);
   border-radius: 8px;
+  /* Related to editBoxHeight in the `edit-text-message` component */
   padding: 8px;
   align-items: center;
   flex-grow: 1;
diff --git a/web/chat/chat-input-text-area.react.js b/web/chat/chat-input-text-area.react.js
--- a/web/chat/chat-input-text-area.react.js
+++ b/web/chat/chat-input-text-area.react.js
@@ -3,6 +3,7 @@
 import invariant from 'invariant';
 import * as React from 'react';
 
+import { defaultMaxTextAreaHeight } from './chat-constants.js';
 import css from './chat-input-bar.css';
 
 type Props = {
@@ -12,6 +13,7 @@
   +currentText: string,
   +setCurrentText: (text: string) => void,
   +onChangePosition: () => void,
+  +maxHeight?: number,
 };
 
 const ChatInputTextArea: React.ComponentType<Props> = React.memo<Props>(
@@ -23,6 +25,7 @@
       send,
       setCurrentText,
       onChangePosition,
+      maxHeight = defaultMaxTextAreaHeight,
     } = props;
     const textareaRef = React.useRef(null);
 
@@ -53,11 +56,11 @@
       const textarea = textareaRef.current;
       if (textarea) {
         textarea.style.height = 'auto';
-        const newHeight = Math.min(textarea.scrollHeight, 150);
+        const newHeight = Math.min(textarea.scrollHeight, maxHeight);
         textarea.style.height = `${newHeight}px`;
       }
       onChangePosition();
-    }, [onChangePosition]);
+    }, [maxHeight, onChangePosition]);
 
     React.useEffect(() => {
       focusAndUpdateText();
diff --git a/web/chat/chat-message-list.css b/web/chat/chat-message-list.css
--- a/web/chat/chat-message-list.css
+++ b/web/chat/chat-message-list.css
@@ -18,6 +18,9 @@
 div.mirroredMessageContainer > div {
   transform: scaleY(-1);
 }
+div.disableAnchor {
+  overflow-anchor: none;
+}
 
 div.message {
   display: flex;
diff --git a/web/chat/chat-message-list.react.js b/web/chat/chat-message-list.react.js
--- a/web/chat/chat-message-list.react.js
+++ b/web/chat/chat-message-list.react.js
@@ -3,6 +3,7 @@
 import classNames from 'classnames';
 import { detect as detectBrowser } from 'detect-browser';
 import invariant from 'invariant';
+import _debounce from 'lodash/debounce.js';
 import * as React from 'react';
 
 import {
@@ -28,7 +29,9 @@
   useDispatchActionPromise,
 } from 'lib/utils/action-utils.js';
 
+import { editBoxHeight, defaultMaxTextAreaHeight } from './chat-constants.js';
 import css from './chat-message-list.css';
+import type { ScrollToMessageCallback } from './edit-message-provider.js';
 import { useEditModalContext } from './edit-message-provider.js';
 import { MessageListContext } from './message-list-types.js';
 import Message from './message.react.js';
@@ -43,6 +46,10 @@
 const supportsReverseFlex =
   !browser || browser.name !== 'firefox' || parseInt(browser.version) >= 81;
 
+// Margin between the top of the maximum height edit box
+// and the top of the container
+const editBoxTopMargin = 10;
+
 type BaseProps = {
   +threadInfo: ThreadInfo,
 };
@@ -64,18 +71,37 @@
   +clearTooltip: () => mixed,
   +oldestMessageServerID: ?string,
   +isEditState: boolean,
+  +addScrollToMessageListener: ScrollToMessageCallback => mixed,
+  +removeScrollToMessageListener: ScrollToMessageCallback => mixed,
 };
 type Snapshot = {
   +scrollTop: number,
   +scrollHeight: number,
 };
-class ChatMessageList extends React.PureComponent<Props> {
+
+type State = {
+  +scrollingEndCallback: ?() => mixed,
+};
+
+class ChatMessageList extends React.PureComponent<Props, State> {
   container: ?HTMLDivElement;
   messageContainer: ?HTMLDivElement;
   loadingFromScroll = false;
 
+  constructor(props: Props) {
+    super(props);
+    this.state = {
+      scrollingEndCallback: null,
+    };
+  }
+
   componentDidMount() {
     this.scrollToBottom();
+    this.props.addScrollToMessageListener(this.scrollToMessage);
+  }
+
+  componentWillUnmount() {
+    this.props.removeScrollToMessageListener(this.scrollToMessage);
   }
 
   getSnapshotBeforeUpdate(prevProps: Props) {
@@ -178,8 +204,106 @@
     );
   };
 
+  scrollingEndCallbackWrapper = (
+    composedMessageID: string,
+    callback: (maxHeight: number) => mixed,
+  ): (() => mixed) => {
+    return () => {
+      const maxHeight = this.getMaxEditTextAreaHeight(composedMessageID);
+      callback(maxHeight);
+    };
+  };
+
+  scrollToMessage = (
+    composedMessageID: string,
+    callback: (maxHeight: number) => mixed,
+  ) => {
+    const element = document.getElementById(composedMessageID);
+    if (!element) {
+      return;
+    }
+    const scrollingEndCallback = this.scrollingEndCallbackWrapper(
+      composedMessageID,
+      callback,
+    );
+    if (!this.willMessageEditWindowOverflow(composedMessageID)) {
+      scrollingEndCallback();
+      return;
+    }
+    this.setState(
+      {
+        scrollingEndCallback,
+      },
+      () => {
+        element.scrollIntoView({ behavior: 'smooth', block: 'center' });
+        // It covers the case when browser decide not to scroll to the message
+        // because it's already in the view.
+        // In this case, the 'scroll' event won't be triggered,
+        // so we need to call the callback manually.
+        this.debounceEditModeAfterScrollToMessage();
+      },
+    );
+  };
+
+  getMaxEditTextAreaHeight = (composedMessageID: string): number => {
+    const { messageContainer } = this;
+    if (!messageContainer) {
+      return defaultMaxTextAreaHeight;
+    }
+    const messageElement = document.getElementById(composedMessageID);
+    if (!messageElement) {
+      console.log(`couldn't find the message element`);
+      return defaultMaxTextAreaHeight;
+    }
+
+    const msgPos = messageElement.getBoundingClientRect();
+    const containerPos = messageContainer.getBoundingClientRect();
+
+    const messageBottom = msgPos.bottom;
+    const containerTop = containerPos.top;
+
+    const maxHeight =
+      messageBottom - containerTop - editBoxHeight - editBoxTopMargin;
+
+    return maxHeight;
+  };
+
+  willMessageEditWindowOverflow(composedMessageID: string) {
+    const { messageContainer } = this;
+    if (!messageContainer) {
+      return false;
+    }
+    const messageElement = document.getElementById(composedMessageID);
+    if (!messageElement) {
+      console.log(`couldn't find the message element`);
+      return false;
+    }
+
+    const msgPos = messageElement.getBoundingClientRect();
+    const containerPos = messageContainer.getBoundingClientRect();
+    const containerTop = containerPos.top;
+    const containerBottom = containerPos.bottom;
+
+    const availableTextAreaHeight =
+      (containerBottom - containerTop) / 2 - editBoxHeight;
+    const messageHeight = msgPos.height;
+    const expectedMinimumHeight = Math.min(
+      defaultMaxTextAreaHeight,
+      availableTextAreaHeight,
+    );
+    const offset = Math.max(
+      0,
+      expectedMinimumHeight + editBoxHeight + editBoxTopMargin - messageHeight,
+    );
+
+    const messageTop = msgPos.top - offset;
+    const messageBottom = msgPos.bottom;
+
+    return messageBottom > containerBottom || messageTop < containerTop;
+  }
+
   render() {
-    const { messageListData, threadInfo, inputState } = this.props;
+    const { messageListData, threadInfo, inputState, isEditState } = this.props;
     if (!messageListData) {
       return <div className={css.container} />;
     }
@@ -192,6 +316,8 @@
     }
 
     const messageContainerStyle = classNames({
+      [css.disableAnchor]:
+        this.state.scrollingEndCallback !== null || isEditState,
       [css.messageContainer]: true,
       [css.mirroredMessageContainer]: !supportsReverseFlex,
     });
@@ -221,8 +347,16 @@
     }
     this.props.clearTooltip();
     this.possiblyLoadMoreMessages();
+    this.debounceEditModeAfterScrollToMessage();
   };
 
+  debounceEditModeAfterScrollToMessage = _debounce(() => {
+    if (this.state.scrollingEndCallback) {
+      this.state.scrollingEndCallback();
+    }
+    this.setState({ scrollingEndCallback: null });
+  }, 100);
+
   async possiblyLoadMoreMessages() {
     if (!this.messageContainer) {
       return;
@@ -313,7 +447,11 @@
 
     const oldestMessageServerID = useOldestMessageServerID(threadInfo.id);
 
-    const { editState } = useEditModalContext();
+    const {
+      editState,
+      addScrollToMessageListener,
+      removeScrollToMessageListener,
+    } = useEditModalContext();
     const isEditState = editState !== null;
 
     return (
@@ -330,6 +468,8 @@
           clearTooltip={clearTooltip}
           oldestMessageServerID={oldestMessageServerID}
           isEditState={isEditState}
+          addScrollToMessageListener={addScrollToMessageListener}
+          removeScrollToMessageListener={removeScrollToMessageListener}
         />
       </MessageListContext.Provider>
     );
diff --git a/web/chat/composed-message.react.js b/web/chat/composed-message.react.js
--- a/web/chat/composed-message.react.js
+++ b/web/chat/composed-message.react.js
@@ -14,6 +14,7 @@
 import { assertComposableMessageType } from 'lib/types/message-types.js';
 import { type ThreadInfo } from 'lib/types/thread-types.js';
 
+import { getComposedMessageID } from './chat-constants.js';
 import css from './chat-message-list.css';
 import FailedSend from './failed-send.react.js';
 import InlineEngagement from './inline-engagement.react.js';
@@ -23,6 +24,8 @@
 import { useMessageTooltip } from '../utils/tooltip-action-utils.js';
 import { tooltipPositions } from '../utils/tooltip-utils.js';
 
+export type ComposedMessageID = string;
+
 const availableTooltipPositionsForViewerMessage = [
   tooltipPositions.LEFT,
   tooltipPositions.LEFT_BOTTOM,
@@ -188,7 +191,11 @@
             onMouseLeave={this.props.onMouseLeave}
           >
             {pinIcon}
-            <div className={messageBoxClassName} style={messageBoxStyle}>
+            <div
+              className={messageBoxClassName}
+              style={messageBoxStyle}
+              id={getComposedMessageID(item.messageInfo)}
+            >
               {this.props.children}
             </div>
           </div>
diff --git a/web/chat/edit-message-provider.js b/web/chat/edit-message-provider.js
--- a/web/chat/edit-message-provider.js
+++ b/web/chat/edit-message-provider.js
@@ -22,8 +22,14 @@
   +editedMessageDraft: ?string,
   +isError: boolean,
   +position?: ModalPosition,
+  +maxHeight: number,
 };
 
+export type ScrollToMessageCallback = (
+  composedMessageID: string,
+  callback: (maxHeight: number) => void,
+) => void;
+
 type EditModalContextType = {
   +renderEditModal: (params: EditState) => void,
   +clearEditModal: () => void,
@@ -31,6 +37,9 @@
   +setDraft: string => void,
   +setError: boolean => void,
   +updatePosition: ModalPosition => void,
+  +scrollToMessage: ScrollToMessageCallback,
+  +addScrollToMessageListener: ScrollToMessageCallback => void,
+  +removeScrollToMessageListener: ScrollToMessageCallback => void,
 };
 
 const EditModalContext: React.Context<EditModalContextType> =
@@ -41,6 +50,9 @@
     setDraft: () => {},
     setError: () => {},
     updatePosition: () => {},
+    scrollToMessage: () => {},
+    addScrollToMessageListener: () => {},
+    removeScrollToMessageListener: () => {},
   });
 
 type Props = {
@@ -51,6 +63,9 @@
 
   const [editState, setEditState] = React.useState<?EditState>(null);
 
+  const [scrollToMessageCallbacks, setScrollToMessageCallbacks] =
+    React.useState<Array<ScrollToMessageCallback>>([]);
+
   const clearEditModal = React.useCallback(() => {
     setEditState(null);
   }, []);
@@ -118,6 +133,36 @@
     [editState, setEditState],
   );
 
+  const scrollToMessage: ScrollToMessageCallback = React.useCallback(
+    (messageKey: string, callback: (maxHeight: number) => void) => {
+      scrollToMessageCallbacks.forEach((callback2: ScrollToMessageCallback) =>
+        callback2(messageKey, callback),
+      );
+    },
+    [scrollToMessageCallbacks],
+  );
+
+  const addScrollToMessageListener = React.useCallback(
+    (callback: ScrollToMessageCallback): void => {
+      setScrollToMessageCallbacks(prevScrollToMessageCallbacks => [
+        ...prevScrollToMessageCallbacks,
+        callback,
+      ]);
+    },
+    [],
+  );
+
+  const removeScrollToMessageListener = React.useCallback(
+    (callback: ScrollToMessageCallback) => {
+      setScrollToMessageCallbacks(prevScrollToMessageCallbacks =>
+        prevScrollToMessageCallbacks.filter(
+          candidate => candidate !== callback,
+        ),
+      );
+    },
+    [],
+  );
+
   const value = React.useMemo(
     () => ({
       renderEditModal,
@@ -126,6 +171,9 @@
       setDraft,
       setError,
       updatePosition,
+      scrollToMessage,
+      addScrollToMessageListener,
+      removeScrollToMessageListener,
     }),
     [
       renderEditModal,
@@ -134,6 +182,9 @@
       setDraft,
       setError,
       updatePosition,
+      scrollToMessage,
+      addScrollToMessageListener,
+      removeScrollToMessageListener,
     ],
   );
 
diff --git a/web/chat/edit-text-message.css b/web/chat/edit-text-message.css
--- a/web/chat/edit-text-message.css
+++ b/web/chat/edit-text-message.css
@@ -1,4 +1,5 @@
 .editMessage {
+  /* Related to editBoxHeight in the `edit-text-message` component */
   padding: 10px;
   background-color: var(--modal-bg);
   border-radius: 8px;
@@ -9,6 +10,7 @@
 }
 
 .bottomRow {
+  /* Related to editBoxHeight in the `edit-text-message` component */
   padding-top: 10px;
   display: flex;
   align-items: center;
diff --git a/web/chat/edit-text-message.react.js b/web/chat/edit-text-message.react.js
--- a/web/chat/edit-text-message.react.js
+++ b/web/chat/edit-text-message.react.js
@@ -10,7 +10,7 @@
 import { trimMessage } from 'lib/shared/message-utils.js';
 import { type ThreadInfo } from 'lib/types/thread-types.js';
 
-import cssInputBar from './chat-input-bar.css';
+import { editBoxBottomRowHeight } from './chat-constants.js';
 import ChatInputTextArea from './chat-input-text-area.react.js';
 import ComposedMessage from './composed-message.react.js';
 import { useEditModalContext } from './edit-message-provider.js';
@@ -28,6 +28,8 @@
   backgroundColor: 'transparent',
 };
 
+const bottomRowStyle = { height: editBoxBottomRowHeight };
+
 function EditTextMessage(props: Props): React.Node {
   const { background, threadInfo, item } = props;
   const { editState, clearEditModal, setDraft, setError, updatePosition } =
@@ -138,18 +140,19 @@
     [css.backgroundEditMessage]: background,
   });
 
+  const maxTextAreaHeight = editState?.maxHeight;
+
   return (
     <div className={containerStyle} ref={myRef}>
-      <div className={cssInputBar.inputBarTextInput}>
-        <ChatInputTextArea
-          focus={!background}
-          currentText={editedMessageDraft}
-          setCurrentText={setDraft}
-          onChangePosition={updateDimensions}
-          send={checkAndEdit}
-        />
-      </div>
-      <div className={css.bottomRow}>
+      <ChatInputTextArea
+        focus={!background}
+        currentText={editedMessageDraft}
+        setCurrentText={setDraft}
+        onChangePosition={updateDimensions}
+        send={checkAndEdit}
+        maxHeight={maxTextAreaHeight}
+      />
+      <div className={css.bottomRow} style={bottomRowStyle}>
         {editFailed}
         <div className={css.buttons}>
           <Button
diff --git a/web/components/button.css b/web/components/button.css
--- a/web/components/button.css
+++ b/web/components/button.css
@@ -8,6 +8,11 @@
   border: none;
 }
 
+/*
+ * Changes to the height of the button component should be reflected in
+ * the `chat-constants.js`component in the `editBoxBottomRowHeight`
+ * variable as well.
+ */
 .btn {
   --border-width: 1px;
   --border-radius: 8px;
diff --git a/web/utils/tooltip-action-utils.js b/web/utils/tooltip-action-utils.js
--- a/web/utils/tooltip-action-utils.js
+++ b/web/utils/tooltip-action-utils.js
@@ -27,6 +27,7 @@
   type TooltipSize,
   type TooltipPosition,
 } from './tooltip-utils.js';
+import { getComposedMessageID } from '../chat/chat-constants.js';
 import { useEditModalContext } from '../chat/edit-message-provider.js';
 import MessageTooltip from '../chat/message-tooltip.react.js';
 import type { PositionInfo } from '../chat/position-types.js';
@@ -226,7 +227,7 @@
   const { messageInfo } = item;
 
   const canEditMessage = useCanEditMessage(threadInfo, messageInfo);
-  const { renderEditModal } = useEditModalContext();
+  const { renderEditModal, scrollToMessage } = useEditModalContext();
   const { clearTooltip } = useTooltipContext();
 
   return React.useMemo(() => {
@@ -235,13 +236,16 @@
     }
     const buttonContent = <CommIcon icon="edit-filled" size={18} />;
     const onClickEdit = () => {
+      const callback = (maxHeight: number) =>
+        renderEditModal({
+          messageInfo: item,
+          threadInfo,
+          isError: false,
+          editedMessageDraft: messageInfo.text,
+          maxHeight: maxHeight,
+        });
       clearTooltip();
-      renderEditModal({
-        messageInfo: item,
-        threadInfo,
-        isError: false,
-        editedMessageDraft: messageInfo.text,
-      });
+      scrollToMessage(getComposedMessageID(messageInfo), callback);
     };
     return {
       actionButtonContent: buttonContent,
@@ -252,8 +256,9 @@
     canEditMessage,
     clearTooltip,
     item,
-    messageInfo.text,
+    messageInfo,
     renderEditModal,
+    scrollToMessage,
     threadInfo,
   ]);
 }