修正 Elementor 導覽選單那一下「閃」:實測穩定解法分享

目錄

文章摘要:

在使用 Elementor 製作網站導覽選單時,常會出現頁面剛載入就閃爍或跳動的情況。選單項目會短暫位移,下拉箭頭稍後才出現,讓整個頁首顯得不穩定。問題並非源自 CSS 排版,而是 Elementor 的 Nav Menu 小工具在初始化時,透過 JavaScript 動態插入箭頭圖示所造成的結果。

當網站啟用了像 WP Rocket、LiteSpeed Cache 等快取外掛時,這種延遲更為明顯,因為外掛改變了 JavaScript 的執行時機,使箭頭在畫面顯示後才被補上。修正方式是讓箭頭在伺服器端(PHP)階段就先輸出到 HTML,並使用 CSS 隱藏 Elementor 原生插入的版本,讓畫面在首次渲染時就保持完整。

這個方法不需要修改 Elementor 核心,也不影響編輯器預覽。只需幾行程式,即可讓導覽列在載入時穩定呈現,不再閃爍或跳動,整體體驗更一致、更專業。

在使用 Elementor 的導覽選單製作網站頁首(Header)時,常會遇到一個令人在意的細節:網頁剛載入時,選單項目會突然「跳動」一下,然後才看到下拉箭頭出現。

這種畫面上的抖動不只是視覺干擾,它其實會讓使用者在第一眼就感覺到畫面的不穩定與不一致。雖然它不構成錯誤,也不會破壞功能,但在體驗上卻足以讓整體介面顯得不夠扎實。

特別是當網站啟用了像 WP Rocket、LiteSpeed Cache 等快取外掛時,問題會變得更加明顯。這些外掛通常會調整 JavaScript 的載入時機,或延後腳本執行,進而放大了這種「畫面先顯示、箭頭後補上」的時間差。

問題根源:下拉箭頭是由 JS 動態插入

Elementor 的 Nav Menu 元件,在前端初始化時會掃描所有有子選單的項目,然後用 JavaScript 動態插入箭頭圖示。這個插入動作通常是在網頁主體載入完成後進行,也就是說——HTML 一開始是不含這些箭頭的。

具體來說,Elementor 是在 element_ready 階段插入 <span class="sub-arrow">,這動作不大,但正好會觸發瀏覽器對 DOM 結構的重新排版(reflow)與重繪(repaint)。因此你會看到畫面明明已經排好,卻因為多了一個元素導致整列選單發生閃爍或跳位現象。

這種「先載入再插入」的策略也會與 CSS 的排版邏輯產生衝突,尤其你若使用的是 flexbox、inline-block 排版方式,或設計上使用了自訂的間距、字級、行高等控制,這個箭頭插入的延遲就會非常明顯,甚至影響整體版面穩定性。

解決方向:讓箭頭預先存在、並隱藏插入的箭頭

既然問題在於JS插入的箭頭出現得太晚,我們就反過來處理:讓箭頭隱藏起來。

更精確的說法是:

  1. 讓 Elementor 的箭頭在伺服器端(PHP)渲染階段就寫入 HTML。
  2. 同時隱藏JS插入的箭頭,讓視覺上不會因為晚插入的箭頭產生偏移閃爍。

這樣做可以確保兩件事:

  • 畫面第一次載入時,箭頭就已經在 DOM 結構中,就算因為新增節點而重繪,也早一先一步使用css將其隱藏。
  • Elementor 的其他功能(例如子選單展開收合)依然可以正常使用,因為我們只是隱藏了原本閃爍的箭頭,並沒有移除整體互動行為。

程式碼實作

這段程式碼可以直接放進主題的 functions.php,或打包成自訂外掛使用。

不過更建議的做法是,建立一個子佈景主題(Child Theme),將這類客製化功能集中管理。這樣不僅能讓代碼結構更清晰,也能避免日後主題更新時自訂修改被覆蓋或消失的情況。

/**
 * 修復 Elementor 導航選單(Nav Menu)下拉指標閃爍問題
 * ------------------------------------------------------------
 * - 攔截 Nav Menu widget 的 HTML 輸出
 * - 插入並修正子選單箭頭圖示位置與樣式
 * - 修正 SVG 顏色繼承、避免閃爍或重疊
 * - 僅前台生效(不影響後台與 Elementor 編輯器)
 */

add_filter('elementor/widget/render_content', function ($content, $widget) {
    if (is_admin() || (defined('ELEMENTOR_EDITOR') && ELEMENTOR_EDITOR)) {
        return $content;
    }
    if (!did_action('elementor/loaded')) {
        return $content;
    }
    if (!class_exists('\Elementor\Icons_Manager')) {
        return $content;
    }
    if ('nav-menu' !== $widget->get_name()) {
        return $content;
    }
    if (strpos($content, 'menu-item-has-children') === false) {
        return $content;
    }

    $icon = $widget->get_settings_for_display('submenu_icon');
    $icon_html = '';

    if (!empty($icon)) {
        if (is_array($icon)) {
            ob_start();
            \Elementor\Icons_Manager::render_icon($icon, ['aria-hidden' => 'true']);
            $rendered = ob_get_clean();

            $rendered = preg_replace('/fill="[^"]*"/i', '', $rendered);
            $rendered = preg_replace('/<svg(.*?)>/i', '<svg$1 fill="currentColor">', $rendered);

            $icon_html = '<span class="sub-arrow sub-arrow-icon">' . $rendered . '</span>';
        } elseif (is_string($icon)) {
            $icon_html = '<span class="sub-arrow sub-arrow-icon"><i class="' . esc_attr($icon) . '"></i></span>';
        }
    }

    if ($icon_html) {
        $content = preg_replace(
            '#(<li[^>]*class="[^"]*\bmenu-item-has-children\b[^"]*"[^>]*>\s*<a[^>]*?>)(.*?)(</a>)#si',
            '$1$2 ' . $icon_html . '$3',
            $content
        );
    }

    static $css_printed = false;
    if (!$css_printed) {
        add_action('wp_footer', function () {
            echo '<style id="pongo-navmenu-icon-css">
                .elementor-nav-menu .sub-arrow { display: none !important; }
                .elementor-nav-menu .sub-arrow.sub-arrow-icon {
                    display: inline-block !important;
                    vertical-align: middle;
                    color: inherit !important;
                    fill: currentColor !important;
                }
                .elementor-nav-menu .menu-item-has-children:hover .sub-arrow-icon,
                .elementor-nav-menu .menu-item-has-children:focus-within .sub-arrow-icon {
                    color: currentColor !important;
                    fill: currentColor !important;
                }
            </style>';
        });
        $css_printed = true;
    }

    return $content;
}, 10, 2);Code language: PHP (php)

完成上述修改後,網頁載入的穩定性會有明顯改善。最直接的體感是:導覽選單不再抖動,箭頭從一開始就存在於版面中,整體畫面不再因 DOM 被修改而重新排版,也不會因箭頭晚一步出現而產生錯位、重疊、或 hover 效果異常的問題。

此外,這個方法是使用 Elementor 官方所提供的過濾器來增加輸出一個箭頭,不修改 Elementor 核心、不破壞編輯器預覽,對未來的更新也保有良好相容性。

結語

Elementor 之所以選擇在載入後再插入箭頭圖示,是出於元件化架構與樣式彈性的考量。然而在實際運行中,這種設計卻為導覽列帶來了意料之外的副作用——畫面閃爍、位移、整體穩定性下降。

如果你也遇到這個情況,其實不用再懷疑是 CSS 排版出了問題,也不必為了避開它而關閉快取或調整 JS 延遲策略。只要幾行簡潔的程式,就能讓導覽列在載入時維持穩定、不跳、不抖,呈現出應有的設計品質與細節一致性。

常見問題

我在使用 Elementor 製作網站導覽選單時,網頁剛載入會閃一下或跳動,這是什麼原因?

Elementor 的導覽選單(Nav Menu)在前端初始化階段,會透過 JavaScript 動態插入下拉箭頭圖示。畫面第一次載入時 HTML 裡並沒有箭頭,等到 JS 執行後才新增節點,瀏覽器因此重新排版(reflow)與重繪(repaint),就造成肉眼可見的閃爍與跳動。

Elementor 網站導覽選單抖動是 CSS 或主題排版造成的嗎?

不是。這個現象與主題或 CSS 無關,即使使用 Elementor 官方主題也可能出現。根本原因在於 Elementor 的導覽選單初始化機制,而非樣式排版問題。

為什麼啟用快取外掛(例如 WP Rocket、LiteSpeed Cache)後,Elementor 網站導覽選單的閃爍會更明顯?

快取外掛會改變或延遲 JavaScript 的執行時機,使得箭頭插入的時間點更晚。當畫面已經渲染完成、JS 才動態修改 DOM 時,瀏覽器就會再重新排版,閃爍與位移的現象因此更明顯。

修正 Elementor 網站導覽選單閃爍需要修改 Elementor 核心程式嗎?

不需要。建議使用 PHP 在伺服器端預先輸出箭頭圖示,並以 CSS 隱藏 Elementor 原生版本。這樣既能避免畫面重排,又不會影響 Elementor 核心與後續更新。

修正後會不會影響 Elementor 網站導覽選單的下拉展開功能?

不會。這個修正只針對箭頭顯示的時機與樣式進行調整,不會改變導覽列的互動邏輯。子選單開合、hover 效果等功能都能正常運作。

如果主題更新,這段修正代碼會不會消失?應該怎麼管理?

建議建立一個子佈景主題(Child Theme),將這類自訂代碼統一放在子主題中管理。這樣可以避免主題更新時原始檔被覆蓋,讓修正能長期維持並確保安全。

您可能感興趣
正在經營電商網站的你,是不是正在煩惱該如何提升網站營收呢?隨著網購成為人們生活中不可或缺的一部分,各種類型的網路行銷手法蓬勃發展,不論是SEO優化、社群行銷,還是KOL行銷都可以快速幫助品牌佈局網路行銷渠道,帶來不錯的轉換效果。這一篇文章將會帶大家一起了解影響網站營收的電商經營公式,還有常見的行銷策略,以及各種電商經營的注意事項。電商銷售的基本公式提升網站營收必備的電商公式:流量×轉換率×客單價=...
第一次設計網頁時,許多使用者常會面臨相同疑問:應該使用哪種架站方式、需要多少預算、網站由哪些技術構成、內容該如何準備、製作流程會遇到什麼問題等等。本篇文章以清楚方式整理網站製作的核心概念,協助首次建立網站的使用者快速掌握必要知識,減少不必要的摸索。什麼是網頁設計?網頁設計是將視覺、內容與技術整合,打造一個能被使用者順暢瀏覽的網站。它不只是美化畫面,而是透過版面配置、操作流程、資訊層級與程式技術等多...
很多人把 SEO想成「跟演算法鬥智」,所以一開始就會焦慮,怕自己不懂技術、不會寫程式、也怕做了半天沒成果。其實 SEO更像你在把網站整理成一個「好找、好讀、好信任、也好行動」的地方。你把路鋪順了,搜尋引擎才敢把人帶過來;人來了覺得舒服,才會停、才會看、才會問。這篇會把 SEO拆成你真的做得下去的順序,先讓你知道該從哪裡下手,再讓你知道哪些地方最容易白做,最後把追蹤節奏與內容寫法也補齊,讓它不像一篇觀念文,而是一篇可...
為什麼網頁設計在今天比以往更重要?在數位時代,網站早已不只是輔助工具,而是品牌、企業甚至個人的「第一門面」。無論是建立信任、推廣服務,或單純分享資訊,使用者對網站的第一印象,往往決定了他是否願意繼續深入了解。短短幾秒鐘的瀏覽,就足以影響訪客的後續行為,因此網站設計的重要性比以往更加凸顯。影響網站成效的另一個關鍵,是行動裝置的普及與搜尋引擎演算法的持續演進。如今,大部分使用者都是透過手機搜尋與瀏覽,...
不管你選擇自行架設或是委託給網頁設計公司,網站架設從主機伺服器、網域名稱、網頁版面設計、網站視覺呈現,再到後續網站經營的追蹤工具、行銷推廣策略,當中有大量的選擇仍需要你自行決定,就算是網頁設計公司也只能站在專業的角度提供建置協助。因此,在被伺服器與網頁設計公司的方案差異弄得心煩意亂前,也許你可以先參考一下這篇文章所提到的配置數據與選擇技巧,它們可以幫助你避開沒必要糾結的選擇,加速形象網站的建置流程...