text-decoration: none!important;としないとWordPressのhoverの下線が消えない原因と対処法

原因はほぼ「CSSの詳細度」と「WordPress側が後から出しているグローバルスタイル」の競合です。実際のセレクタ構造に沿って整理します。

結論

WordPressのブロックテーマやサイトエディターでは、リンク装飾が単純な

a {
text-decoration: none;
}

だけでは上書きできない形で出力されていることがあります。

特に、WordPress側が次のようなセレクタを自動生成している場合があります。

:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):hover)

そのため、こちらも同じような形で指定しないと、対象が合わなかったり、優先順位で負けたりします。


なぜ a {} だけでは効かないのか

例えば、こちらの指定はかなり弱いです。

a:where(:not(.wp-element-button)) {
text-decoration: none;
}

これは「ボタン以外のリンク全体」に効く指定です。

ただし、WordPress側で次のように「投稿タイトルのリンク」「投稿日リンク」「カテゴリーリンク」など、ブロックごとに細かく指定されていると、そちらが優先されることがあります。

.wp-block-post-title a:hover
.wp-block-post-date a:hover
.is-style-post-terms-1--3 a:hover

つまり、

a

よりも、

.wp-block-post-title a:hover

のほうが「どこのリンクか」が具体的なので強いです。

CSSは、同じプロパティがぶつかった場合、より具体的な指定が優先されます。これをCSSの詳細度といいます。MDNでも、詳細度は競合するCSS宣言のうち、どれを適用するかを決める仕組みとして説明されています。


:root :where(...) はWordPressのグローバルスタイル対策

WordPressのブロックテーマでは、theme.json やサイトエディターの「スタイル」設定からCSSが自動生成されます。

WordPress 6.6以降では、ブロックスタイルやグローバルスタイルのCSS詳細度が原則 0-1-0 程度に調整されています。そこで使われる代表的な形が、

:root :where(...)

です。WordPress公式の開発ノートでも、theme.json やグローバルスタイルから出力されるブロックスタイルは 0-1-0 の詳細度に制限されると説明されています。

ポイントは、:where() の中身は詳細度に加算されないことです。

:where(.wp-block-post-title a:hover)

この中にクラスやhoverが入っていても、:where() 自体の詳細度はゼロ扱いです。MDNでも、:where() は常に詳細度 0-0-0 になると説明されています。

しかし、外側にある

:root

は擬似クラスなので、詳細度が加算されます。

そのため、

:root :where(.wp-block-post-title a:hover)

は、見た目は長いですが、詳細度としてはだいたい

0-1-0

になります。

WordPressはこの形で「弱すぎず、強すぎないCSS」を出しているわけです。


なぜ !important が必要になるのか

今回のコードでは、さらに

text-decoration: none!important;

を使っています。

これは、WordPressやテーマ側で

text-decoration: underline;

が後から読み込まれている、または同じくらい強いセレクタで指定されている可能性があるためです。

CSSは基本的に次の順で勝敗が決まります。

  1. !important があるか
  2. 詳細度が高いか
  3. 後から読み込まれているか

つまり、こちらが

a {
text-decoration: none;
}

と書いても、後ろでWordPressやテーマが

:root :where(.wp-block-post-title a:hover) {
text-decoration: underline;
}

を出していれば、そちらが勝ちます。

だから、同じ対象に対して

:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):hover) {
text-decoration: none!important;
}

のように書くと効く、ということです。


今回のコードの意味

投稿タイトルのホバー下線を消す

:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):hover) {
text-decoration: none!important;
}

投稿タイトルブロック内のリンクにマウスを乗せたとき、下線を消しています。


カテゴリーやタグのホバー下線を消して背景色を付ける

:root :where(.is-style-post-terms-1--3 a:where(:not(.wp-element-button)):hover) {
text-decoration: none!important;
background: #eeeeee;
}

投稿カテゴリーやタグなどのリンクにマウスを乗せたとき、下線を消して、背景色を薄いグレーにしています。


通常リンクの下線を消す

a:where(:not(.wp-element-button)) {
text-decoration: none;
}

ボタン以外の通常リンクの下線を消しています。

ただし、これは通常状態には効いても、:hover には別指定があるため、ホバー時には負ける場合があります。


投稿日リンクのホバー下線を消す

:root :where(.wp-block-post-date a:where(:not(.wp-element-button)):hover) {
text-decoration: none!important;
}

投稿日ブロック内のリンクにマウスを乗せたとき、下線を消しています。


より整理するとこう書けます

同じ処理が多いので、まとめるなら次のようにできます。

:root :where(
.wp-block-post-title a:where(:not(.wp-element-button)):hover,
.wp-block-post-date a:where(:not(.wp-element-button)):hover,
.is-style-post-terms-1--3 a:where(:not(.wp-element-button)):hover
) {
text-decoration: none !important;
}:root :where(.is-style-post-terms-1--3 a:where(:not(.wp-element-button)):hover) {
background: #eeeeee;
}a:where(:not(.wp-element-button)) {
text-decoration: none;
}

ただし、古い環境や一部のCSS圧縮プラグインでセレクタリスト内の:where()が崩れる可能性がある場合は、今のように個別に書いたほうが安全です。


実務上の考え方

WordPressのブロックテーマでは、リンク装飾を消したい場合、単純に

a {
text-decoration: none;
}

では弱いです。

特に以下のようなブロックは、個別指定が必要になりやすいです。

.wp-block-post-title
.wp-block-post-date
.wp-block-post-terms
.wp-block-navigation
.wp-block-query

今回のように「投稿タイトル」「投稿日」「タームリンク」など、実際に下線が出ているブロックを狙って指定するのが正解です。


まとめ

この書き方でないと効かない理由は、WordPress側がブロックごとに自動生成したCSSを出しているためです。

特にブロックテーマでは、theme.json やサイトエディターの設定から

:root :where(...)

形式のCSSが出力されることがあります。

そのため、こちらも同じレベルで対象を指定し、必要に応じて !important を使わないと、WordPress側のリンク装飾に負けます。

今回のコードは、WordPressのブロックテーマ環境ではかなり現実的な書き方です。
ただし、!important を増やしすぎると後から修正しづらくなるため、「投稿タイトル」「投稿日」「タームリンク」など、必要な場所だけに限定して使うのが安全です。