diff --git a/web_src/js/index.js b/web_src/js/index.js
index ec9df29e74..aa684b0467 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -788,10 +788,13 @@ async function initRepository() {
 
   // Commit statuses
   $('.commit-statuses-trigger').each(function () {
+    const positionRight = $('.repository.file.list').length > 0 || $('.repository.diff').length > 0;
+    const popupPosition = positionRight ? 'right center' : 'left center';
     $(this)
       .popup({
         on: 'click',
-        position: ($('.repository.file.list').length > 0 ? 'right center' : 'left center'),
+        lastResort: popupPosition, // prevent error message "Popup does not fit within the boundaries of the viewport"
+        position: popupPosition,
       });
   });
 
diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less
index ba6f19617c..993b7f5be2 100644
--- a/web_src/less/_repository.less
+++ b/web_src/less/_repository.less
@@ -1,6 +1,19 @@
 .repository {
-  .commit-statuses .list > .item {
-    line-height: 2;
+  .popup.commit-statuses {
+    // we had better limit the max size of the popup, and add scroll bars if the content size is too large.
+    // otherwise some part of the popup will be hidden by viewport boundary
+    max-height: 45vh;
+    max-width: 60vw;
+    overflow: auto;
+    padding: 0;
+
+    .list {
+      padding: .8em; // to make the scrollbar align to the border, we move the padding from outer `.popup` to this inside `.list`
+
+      > .item {
+        line-height: 2;
+      }
+    }
   }
 
   .repo-header {