Hey Brian, feels like this is a bug, and so you can probably ask support for some help. Here’s another thread where a bunch of people were having the same issue
I put together a userscript to solve this problem for myself and I’ve attached it below. To use it, you’d need to install Tampermonkey on your browser and add the script in

(It can probably be written better and I’m very open to feedback on it!)
Let me know if you hit any issues with it and I’ll see what I can do
// ==UserScript==
// @name Airtable Timeline Label Fix
// @description Keeps the labels of the record in view in the Timeline view
// @author Adam
// @homepage https://thetimesaving.company
// @match https://airtable.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=airtable.com
// ==/UserScript==
(function() {
let target = document.getElementById("view")
const observer = new MutationObserver(function() {
if(document.getElementById("view").firstChild.classList.contains("timelineView")){
let lastKnownScrollPosition = 0;
let ticking = false;
let timelineRecordItems = document.getElementsByClassName("timelineRecordItem")
function moveItems(scrollPos) {
for (let timelineRecordItem of timelineRecordItems){
let itemLeft = Number(timelineRecordItem.style.left.replace('px', ''))
let itemWidth = Number(timelineRecordItem.style.width.replace('px', ''))
let leftToWatch = itemLeft + itemWidth
if(scrollPos > itemLeft && scrollPos < leftToWatch){
let newPX = scrollPos.toString() + "px"
timelineRecordItem.getElementsByClassName("px1")a0].style.left = newPX
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"
}
else{
if(timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"){
timelineRecordItem.getElementsByClassName("px1")a0].style.left = "auto"
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "auto"
}
}
}
}
let scrollTarget = timelineRecordItemse0].parentElement.parentElement.parentElement
scrollTarget.addEventListener('scroll', function(e) {
lastKnownScrollPosition = scrollTarget.scrollLeft;
if (!ticking) {
window.requestAnimationFrame(function() {
moveItems(lastKnownScrollPosition);
ticking = false;
});
ticking = true;
}
});
}
});
observer.observe(target, {subtree: true, childList: true});
})();
Hey Brian, feels like this is a bug, and so you can probably ask support for some help. Here’s another thread where a bunch of people were having the same issue
I put together a userscript to solve this problem for myself and I’ve attached it below. To use it, you’d need to install Tampermonkey on your browser and add the script in

(It can probably be written better and I’m very open to feedback on it!)
Let me know if you hit any issues with it and I’ll see what I can do
// ==UserScript==
// @name Airtable Timeline Label Fix
// @description Keeps the labels of the record in view in the Timeline view
// @author Adam
// @homepage https://thetimesaving.company
// @match https://airtable.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=airtable.com
// ==/UserScript==
(function() {
let target = document.getElementById("view")
const observer = new MutationObserver(function() {
if(document.getElementById("view").firstChild.classList.contains("timelineView")){
let lastKnownScrollPosition = 0;
let ticking = false;
let timelineRecordItems = document.getElementsByClassName("timelineRecordItem")
function moveItems(scrollPos) {
for (let timelineRecordItem of timelineRecordItems){
let itemLeft = Number(timelineRecordItem.style.left.replace('px', ''))
let itemWidth = Number(timelineRecordItem.style.width.replace('px', ''))
let leftToWatch = itemLeft + itemWidth
if(scrollPos > itemLeft && scrollPos < leftToWatch){
let newPX = scrollPos.toString() + "px"
timelineRecordItem.getElementsByClassName("px1")a0].style.left = newPX
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"
}
else{
if(timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"){
timelineRecordItem.getElementsByClassName("px1")a0].style.left = "auto"
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "auto"
}
}
}
}
let scrollTarget = timelineRecordItemse0].parentElement.parentElement.parentElement
scrollTarget.addEventListener('scroll', function(e) {
lastKnownScrollPosition = scrollTarget.scrollLeft;
if (!ticking) {
window.requestAnimationFrame(function() {
moveItems(lastKnownScrollPosition);
ticking = false;
});
ticking = true;
}
});
}
});
observer.observe(target, {subtree: true, childList: true});
})();
@Brian_Cavanaugh FYI I contacted support about this and the response on 6/13/22 was: “engineering has let me know that this is expected behavior. We recently removed these indicators due to performance reasons.”
@Adam_TheTimeSavingCo Many thanks!
Hey Brian, feels like this is a bug, and so you can probably ask support for some help. Here’s another thread where a bunch of people were having the same issue
I put together a userscript to solve this problem for myself and I’ve attached it below. To use it, you’d need to install Tampermonkey on your browser and add the script in

(It can probably be written better and I’m very open to feedback on it!)
Let me know if you hit any issues with it and I’ll see what I can do
// ==UserScript==
// @name Airtable Timeline Label Fix
// @description Keeps the labels of the record in view in the Timeline view
// @author Adam
// @homepage https://thetimesaving.company
// @match https://airtable.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=airtable.com
// ==/UserScript==
(function() {
let target = document.getElementById("view")
const observer = new MutationObserver(function() {
if(document.getElementById("view").firstChild.classList.contains("timelineView")){
let lastKnownScrollPosition = 0;
let ticking = false;
let timelineRecordItems = document.getElementsByClassName("timelineRecordItem")
function moveItems(scrollPos) {
for (let timelineRecordItem of timelineRecordItems){
let itemLeft = Number(timelineRecordItem.style.left.replace('px', ''))
let itemWidth = Number(timelineRecordItem.style.width.replace('px', ''))
let leftToWatch = itemLeft + itemWidth
if(scrollPos > itemLeft && scrollPos < leftToWatch){
let newPX = scrollPos.toString() + "px"
timelineRecordItem.getElementsByClassName("px1")a0].style.left = newPX
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"
}
else{
if(timelineRecordItem.getElementsByClassName("px1")a0].style.position = "fixed"){
timelineRecordItem.getElementsByClassName("px1")a0].style.left = "auto"
timelineRecordItem.getElementsByClassName("px1")a0].style.position = "auto"
}
}
}
}
let scrollTarget = timelineRecordItemse0].parentElement.parentElement.parentElement
scrollTarget.addEventListener('scroll', function(e) {
lastKnownScrollPosition = scrollTarget.scrollLeft;
if (!ticking) {
window.requestAnimationFrame(function() {
moveItems(lastKnownScrollPosition);
ticking = false;
});
ticking = true;
}
});
}
});
observer.observe(target, {subtree: true, childList: true});
})();
Thanks, Adam! I’ll give this a try and see if it helps. i’ve sent a support request twice with no response yet so we’ll see what the support team has to say when the time comes.
@Brian_Cavanaugh FYI I contacted support about this and the response on 6/13/22 was: “engineering has let me know that this is expected behavior. We recently removed these indicators due to performance reasons.”
@Adam_TheTimeSavingCo Many thanks!
@tbesa Thanks for the heads up. I’ve also reached out to support and have yet to hear back, but will be interested to see if I receive the same response.
I can understand optimizing things for performance, but this seems like a poor choice as in my opinion this change makes the timeline view completely unusable. What good is a timeline to be looking at a long list of records over time with no context of what projects I’m even looking at / evaluating. Sometimes I have to scroll back several months to see what project I’m looking at. Hovering over each one is a pain to get that information too because I want to see all of the projects in comparison at a glance, not one at a time with a hover tool tip.
I’ll update this thread if I receive a different response.
Appreciate the help!