diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
index e047d10ac93d953875248188e9562de33f4be9c1..c32dc83da8e703fcd69c994fb6a07b0b77e298e5 100644
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
@@ -109,6 +109,7 @@ export default {
             :key="i"
           >
             <job-component
+              :dropdown-length="job.size"
               :job="item"
               css-class-job-name="mini-pipeline-graph-dropdown-item"
               @pipelineActionRequestComplete="pipelineActionRequestComplete"
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue
index 886e62ab1a73c19c6bbcc27b097e42cdb1f78b92..8af984ef91a6b788a43788bde4133ebefc1ab0ec 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue
@@ -46,6 +46,11 @@ export default {
       required: false,
       default: '',
     },
+    dropdownLength: {
+      type: Number,
+      required: false,
+      default: Infinity,
+    },
   },
   computed: {
     status() {
@@ -70,6 +75,10 @@ export default {
       return textBuilder.join(' ');
     },
 
+    tooltipBoundary() {
+      return this.dropdownLength < 5 ? 'viewport' : null;
+    },
+
     /**
      * Verifies if the provided job has an action path
      *
@@ -94,9 +103,9 @@ export default {
       :href="status.details_path"
       :title="tooltipText"
       :class="cssClassJobName"
+      :data-boundary="tooltipBoundary"
       data-container="body"
       data-html="true"
-      data-boundary="viewport"
       class="js-pipeline-graph-job-link"
     >
 
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index b9231c002fdc8730ba223283413b90554e622420..56fdb858088dad02015d1a3d89bfe29b568f294e 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -186,32 +186,27 @@ export default {
       </i>
     </button>
 
-    <ul
+    <div
       class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
       aria-labelledby="stageDropdown"
     >
-
-      <li
+      <loading-icon v-if="isLoading"/>
+      <ul
+        v-else
         class="js-builds-dropdown-list scrollable-menu"
       >
-
-        <loading-icon v-if="isLoading"/>
-
-        <ul
-          v-else
+        <li
+          v-for="job in dropdownContent"
+          :key="job.id"
         >
-          <li
-            v-for="job in dropdownContent"
-            :key="job.id"
-          >
-            <job-component
-              :job="job"
-              css-class-job-name="mini-pipeline-graph-dropdown-item"
-              @pipelineActionRequestComplete="pipelineActionRequestComplete"
-            />
-          </li>
-        </ul>
-      </li>
-    </ul>
+          <job-component
+            :dropdown-length="dropdownContent.length"
+            :job="job"
+            css-class-job-name="mini-pipeline-graph-dropdown-item"
+            @pipelineActionRequestComplete="pipelineActionRequestComplete"
+          />
+        </li>
+      </ul>
+    </div>
   </div>
 </template>
diff --git a/changelogs/unreleased/47516-pipe-scroll.yml b/changelogs/unreleased/47516-pipe-scroll.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3e283f649bd8103f33b22a27b662ea3d316d6de0
--- /dev/null
+++ b/changelogs/unreleased/47516-pipe-scroll.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent pipeline job tooltip from scrolling off dropdown container
+merge_request:
+author:
+type: fixed
diff --git a/spec/javascripts/pipelines/graph/job_component_spec.js b/spec/javascripts/pipelines/graph/job_component_spec.js
index 073dae56c25956077d403e57cf621a6d3d64bcd4..9c55a19ebc707af04dc07c0ac815a84ec3d0b3e0 100644
--- a/spec/javascripts/pipelines/graph/job_component_spec.js
+++ b/spec/javascripts/pipelines/graph/job_component_spec.js
@@ -135,4 +135,34 @@ describe('pipeline graph job component', () => {
       expect(component.$el.querySelector('.js-job-component-tooltip').getAttribute('data-original-title')).toEqual('test - success');
     });
   });
+
+  describe('tooltip placement', () => {
+    const tooltipBoundary = 'a[data-boundary="viewport"]';
+
+    it('does not set tooltip boundary by default', () => {
+      component = mountComponent(JobComponent, {
+        job: mockJob,
+      });
+
+      expect(component.$el.querySelector(tooltipBoundary)).toBeNull();
+    });
+
+    it('sets tooltip boundary to viewport for small dropdowns', () => {
+      component = mountComponent(JobComponent, {
+        job: mockJob,
+        dropdownLength: 1,
+      });
+
+      expect(component.$el.querySelector(tooltipBoundary)).not.toBeNull();
+    });
+
+    it('does not set tooltip boundary for large lists', () => {
+      component = mountComponent(JobComponent, {
+        job: mockJob,
+        dropdownLength: 7,
+      });
+
+      expect(component.$el.querySelector(tooltipBoundary)).toBeNull();
+    });
+  });
 });