diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 551a66fbf3aba2b1f2d3a3135f884320ae9512be..bac831ec315d39cbb9a532b7b9b4f09f43b158e2 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -43,6 +43,12 @@
     }
   }
 
+  .todo-avatar,
+  .todo-actions {
+    -webkit-flex: 0 0 auto;
+    flex: 0 0 auto;
+  }
+
   .todo-actions {
     display: -webkit-flex;
     display: flex;
@@ -55,8 +61,9 @@
   }
 
   .todo-item {
-    -webkit-flex: auto;
-    flex: auto;
+    -webkit-flex: 0 1 100%;
+    flex: 0 1 100%;
+    min-width: 0;
   }
 }
 
@@ -74,8 +81,29 @@
 
 .todo-item {
   .todo-title {
-    @include str-truncated(calc(100% - 174px));
-    overflow: visible;
+    display: flex;
+
+    & > .title-item {
+      -webkit-flex: 0 0 auto;
+      flex: 0 0 auto;
+      margin: 0 2px;
+
+      &:first-child {
+        margin-left: 0;
+      }
+
+      &:last-child {
+        margin-right: 0;
+      }
+    }
+
+    .todo-label {
+      -webkit-flex: 0 1 auto;
+      flex: 0 1 auto;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
   }
 
   .status-box {
@@ -154,10 +182,12 @@
 
   .todo-item {
     .todo-title {
-      white-space: normal;
-      overflow: visible;
-      max-width: 100%;
+      flex-flow: row wrap;
       margin-bottom: 10px;
+
+      .todo-label {
+        white-space: normal;
+      }
     }
 
     .todo-body {
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index dc2d924f212a69d4e64049657a7c9dc8406249fe..a3993d5ef16709162ffb39e2b40f48bf821c1f30 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -1,28 +1,33 @@
 %li{ class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo), data: { url: todo_target_path(todo) } }
-  = author_avatar(todo, size: 40)
+  .todo-avatar
+    = author_avatar(todo, size: 40)
 
   .todo-item.todo-block
     .todo-title.title
       - unless todo.build_failed? || todo.unmergeable?
         = todo_target_state_pill(todo)
 
-        %span.author-name
+        .title-item.author-name
           - if todo.author
             = link_to_author(todo)
           - else
             (removed)
 
-      %span.action-name
+      .title-item.action-name
         = todo_action_name(todo)
 
-      %span.todo-label
+      .title-item.todo-label
         - if todo.target
           = todo_target_link(todo)
         - else
           (removed)
 
-      · #{time_ago_with_tooltip(todo.created_at)}
-      = todo_due_date(todo)
+      .title-item
+        ·
+
+      .title-item
+        #{time_ago_with_tooltip(todo.created_at)}
+        = todo_due_date(todo)
 
     .todo-body
       .todo-note
diff --git a/changelogs/unreleased/28186-long-group-names-overflow-out-of-todos-view.yml b/changelogs/unreleased/28186-long-group-names-overflow-out-of-todos-view.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3bcf0e06d081a7fbceff6a02dcf76b11327f449f
--- /dev/null
+++ b/changelogs/unreleased/28186-long-group-names-overflow-out-of-todos-view.yml
@@ -0,0 +1,4 @@
+---
+title: Truncate long Todo titles for non-mobile screens
+merge_request: 9311
+author: