|CSS|Fix Hover Font Weight & Spacing Changes

Fix Hover Font Weight & Spacing Changes

當設計 hover 效果時想變更文字粗細或是字距,文字通常會導致佈局發生一些變化。這是因為粗體字和字距變得比原空間更大所導致。以下將示範如何解決文字粗細、字距導致空間改變的問題:

在文字標籤 .tt-block 上設置自定義屬性 data-*,屬性名稱可自訂,並將其值設為與標籤內顯示的文字內容相同。

html


在文字標籤的偽元素 .tt-block::before 上,使用 content 屬性來取得 .tt-block 的 data-tt 值,並設定與 .tt-block:hover 相同的 font-weight 和 letter-spacing,用來撐開標籤的空間。接著,為 .tt-block::before 設定 pointer-events: none、display: block 和 height: 0,達到隱藏效果。

以上做法是用偽元素來預留空間,將 hover 狀態的 font-weight 和 letter-spacing 設定到偽元素中。即使在 hover 時文字外觀發生變化,整體布局空間仍保持不變,避免因字體調整導致跳動。

css
.tt-block{ font-weight: 300;
           color: rgba(0, 0, 0, 1);
           letter-spacing: 0;
           transition: color 0.5s, letter-spacing 0.5s;
          }

.btn:hover .tt-block{ font-weight: 700;
                      color: rgba(255, 255, 255, 1);
                      letter-spacing: var(--tt-spacing);
                    }
  
/* 偽元素撐開 */
.fix .tt-block::before{ content: attr(data-tt); /* 用 content 屬性獲取 data-tt 的值 */
                        font-weight: 700; /* 設定同 hover 時的字體粗細 */
                        letter-spacing: var(--tt-spacing); /* 設定同 hover 時的字距 */
                        pointer-events: none; /* 鼠標觸發不到它 */
                        display: block; /* 讓 ::before 往下空間擠 */
                        height: 0; /* 隱藏用 */
                      }   
:root{ --tt-spacing: min(0.12vw, 0.2rem);}                      

如果只有單純做文字粗細變化,可改用 text-shadow 的疊加做出文字粗細變化效果,也可達到不會改變文字空間。

css
.font-weight .tt-block{ transition: color 0.5s, text-shadow 0.5s;
                        text-shadow: 0 0 0 rgba(255, 255, 255, 0), 
                                     0 0 0 rgba(255, 255, 255, 0),
                                     0 0 0 rgba(255, 255, 255, 0),
                                     0 0 0 rgba(255, 255, 255, 0),
                                     0 0 1px rgba(255, 255, 255, 0);
                      }
.font-weight .btn:hover .tt-block{ text-shadow: 0 0 0.8px rgba(255, 255, 255, 1), 
                                               0 0 0.8px rgba(255, 255, 255, 1),
                                               0 0 0.8px rgba(255, 255, 255, 1),
                                               0 0 0.8px rgba(255, 255, 255, 1),
                                               0 0 0.8px rgba(255, 255, 255, 0.5);
                                   }