diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index 060449d75ebc1bc49329e4240a852dd0546b9a3e..b575fab14451d55e603c76ec724410b26b7456f3 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -760,15 +760,20 @@ drupal.tabledrag.ajax:
 
 drupal.tableheader:
   version: VERSION
-  js:
-    misc/tableheader.js: {}
-  dependencies:
-    - core/jquery
-    - core/drupal
-    - core/drupalSettings
-    - core/once
-    - core/drupal.displace
-
+  css:
+    component:
+      misc/components/sticky-header.module.css: { weight: -10 }
+  moved_files:
+    system/base:
+      deprecation_version: 10.3.0
+      removed_version: 11.0.0
+      deprecation_link: https://www.drupal.org/node/3440477
+      css:
+        component:
+          css/components/sticky-header.module.css: misc/components/sticky-header.module.css
+      js:
+        misc/tableheader.js: false
+        
 drupal.tableresponsive:
   version: VERSION
   js:
diff --git a/core/lib/Drupal/Core/Render/Element/Table.php b/core/lib/Drupal/Core/Render/Element/Table.php
index cc2925bcd764911163da5b6ed528c0f0f03f4a9c..c3e17db87b74fe1615e9871d2a467a8572379886 100644
--- a/core/lib/Drupal/Core/Render/Element/Table.php
+++ b/core/lib/Drupal/Core/Render/Element/Table.php
@@ -23,8 +23,8 @@
  * - #empty: Text to display when no rows are present.
  * - #responsive: Indicates whether to add the drupal.tableresponsive library
  *   providing responsive tables.  Defaults to TRUE.
- * - #sticky: Indicates whether to add the drupal.tableheader library that makes
- *   table headers always visible at the top of the page. Defaults to FALSE.
+ * - #sticky: Indicates whether to make the table headers sticky at
+ *   the top of the page. Defaults to FALSE.
  * - #footer: Table footer rows, in the same format as the #rows property.
  * - #caption: A localized string for the <caption> tag.
  *
@@ -420,9 +420,7 @@ public static function preRenderTable($element) {
     // Add sticky headers, if applicable.
     if (count($element['#header']) && $element['#sticky']) {
       $element['#attached']['library'][] = 'core/drupal.tableheader';
-      // Add 'sticky-enabled' class to the table to identify it for JS.
-      // This is needed to target tables constructed by this function.
-      $element['#attributes']['class'][] = 'sticky-enabled';
+      $element['#attributes']['class'][] = 'sticky-header';
     }
     // If the table has headers and it should react responsively to columns hidden
     // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
diff --git a/core/misc/components/sticky-header.module.css b/core/misc/components/sticky-header.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..63571d9fd2612e8c3e75ebd13495e891b25e5e29
--- /dev/null
+++ b/core/misc/components/sticky-header.module.css
@@ -0,0 +1,5 @@
+table.sticky-header thead {
+  position: sticky;
+  z-index: 500;
+  top: var(--drupal-displace-offset-top, 0);
+}
diff --git a/core/misc/tableheader.js b/core/misc/tableheader.js
deleted file mode 100644
index f649a767a3983576dec20b86f0dd90e4afc8c7dc..0000000000000000000000000000000000000000
--- a/core/misc/tableheader.js
+++ /dev/null
@@ -1,335 +0,0 @@
-/**
- * @file
- * Sticky table headers.
- */
-
-(function ($, Drupal, displace) {
-  /**
-   * Constructor for the tableHeader object. Provides sticky table headers.
-   *
-   * TableHeader will make the current table header stick to the top of the page
-   * if the table is very long.
-   *
-   * @constructor Drupal.TableHeader
-   *
-   * @param {HTMLElement} table
-   *   DOM object for the table to add a sticky header to.
-   *
-   * @listens event:columnschange
-   */
-  function TableHeader(table) {
-    const $table = $(table);
-
-    /**
-     * @name Drupal.TableHeader#$originalTable
-     *
-     * @type {HTMLElement}
-     */
-    this.$originalTable = $table;
-
-    /**
-     * @type {jQuery}
-     */
-    this.$originalHeader = $table.children('thead');
-
-    /**
-     * @type {jQuery}
-     */
-    this.$originalHeaderCells = this.$originalHeader.find('> tr > th');
-
-    /**
-     * @type {null|boolean}
-     */
-    this.displayWeight = null;
-    this.$originalTable.addClass('sticky-table');
-    this.tableHeight = $table[0].clientHeight;
-    this.tableOffset = this.$originalTable.offset();
-
-    // React to columns change to avoid making checks in the scroll callback.
-    this.$originalTable.on(
-      'columnschange',
-      { tableHeader: this },
-      (e, display) => {
-        const tableHeader = e.data.tableHeader;
-        if (
-          tableHeader.displayWeight === null ||
-          tableHeader.displayWeight !== display
-        ) {
-          tableHeader.recalculateSticky();
-        }
-        tableHeader.displayWeight = display;
-      },
-    );
-
-    // Create and display sticky header.
-    this.createSticky();
-  }
-
-  // Helper method to loop through tables and execute a method.
-  function forTables(method, arg) {
-    const tables = TableHeader.tables;
-    const il = tables.length;
-    for (let i = 0; i < il; i++) {
-      tables[i][method](arg);
-    }
-  }
-
-  // Select and initialize sticky table headers.
-  function tableHeaderInitHandler(e) {
-    once('tableheader', $(e.data.context).find('table.sticky-enabled')).forEach(
-      (table) => {
-        TableHeader.tables.push(new TableHeader(table));
-      },
-    );
-    forTables('onScroll');
-  }
-
-  /**
-   * Attaches sticky table headers.
-   *
-   * @type {Drupal~behavior}
-   *
-   * @prop {Drupal~behaviorAttach} attach
-   *   Attaches the sticky table header behavior.
-   */
-  Drupal.behaviors.tableHeader = {
-    attach(context) {
-      $(window).one(
-        'scroll.TableHeaderInit',
-        { context },
-        tableHeaderInitHandler,
-      );
-    },
-  };
-
-  function scrollValue(position) {
-    return document.documentElement[position] || document.body[position];
-  }
-
-  function tableHeaderResizeHandler(e) {
-    forTables('recalculateSticky');
-  }
-
-  function tableHeaderOnScrollHandler(e) {
-    forTables('onScroll');
-  }
-
-  function tableHeaderOffsetChangeHandler(e, offsets) {
-    forTables('stickyPosition', offsets.top);
-  }
-
-  // Bind event that need to change all tables.
-  $(window).on({
-    /**
-     * When resizing table width can change, recalculate everything.
-     *
-     * @ignore
-     */
-    'resize.TableHeader': tableHeaderResizeHandler,
-
-    /**
-     * Bind only one event to take care of calling all scroll callbacks.
-     *
-     * @ignore
-     */
-    'scroll.TableHeader': tableHeaderOnScrollHandler,
-  });
-  // Bind to custom Drupal events.
-  $(document).on({
-    /**
-     * Recalculate columns width when window is resized, when show/hide weight
-     * is triggered, or when toolbar tray is toggled.
-     *
-     * @ignore
-     */
-    'columnschange.TableHeader drupalToolbarTrayChange':
-      tableHeaderResizeHandler,
-
-    /**
-     * Recalculate TableHeader.topOffset when viewport is resized.
-     *
-     * @ignore
-     */
-    'drupalViewportOffsetChange.TableHeader': tableHeaderOffsetChangeHandler,
-  });
-
-  /**
-   * Store the state of TableHeader.
-   */
-  $.extend(
-    TableHeader,
-    /** @lends Drupal.TableHeader */ {
-      /**
-       * This will store the state of all processed tables.
-       *
-       * @type {Array.<Drupal.TableHeader>}
-       */
-      tables: [],
-    },
-  );
-
-  /**
-   * Extend TableHeader prototype.
-   */
-  $.extend(
-    TableHeader.prototype,
-    /** @lends Drupal.TableHeader# */ {
-      /**
-       * Minimum height in pixels for the table to have a sticky header.
-       *
-       * @type {number}
-       */
-      minHeight: 100,
-
-      /**
-       * Absolute position of the table on the page.
-       *
-       * @type {?Drupal~displaceOffset}
-       */
-      tableOffset: null,
-
-      /**
-       * Absolute position of the table on the page.
-       *
-       * @type {?number}
-       */
-      tableHeight: null,
-
-      /**
-       * Boolean storing the sticky header visibility state.
-       *
-       * @type {boolean}
-       */
-      stickyVisible: false,
-
-      /**
-       * Create the duplicate header.
-       */
-      createSticky() {
-        // For caching purposes.
-        this.$html = $('html');
-        // Clone the table header so it inherits original jQuery properties.
-        const $stickyHeader = this.$originalHeader.clone(true);
-        // Hide the table to avoid a flash of the header clone upon page load.
-        this.$stickyTable = $(
-          '<table class="sticky-header" style="visibility: hidden; position: fixed; top: 0;"></table>',
-        )
-          .append($stickyHeader)
-          .insertBefore(this.$originalTable);
-
-        this.$stickyHeaderCells = $stickyHeader.find('> tr > th');
-
-        // Initialize all computations.
-        this.recalculateSticky();
-      },
-
-      /**
-       * Set absolute position of sticky.
-       *
-       * @param {number} offsetTop
-       *   The top offset for the sticky header.
-       * @param {number} offsetLeft
-       *   The left offset for the sticky header.
-       *
-       * @return {jQuery}
-       *   The sticky table as a jQuery collection.
-       */
-      stickyPosition(offsetTop, offsetLeft) {
-        const css = {};
-        if (typeof offsetTop === 'number') {
-          css.top = `${offsetTop}px`;
-        }
-        if (typeof offsetLeft === 'number') {
-          css.left = `${this.tableOffset.left - offsetLeft}px`;
-        }
-        this.$html[0].style.scrollPaddingTop =
-          displace.offsets.top +
-          (this.stickyVisible ? this.$stickyTable.height() : 0);
-
-        Object.assign(this.$stickyTable[0].style, css);
-
-        return this.$stickyTable;
-      },
-
-      /**
-       * Returns true if sticky is currently visible.
-       *
-       * @return {boolean}
-       *   The visibility status.
-       */
-      checkStickyVisible() {
-        const scrollTop = scrollValue('scrollTop');
-        const tableTop = this.tableOffset.top - displace.offsets.top;
-        const tableBottom = tableTop + this.tableHeight;
-        let visible = false;
-
-        if (tableTop < scrollTop && scrollTop < tableBottom - this.minHeight) {
-          visible = true;
-        }
-
-        this.stickyVisible = visible;
-        return visible;
-      },
-
-      /**
-       * Check if sticky header should be displayed.
-       *
-       * This function is throttled to once every 250ms to avoid unnecessary
-       * calls.
-       *
-       * @param {jQuery.Event} e
-       *   The scroll event.
-       */
-      onScroll(e) {
-        this.checkStickyVisible();
-        // Track horizontal positioning relative to the viewport.
-        this.stickyPosition(null, scrollValue('scrollLeft'));
-        this.$stickyTable[0].style.visibility = this.stickyVisible
-          ? 'visible'
-          : 'hidden';
-      },
-
-      /**
-       * Event handler: recalculates position of the sticky table header.
-       *
-       * @param {jQuery.Event} event
-       *   Event being triggered.
-       */
-      recalculateSticky(event) {
-        // Update table size.
-        this.tableHeight = this.$originalTable[0].clientHeight;
-
-        // Update offset top.
-        displace.offsets.top = displace.calculateOffset('top');
-        this.tableOffset = this.$originalTable.offset();
-        this.stickyPosition(displace.offsets.top, scrollValue('scrollLeft'));
-
-        // Update columns width.
-        let $that = null;
-        let $stickyCell = null;
-        let display = null;
-        // Resize header and its cell widths.
-        // Only apply width to visible table cells. This prevents the header from
-        // displaying incorrectly when the sticky header is no longer visible.
-        const il = this.$originalHeaderCells.length;
-        for (let i = 0; i < il; i++) {
-          $that = $(this.$originalHeaderCells[i]);
-          $stickyCell = this.$stickyHeaderCells.eq($that.index());
-          display = window.getComputedStyle($that[0]).display;
-          if (display !== 'none') {
-            Object.assign($stickyCell[0].style, {
-              width: window.getComputedStyle($that[0]).width,
-              display,
-            });
-          } else {
-            $stickyCell[0].style.display = 'none';
-          }
-        }
-        this.$stickyTable[0].style.width = `${this.$originalTable.outerWidth()}px`;
-      },
-    },
-  );
-
-  // Expose constructor in the public space.
-  Drupal.TableHeader = TableHeader;
-})(jQuery, Drupal, window.Drupal.displace);
diff --git a/core/modules/system/css/components/sticky-header.module.css b/core/modules/system/css/components/sticky-header.module.css
deleted file mode 100644
index f6a1b1ec0c627b940216f849506eadbe62fc097a..0000000000000000000000000000000000000000
--- a/core/modules/system/css/components/sticky-header.module.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * @file
- * Table header behavior.
- *
- * @see tableheader.js
- */
-
-table.sticky-header {
-  z-index: 500;
-  top: 0;
-  margin-top: 0;
-  background-color: #fff;
-}
diff --git a/core/modules/system/system.libraries.yml b/core/modules/system/system.libraries.yml
index d708796dd51984dcf653afe0600823fa090fcd24..11491f7a779aea85b6f404ecd93e49440dac8a92 100644
--- a/core/modules/system/system.libraries.yml
+++ b/core/modules/system/system.libraries.yml
@@ -15,7 +15,6 @@ base:
       css/components/position-container.module.css: { weight: -10 }
       css/components/reset-appearance.module.css: { weight: -10 }
       css/components/resize.module.css: { weight: -10 }
-      css/components/sticky-header.module.css: { weight: -10 }
       css/components/system-status-counter.css: { weight: -10 }
       css/components/system-status-report-counters.css: { weight: -10 }
       css/components/system-status-report-general-info.css: { weight: -10 }
diff --git a/core/modules/views/templates/views-view-table.html.twig b/core/modules/views/templates/views-view-table.html.twig
index 0f0bd5ebcbafaa9911256b2da5a13d4c9db375eb..ac62b5c983cfbe731fcfd8ae042cc59b61cb368f 100644
--- a/core/modules/views/templates/views-view-table.html.twig
+++ b/core/modules/views/templates/views-view-table.html.twig
@@ -37,7 +37,7 @@
   set classes = [
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'sticky-enabled',
+    sticky ? 'sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>
diff --git a/core/profiles/demo_umami/themes/umami/templates/classy/views/views-view-table.html.twig b/core/profiles/demo_umami/themes/umami/templates/classy/views/views-view-table.html.twig
index edc14983da77f19519d5e5fcba6230c281cc634a..042c42b1bc19c66013f618433a71b583a8b6076f 100644
--- a/core/profiles/demo_umami/themes/umami/templates/classy/views/views-view-table.html.twig
+++ b/core/profiles/demo_umami/themes/umami/templates/classy/views/views-view-table.html.twig
@@ -37,7 +37,7 @@
     'views-view-table',
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'sticky-enabled',
+    sticky ? 'sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>
diff --git a/core/tests/Drupal/KernelTests/Core/Render/Element/TableTest.php b/core/tests/Drupal/KernelTests/Core/Render/Element/TableTest.php
index 24f4ed8b277ec2837f00f219d3e0158bdef8ade6..04741d5114b883384dab997b780da1c405c347d2 100644
--- a/core/tests/Drupal/KernelTests/Core/Render/Element/TableTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Render/Element/TableTest.php
@@ -21,7 +21,7 @@ class TableTest extends KernelTestBase {
   protected static $modules = ['system', 'form_test'];
 
   /**
-   * Tableheader.js provides 'sticky' table headers, and is included by default.
+   * If $sticky is TRUE, `sticky-header` class should be included.
    */
   public function testThemeTableStickyHeaders() {
     $header = ['one', 'two', 'three'];
@@ -33,14 +33,11 @@ public function testThemeTableStickyHeaders() {
       '#sticky' => TRUE,
     ];
     $this->render($table);
-    // Make sure tableheader.js was attached.
-    $tableheader = $this->xpath("//script[contains(@src, 'tableheader.js')]");
-    $this->assertCount(1, $tableheader);
-    $this->assertRaw('sticky-enabled');
+    $this->assertRaw('sticky-header');
   }
 
   /**
-   * If $sticky is FALSE, no tableheader.js should be included.
+   * If $sticky is FALSE, `sticky-header` class should not be included.
    */
   public function testThemeTableNoStickyHeaders() {
     $header = ['one', 'two', 'three'];
@@ -58,10 +55,7 @@ public function testThemeTableNoStickyHeaders() {
       '#sticky' => FALSE,
     ];
     $this->render($table);
-    // Make sure tableheader.js was not attached.
-    $tableheader = $this->xpath("//script[contains(@src, 'tableheader.js')]");
-    $this->assertCount(0, $tableheader);
-    $this->assertNoRaw('sticky-enabled');
+    $this->assertNoRaw('sticky-header');
   }
 
   /**
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ClaroTableTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ClaroTableTest.php
deleted file mode 100644
index 4def267e76f18764563bf688ad5781ae51665ea4..0000000000000000000000000000000000000000
--- a/core/tests/Drupal/KernelTests/Core/Theme/ClaroTableTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\KernelTests\Core\Theme;
-
-use Drupal\claro\ClaroPreRender;
-use Drupal\KernelTests\KernelTestBase;
-
-/**
- * Tests Claro specific table functionality.
- *
- * @group Theme
- */
-class ClaroTableTest extends KernelTestBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected static $modules = ['system'];
-
-  /**
-   * Confirm that Claro tables override use of the `sticky-enabled` class.
-   */
-  public function testThemeTableStickyHeaders() {
-    // Enable the Claro theme.
-    \Drupal::service('theme_installer')->install(['claro']);
-    $this->config('system.theme')->set('default', 'claro')->save();
-    $header = ['one', 'two', 'three'];
-    $rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
-    $table = [
-      '#type' => 'table',
-      '#header' => $header,
-      '#rows' => $rows,
-      '#sticky' => TRUE,
-    ];
-    $this->render($table);
-
-    // Confirm that position-sticky is used instead of sticky-enabled.
-    $this->assertNoRaw('sticky-enabled');
-    $this->assertRaw('position-sticky');
-  }
-
-  /**
-   * Confirm Claro prerender callback is not executed for non-array class.
-   */
-  public function testThemeTablePositionStickyPreRender(): void {
-    // Enable the Claro theme.
-    \Drupal::service('theme_installer')->install(['claro']);
-    $this->config('system.theme')->set('default', 'claro')->save();
-    $header = ['one', 'two', 'three'];
-    $rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
-    $table = [
-      '#type' => 'table',
-      '#header' => $header,
-      '#rows' => $rows,
-      '#sticky' => TRUE,
-      '#attributes' => [
-        'class' => 'class',
-      ],
-      '#pre_render' => [
-        [
-          ClaroPreRender::class,
-          'tablePositionSticky',
-        ],
-      ],
-    ];
-
-    $renderedTable = (string) \Drupal::service('renderer')->renderRoot($table);
-
-    // Confirm that table is rendered.
-    $this->assertStringContainsString('class="class"', $renderedTable);
-  }
-
-}
diff --git a/core/themes/claro/claro.theme b/core/themes/claro/claro.theme
index e46b460637070e2c06a21b7fc703748e9f3a13f6..11c0cad0c0b80cf0c4678face1a4488a8685640a 100644
--- a/core/themes/claro/claro.theme
+++ b/core/themes/claro/claro.theme
@@ -295,11 +295,6 @@ function claro_element_info_alter(&$type) {
   if (isset($type['status_messages'])) {
     $type['status_messages']['#pre_render'][] = [ClaroPreRender::class, 'messagePlaceholder'];
   }
-
-  // Add a pre-render to tables to use CSS for sticky positioning.
-  if (isset($type['table'])) {
-    $type['table']['#pre_render'][] = [ClaroPreRender::class, 'tablePositionSticky'];
-  }
 }
 
 /**
diff --git a/core/themes/claro/css/components/tableselect.css b/core/themes/claro/css/components/tableselect.css
index 0baa5b2c29d2e45cf83e446a4d58603e6a5f7189..57d24cc3bf0c45314ece7f2938c0d22bac16f90a 100644
--- a/core/themes/claro/css/components/tableselect.css
+++ b/core/themes/claro/css/components/tableselect.css
@@ -130,9 +130,3 @@ tr.selected td {
     width: auto;
   }
 }
-
-.position-sticky thead {
-  position: sticky;
-  z-index: 500;
-  top: var(--drupal-displace-offset-top, 0);
-}
diff --git a/core/themes/claro/css/components/tableselect.pcss.css b/core/themes/claro/css/components/tableselect.pcss.css
index 6d5bce7b010254c3fe42c1678b7a81734fc0d4fc..531e12b918d490c7c6cb5dc0dcc7db9ae9784c13 100644
--- a/core/themes/claro/css/components/tableselect.pcss.css
+++ b/core/themes/claro/css/components/tableselect.pcss.css
@@ -116,9 +116,3 @@ tr.selected td {
     width: auto;
   }
 }
-
-.position-sticky thead {
-  position: sticky;
-  z-index: 500;
-  top: var(--drupal-displace-offset-top, 0);
-}
diff --git a/core/themes/claro/src/ClaroPreRender.php b/core/themes/claro/src/ClaroPreRender.php
index a47f4ac26e71e4ff4aab3eac5adb98b6810f9141..82f73ac9fa3b986c21438fc81a234a852855bef0 100644
--- a/core/themes/claro/src/ClaroPreRender.php
+++ b/core/themes/claro/src/ClaroPreRender.php
@@ -189,17 +189,6 @@ public static function messagePlaceholder(array $element) {
     return $element;
   }
 
-  /**
-   * Prerender callback for table elements.
-   */
-  public static function tablePositionSticky(array $element) {
-    if (isset($element['#attributes']['class']) && is_array($element['#attributes']['class']) && in_array('sticky-enabled', $element['#attributes']['class'], TRUE)) {
-      unset($element['#attributes']['class'][array_search('sticky-enabled', $element['#attributes']['class'])]);
-      $element['#attributes']['class'][] = 'position-sticky';
-    }
-    return $element;
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -211,7 +200,6 @@ public static function trustedCallbacks() {
       'container',
       'textFormat',
       'messagePlaceholder',
-      'tablePositionSticky',
     ];
   }
 
diff --git a/core/themes/claro/templates/views/views-view-table.html.twig b/core/themes/claro/templates/views/views-view-table.html.twig
index fb9ee0f90888dedd98ef963604718e79eba8d9bc..890205f297399f11e1d952158b46c824bbf9b23a 100644
--- a/core/themes/claro/templates/views/views-view-table.html.twig
+++ b/core/themes/claro/templates/views/views-view-table.html.twig
@@ -37,7 +37,7 @@
     'views-view-table',
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'position-sticky',
+    sticky ? 'position-sticky sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>
diff --git a/core/themes/olivero/templates/views/views-view-table.html.twig b/core/themes/olivero/templates/views/views-view-table.html.twig
index 716ad3723dbd1feda0263daed2434bff6155df00..745f61674d64513428872ad3324ee9111c825ced 100644
--- a/core/themes/olivero/templates/views/views-view-table.html.twig
+++ b/core/themes/olivero/templates/views/views-view-table.html.twig
@@ -38,7 +38,7 @@
     'views-table',
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'sticky-enabled',
+    sticky ? 'sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>
diff --git a/core/themes/stable9/css/core/components/sticky-header.module.css b/core/themes/stable9/css/core/components/sticky-header.module.css
new file mode 100644
index 0000000000000000000000000000000000000000..63571d9fd2612e8c3e75ebd13495e891b25e5e29
--- /dev/null
+++ b/core/themes/stable9/css/core/components/sticky-header.module.css
@@ -0,0 +1,5 @@
+table.sticky-header thead {
+  position: sticky;
+  z-index: 500;
+  top: var(--drupal-displace-offset-top, 0);
+}
diff --git a/core/themes/stable9/css/system/components/sticky-header.module.css b/core/themes/stable9/css/system/components/sticky-header.module.css
deleted file mode 100644
index f6a1b1ec0c627b940216f849506eadbe62fc097a..0000000000000000000000000000000000000000
--- a/core/themes/stable9/css/system/components/sticky-header.module.css
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * @file
- * Table header behavior.
- *
- * @see tableheader.js
- */
-
-table.sticky-header {
-  z-index: 500;
-  top: 0;
-  margin-top: 0;
-  background-color: #fff;
-}
diff --git a/core/themes/stable9/stable9.info.yml b/core/themes/stable9/stable9.info.yml
index dd81e741775d9309e482a5a7bba5e2e4a708d844..6cde0aa03bcefd8ac5ce21b96c78471cb0e692f8 100644
--- a/core/themes/stable9/stable9.info.yml
+++ b/core/themes/stable9/stable9.info.yml
@@ -96,6 +96,11 @@ libraries-override:
         misc/components/tabledrag.module.css: css/core/components/tabledrag.module.css
         misc/components/tree-child.module.css: css/core/components/tree-child.module.css
 
+  core/drupal.tableheader:
+    css:
+      component:
+        misc/components/sticky-header.module.css: css/core/components/sticky-header.module.css
+
   core/drupal.vertical-tabs:
     css:
       component:
@@ -243,7 +248,6 @@ libraries-override:
         css/components/position-container.module.css: css/system/components/position-container.module.css
         css/components/reset-appearance.module.css: css/system/components/reset-appearance.module.css
         css/components/resize.module.css: css/system/components/resize.module.css
-        css/components/sticky-header.module.css: css/system/components/sticky-header.module.css
         css/components/system-status-counter.css: css/system/components/system-status-counter.css
         css/components/system-status-report-counters.css: css/system/components/system-status-report-counters.css
         css/components/system-status-report-general-info.css: css/system/components/system-status-report-general-info.css
diff --git a/core/themes/stable9/templates/views/views-view-table.html.twig b/core/themes/stable9/templates/views/views-view-table.html.twig
index a26eaeba8561a33b8b4f987439902881258699ef..ae106704d8f4baa926501106c7374de5497110d3 100644
--- a/core/themes/stable9/templates/views/views-view-table.html.twig
+++ b/core/themes/stable9/templates/views/views-view-table.html.twig
@@ -35,7 +35,7 @@
   set classes = [
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'sticky-enabled',
+    sticky ? 'sticky-enabled sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>
diff --git a/core/themes/starterkit_theme/templates/views/views-view-table.html.twig b/core/themes/starterkit_theme/templates/views/views-view-table.html.twig
index edc14983da77f19519d5e5fcba6230c281cc634a..042c42b1bc19c66013f618433a71b583a8b6076f 100644
--- a/core/themes/starterkit_theme/templates/views/views-view-table.html.twig
+++ b/core/themes/starterkit_theme/templates/views/views-view-table.html.twig
@@ -37,7 +37,7 @@
     'views-view-table',
     'cols-' ~ header|length,
     responsive ? 'responsive-enabled',
-    sticky ? 'sticky-enabled',
+    sticky ? 'sticky-header',
   ]
 %}
 <table{{ attributes.addClass(classes) }}>