Table of Contents is a relatively new Elementor Pro widget that is very useful and works well. However, it does not have a built-in option to define an offset when scrolling content. Here are two different and independent ways to overcome this shortcoming. Both solutions involve the use of custom code, which is included for both.
I recently worked as a subcontractor on a project for a designer client, which involved creating an Elementor single-post template. The Figma design I used to create the site required a Content table, which is best achieved in Elementor by using its native Table of Contents widget.
The site I was working on has a sticky header, and that’s where the problem arose. Elementor’s Table of Contents widget doesn’t have a built-in option to adjust the offset for scrolling to a target anchor. In this case, when a site visitor clicked on a link in the content, the heading was positioned at the top (the posts on the site are quite long, so they can’t fit on one page) and was underlined below the header. The target title was then not visible, only the content below it – and that wasn’t a good user experience.
You can see how it looks by default here:

Elementor (i.e., its TOC widget) does not have a built-in solution for this problem, so it must be sought through the use of additional custom code. Through research and experimentation, I came up with two different and good solutions to this problem, and I will present both of them here.
Both solutions also involve setting different offsets for different screen sizes; I set them according to the common screen width values for desktop, tablet, and mobile screens (I set the offset values to 60px, 55px, and 50px, respectively). Of course, all of this is easily customizable if your needs are different.
Both solutions presented apply exclusively to the Pro version of Elementor.
A simpler solution: using CSS
The first solution is surprisingly simple to implement, and the code is easy to understand. It relies entirely on CSS. The code is entered into the Custom CSS section of the Table of Contents widget. For the values I announced above, the code entered into the Advanced > Custom CSS field of this widget looks like this:
:root { scroll-padding-top: 60px; } @media (max-width: 1024px) { :root { scroll-padding-top: 55px; } } @media (max-width: 767px) { :root { scroll-padding-top: 50px; } }
I know you know this, but I’ll mention it anyway: don’t use the selector keyword in this case.
The advantage of this solution is, obviously, its simplicity and ease of use. This solution is perfect if you don’t need any additional degree of control or effect (e.g., smooth scrolling).
You can see how it all looks after applying this (CSS) solution here:

More complex solution: using JS
Another solution uses custom JS code. This code is entered from the WP dashboard, not from the Elementor editor. Go to WP dashboard > Elementor > Custom Code. Create a new code snippet and give it a name of your choice, execution location body-end, priority 1. The complete code is this:
<script> /* jshint esversion: 6 */ document.addEventListener('DOMContentLoaded', function () { let offsetDesktop = 60; let offsetTablet = 55; let offsetMobile = 50; function getOffset() { if (window.innerWidth <= 768) return offsetMobile; if (window.innerWidth <= 1024) return offsetTablet; return offsetDesktop; } function smoothScroll(targetId) { let targetElement = document.getElementById(targetId); if (targetElement) { let elementPosition = targetElement.getBoundingClientRect().top + window.scrollY; window.scrollTo({ top: elementPosition - getOffset(), behavior: 'smooth' }); } } function overrideTOCScroll() { document.querySelectorAll('.elementor-widget-table-of-contents a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); let targetId = this.getAttribute('href').substring(1); smoothScroll(targetId); }); }); } overrideTOCScroll(); let observer = new MutationObserver(() => overrideTOCScroll()); observer.observe(document.body, { childList: true, subtree: true }); }); </script>
The advantage of this solution is a greater degree of control. In the above code, smooth scrolling is introduced. In all other respects, the result is the same as in the first solution. This solution is recommended if beautiful effects are a higher priority for you than simplicity.