diff --git a/src/plainui/jinja2/plainui/components/calendar.html.j2 b/src/plainui/jinja2/plainui/components/calendar.html.j2
index 3e52e835005c912b8cf9851d4fab71c5335932c9..e09a5a8df7407a4f0db26083a3d4e0a72322557b 100644
--- a/src/plainui/jinja2/plainui/components/calendar.html.j2
+++ b/src/plainui/jinja2/plainui/components/calendar.html.j2
@@ -7,7 +7,7 @@
   {%- else -%}
     {% set time_steps = events.calendar_time_steps -%}
     {% set step_minutes = events.calendar_step_minutes -%}
-    <div class="hub-fahrplan">
+    <div id="hub-fahrplan-calendar" class="hub-fahrplan">
       {% for step in time_steps %}
         <hr class="hub-calendar__divider"
             style="top: {{ 56 + (loop.index0 * step_minutes * 6) }}px">
@@ -33,12 +33,14 @@
               <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
             </h2>
           {% else %}
-            <a class="text-decoration-none a"
-               href="{{ url('plainui:room', slug=room.slug) }}">
-              <h2 class="hub-calendar__column-title" title="{{ room.name }}">
-                <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
-              </h2>
-            </a>
+            <div class="hub-calendar__column-title">
+              <a class="text-decoration-none a"
+                 href="{{ url('plainui:room', slug=room.slug) }}">
+                <h2 title="{{ room.name }}">
+                  <div class="hub-calendar__column-title-inner">{{ room.name }}</div>
+                </h2>
+              </a>
+            </div>
           {% endif %}
           {% for entry in room_events %}
             {% if entry.type == 'space' %}
diff --git a/src/plainui/jinja2/plainui/fahrplan.html.j2 b/src/plainui/jinja2/plainui/fahrplan.html.j2
index 1e2b05bfc66fc9e4d9449a48933263cce1c7b34a..79f6c5e63607d8e1c434a340672b55ddda5c6bc4 100644
--- a/src/plainui/jinja2/plainui/fahrplan.html.j2
+++ b/src/plainui/jinja2/plainui/fahrplan.html.j2
@@ -4,6 +4,10 @@
 {% import "plainui/components/nav.html.j2" as navMacro with context %}
 {% import "plainui/components/tagbox.html.j2" as tagMacros with context %}
 
+{% block head %}
+  <script src="{{ static('plainui/js/fahrplan.js') }}" /></script>
+{% endblock head %}
+
 {% macro filter_button(value, active, label) -%}
   <button type="submit"
           name="set"
diff --git a/src/plainui/jinja2/plainui/public_fahrplan.html.j2 b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
index 81e48466058bca83e0ef532a005d3b5029fb8dd0..f077861d4ab2d609c5e069b761d6861f3a78584e 100644
--- a/src/plainui/jinja2/plainui/public_fahrplan.html.j2
+++ b/src/plainui/jinja2/plainui/public_fahrplan.html.j2
@@ -22,6 +22,7 @@
                 document.querySelector('html').classList.add('js');
             });
     </script>
+    <script src="{{ static('plainui/js/fahrplan.js') }}" /></script>
   </head>
   <body class="hub-fahrplan__pub-body eyecandy">
     <div class="hub-bg-L04 hub-fahrplan__pub-content">
diff --git a/src/plainui/static/plainui/js/fahrplan.js b/src/plainui/static/plainui/js/fahrplan.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad7272a7082d4d9c363d3b31c1839c0ab5b912b7
--- /dev/null
+++ b/src/plainui/static/plainui/js/fahrplan.js
@@ -0,0 +1,47 @@
+// No ES modules used. Wrap into a closure to avoid collisions.
+(function () {
+  // Wait until document is loaded
+  const docReady = (callback) => {
+    if (document.readyState != "loading") callback();
+    else document.addEventListener("DOMContentLoaded", callback);
+  };
+
+  // Defined in _calendar.scss
+  const scrollOffset = -5;
+
+  /**
+   * Tries to get the Fahrplan Element.
+   * This may be something different depending on whether it shows the public or regular Fahrplan view.
+   */
+  const getFahrplanElement = () => {
+    return document.querySelector(".hub-fahrplan__pub-box") ?? document.getElementById("hub-fahrplan-calendar");
+  };
+
+  docReady(() => {
+    const fahrplanElement = getFahrplanElement();
+
+    if (fahrplanElement === null) {
+      // Nothing to do, if there is no Fahrplan
+      return;
+    }
+
+    const roomNames = document.querySelectorAll(".hub-calendar__column-title");
+
+    /**
+     * When scrolling, keep room names always on top of the columns.
+     *
+     * @param {Event} event
+     */
+    const handleScroll = (event) => {
+      // Keep room names always on top of the columns
+      const scrollPosition = event.target.scrollTop;
+      const roomNameTop = `${scrollPosition + scrollOffset}px`;
+
+      roomNames.forEach((roomName) => {
+        roomName.style.top = roomNameTop;
+      });
+    };
+
+    fahrplanElement.addEventListener("scroll", handleScroll);
+  });
+})();
diff --git a/src/plainui/styles/components/_calendar.scss b/src/plainui/styles/components/_calendar.scss
index fed3ebe669db163533065db56bb782a6ca4ce9d5..dd9cfd8cc5f2a4dd752cc2040178f0bc7c4f899f 100644
--- a/src/plainui/styles/components/_calendar.scss
+++ b/src/plainui/styles/components/_calendar.scss
@@ -1,7 +1,13 @@
 .hub-calendar__column-title {
   height: 72px;
   margin-bottom: 0;
-  padding: map-get($spacers, 1);
+  padding: 0 map-get($spacers, 1) map-get($spacers, 1);
+  position: relative;
+  top: -5px;
+}
+
+.hub-calendar__column-title h2 {
+  font-size: 1.8rem;
 }
 
 .hub-calendar__column-title-inner {
@@ -9,7 +15,6 @@
   -webkit-box-orient: vertical;
   color: $white;
   display: -webkit-box;
-  font: $hub-head-category-font;
   overflow: hidden;
   text-align: center;
   text-overflow: ellipsis;
diff --git a/src/plainui/styles/components/_fahrplan.scss b/src/plainui/styles/components/_fahrplan.scss
index 8e06c1a609f1fe464f00f3cf617650b04379d93e..f991cb55c3e7450fe7d2b328105dc3586de9035d 100644
--- a/src/plainui/styles/components/_fahrplan.scss
+++ b/src/plainui/styles/components/_fahrplan.scss
@@ -123,6 +123,7 @@ $public-fahrplan-body-padding: 0.7rem;
 }
 
 .hub-fahrplan__pub-box {
+  padding-top: 10px;
   max-height: 100%;
   overflow: scroll;
 }