Skip to content

Instantly share code, notes, and snippets.

@unicore32
Last active April 6, 2026 14:25
Show Gist options
  • Select an option

  • Save unicore32/c49a8da31b0aa6c4f0ee6d56b9c0eaab to your computer and use it in GitHub Desktop.

Select an option

Save unicore32/c49a8da31b0aa6c4f0ee6d56b9c0eaab to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name X - 不要UIを非表示 + レイアウト最適化
// @namespace https://64g806.me
// @version 3
// @description 不要UI削除 + ホーム画面レイアウト最適化
// @author 64G806
// @match https://x.com/*
// @match https://twitter.com/*
// @grant GM_addStyle
// ==/UserScript==
(function () {
'use strict';
// ╔══════════════════════════════════════════════════════╗
// ║ 設定スイッチ(true = 有効 / false = 無効) ║
// ╚══════════════════════════════════════════════════════╝
const CONFIG = {
// ── レイアウト ──────────────────────────────────────
HIDE_SIDEBAR : true,
HIDE_FOOTER_LINKS : true,
SEARCH_BOX_IN_TABBAR : true,
// ── ポスト ──────────────────────────────────────────
HIDE_POST_ACTIONS : true, // 返信・リポスト・いいね・ビュー数を非表示(ブックマークは残す)
// ── ホーム ──────────────────────────────────────────
HIDE_TAB_OSUSUME : true,
REDIRECT_HOME_TO_PROFILE: true,
MY_SCREEN_NAME : '64G806',
// ── サイドバーウィジェット ──────────────────────────
HIDE_PREMIUM_WIDGET : true,
HIDE_FOLLOW_WIDGET : true,
// ── タイムライン ────────────────────────────────────
HIDE_WHATS_HAPPENING : true,
HIDE_MORE_POSTS : true, // 「もっと見つける」を非表示
HIDE_FOLLOW_SUGGESTIONS: true, // タイムライン内「おすすめユーザー」提案を非表示
// ── 左メニュー ──────────────────────────────────────
// 残す: Xロゴ・プロフィール・もっと見るボタン・ポストする・アカウント選択
// 消す: ホーム・話題の検索・通知・DM・Grok・ブックマーク・クリエイタースタジオ・プレミアム
HIDE_NAV_LINKS : true,
// もっと見るメニュー内で消す項目(リスト・設定とプライバシーは残す)
HIDE_MORE_MENU_ITEMS : true,
// ── /explore ────────────────────────────────────────
HIDE_EXPLORE_CONTENTS : true,
};
// ════════════════════════════════════════════════════════
// CSS
// ════════════════════════════════════════════════════════
GM_addStyle(`
${CONFIG.HIDE_SIDEBAR ? '[data-testid="sidebarColumn"] { display: none !important; }' : ''}
${CONFIG.HIDE_FOOTER_LINKS ? 'nav[aria-label="フッター"], nav[aria-label="Footer"] { display: none !important; }' : ''}
${CONFIG.HIDE_POST_ACTIONS ? `
[role="group"].r-1kbdv8c { display: none !important; }
[role="group"].r-1kbdv8c div:has([data-testid="bookmark"]) { display: flex !important; }
` : ''}
${CONFIG.SEARCH_BOX_IN_TABBAR ? `
[data-testid="ScrollSnap-prevButtonWrapper"],
[data-testid="ScrollSnap-nextButtonWrapper"] { display: none !important; }
[data-testid="ScrollSnap-SwipeableList"] {
flex: 0 0 auto !important; width: auto !important; overflow: visible !important;
}
#ux-tab-row { display: flex !important; align-items: center !important; width: 100% !important; }
#ux-search-wrapper { flex: 1 1 auto; display: flex; align-items: center; padding: 4px 16px; min-width: 0; }
#ux-search-inner {
display: flex; align-items: center; gap: 8px; width: 100%;
border-radius: 9999px; padding: 7px 16px;
border: 1px solid transparent; transition: border-color 0.15s;
}
#ux-search-inner:focus-within { border-color: rgb(29, 155, 240); }
#ux-search-icon { width: 18px; height: 18px; flex-shrink: 0; opacity: 0.45; }
#ux-search-input {
border: none; background: transparent; outline: none;
font-size: 15px; width: 100%; color: inherit; caret-color: rgb(29, 155, 240);
}
#ux-search-input::placeholder { opacity: 0.45; }
` : ''}
`);
// ════════════════════════════════════════════════════════
// 定数
// ════════════════════════════════════════════════════════
// nav内で消すリンクの aria-label(残すもの以外)
const NAV_HIDE_LABELS = [
'ホーム', 'Home',
'調べたいものを検索', 'Search and explore', 'Explore',
'通知', 'Notifications',
'ダイレクトメッセージ', 'Direct Messages',
'Grok',
'ブックマーク', 'Bookmarks',
'クリエイタースタジオ', 'Creator Studio',
'プレミアム', 'Premium',
];
// もっと見るメニュー内で消す項目の aria-label(リスト・設定とプライバシーは残す)
const MORE_MENU_HIDE_LABELS = [
'トピック', 'Topics',
'ブックマーク', 'Bookmarks',
'Spaces',
'マネタイズ', 'Monetization',
'プロフェッショナルツール', 'Professional Tools',
'キーボードショートカット', 'Keyboard shortcuts',
'表示', 'Display',
];
// タイムライン内で「以降を消す」キーワード(もっと見つける)
const MORE_POSTS_KW = [
'もっと見つける', 'More posts like this',
];
// タイムライン内で「そのセルだけ消す」キーワード(おすすめユーザー提案)
const FOLLOW_SUGGESTION_KW = [
'おすすめユーザー', 'Who to follow', 'You might like',
];
// ════════════════════════════════════════════════════════
// ヘルパー
// ════════════════════════════════════════════════════════
function getWrapper(el, classFragment, maxDepth = 8) {
let cur = el.parentElement;
for (let i = 0; i < maxDepth && cur; i++) {
if ((cur.className || '').includes(classFragment)) return cur;
cur = cur.parentElement;
}
return el;
}
// ════════════════════════════════════════════════════════
// 各処理
// ════════════════════════════════════════════════════════
function maybeRedirectHome() {
if (!CONFIG.REDIRECT_HOME_TO_PROFILE) return;
if (location.pathname === '/home') location.replace('/' + CONFIG.MY_SCREEN_NAME);
}
function hideNavLinks() {
if (!CONFIG.HIDE_NAV_LINKS) return;
const nav = document.querySelector('nav[aria-label="メインメニュー"]');
if (!nav) return;
NAV_HIDE_LABELS.forEach((label) => {
nav.querySelectorAll('a[aria-label="' + label + '"]').forEach((el) => {
el.style.display = 'none';
});
});
}
function hideMoreMenuItems() {
if (!CONFIG.HIDE_MORE_MENU_ITEMS) return;
// もっと見るメニューは role="menu" のポップアップとして動的に追加される
document.querySelectorAll('[role="menu"] a[role="menuitem"], [role="menu"] [role="menuitem"]').forEach((item) => {
const label = item.getAttribute('aria-label') || item.textContent.trim();
if (MORE_MENU_HIDE_LABELS.some((kw) => label.includes(kw))) {
item.style.display = 'none';
}
});
}
function hideExploreContents() {
if (!CONFIG.HIDE_EXPLORE_CONTENTS) return;
if (!location.pathname.startsWith('/explore') && !location.pathname.startsWith('/search')) return;
const swipeable = document.querySelector('[data-testid="ScrollSnap-SwipeableList"]');
if (swipeable) swipeable.style.display = 'none';
document.querySelectorAll('section[aria-labelledby]').forEach((section) => {
const h1 = section.querySelector('h1');
if (h1 && (h1.textContent.includes('話題を検索') || h1.textContent.includes('Search'))) {
const tl = section.querySelector('[aria-label*="タイムライン"]')
|| section.querySelector('[aria-label*="Timeline"]');
if (tl) tl.style.display = 'none';
h1.style.display = 'none';
}
});
}
function mountSearchBox() {
if (!CONFIG.SEARCH_BOX_IN_TABBAR) return;
if (document.getElementById('ux-search-wrapper')) return;
const swipeable = document.querySelector('[data-testid="ScrollSnap-SwipeableList"]');
if (!swipeable) return;
const rowDiv = swipeable.parentElement;
if (!rowDiv) return;
rowDiv.id = 'ux-tab-row';
const wrapper = document.createElement('div');
wrapper.id = 'ux-search-wrapper';
const inner = document.createElement('div');
inner.id = 'ux-search-inner';
const svgNS = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(svgNS, 'svg');
svg.id = 'ux-search-icon';
svg.setAttribute('viewBox', '0 0 24 24');
svg.setAttribute('fill', 'none');
svg.setAttribute('stroke', 'currentColor');
svg.setAttribute('stroke-width', '2');
svg.setAttribute('stroke-linecap', 'round');
svg.setAttribute('stroke-linejoin', 'round');
const circle = document.createElementNS(svgNS, 'circle');
circle.setAttribute('cx', '11'); circle.setAttribute('cy', '11'); circle.setAttribute('r', '8');
const line = document.createElementNS(svgNS, 'line');
line.setAttribute('x1', '21'); line.setAttribute('y1', '21');
line.setAttribute('x2', '16.65'); line.setAttribute('y2', '16.65');
svg.appendChild(circle);
svg.appendChild(line);
const input = document.createElement('input');
input.id = 'ux-search-input';
input.type = 'text';
input.placeholder = '検索';
input.autocomplete = 'off';
input.spellcheck = false;
input.addEventListener('keydown', (e) => {
if (e.key !== 'Enter') return;
const q = e.target.value.trim();
if (!q) return;
e.target.value = '';
e.target.blur();
location.href = 'https://x.com/search?q=' + encodeURIComponent(q) + '&src=typed_query&f=live';
});
inner.appendChild(svg);
inner.appendChild(input);
wrapper.appendChild(inner);
rowDiv.appendChild(wrapper);
}
function hideAll() {
maybeRedirectHome();
// サイドバーウィジェット
if (CONFIG.HIDE_PREMIUM_WIDGET) {
['プレミアムにサブスクライブ', 'Subscribe to Premium'].forEach((label) => {
document.querySelectorAll('aside[aria-label="' + label + '"]').forEach((el) => {
getWrapper(el, 'r-14lw9ot').style.display = 'none';
});
});
}
if (CONFIG.HIDE_FOLLOW_WIDGET) {
['おすすめユーザー', 'Who to follow'].forEach((label) => {
document.querySelectorAll('aside[aria-label="' + label + '"]').forEach((el) => {
getWrapper(el, 'r-14lw9ot').style.display = 'none';
});
});
}
// 「いまを見つけよう」
if (CONFIG.HIDE_WHATS_HAPPENING) {
const KW = ['いまを見つけよう', '「いま」を見つけよう', "What's happening", 'Trending now'];
document.querySelectorAll('section[aria-labelledby]').forEach((section) => {
const h2 = section.querySelector('h2');
if (h2 && KW.some((kw) => h2.textContent.includes(kw)))
getWrapper(section, 'r-14lw9ot').style.display = 'none';
});
}
// タイムライン内の cellInnerDiv を走査
document.querySelectorAll('[data-testid="cellInnerDiv"]').forEach((cell) => {
const h2 = cell.querySelector('h2[role="heading"]');
if (!h2) return;
const text = h2.textContent;
// 「もっと見つける」→ そのセル以降を全消し
if (CONFIG.HIDE_MORE_POSTS && MORE_POSTS_KW.some((kw) => text.includes(kw))) {
let sib = cell;
while (sib) { sib.style.display = 'none'; sib = sib.nextElementSibling; }
return;
}
// 「おすすめユーザー」提案 → h2セル+直後のUserCellたちのみ消す(以降のポストは残す)
if (CONFIG.HIDE_FOLLOW_SUGGESTIONS && FOLLOW_SUGGESTION_KW.some((kw) => text.includes(kw))) {
// h2のセル自体を消す
cell.style.display = 'none';
// 直後の兄弟で UserCell を含むものを消す(UserCellがなくなったら停止)
let sib = cell.nextElementSibling;
while (sib) {
if (sib.querySelector('[data-testid="UserCell"]')) {
sib.style.display = 'none';
sib = sib.nextElementSibling;
} else {
break;
}
}
}
});
// 「おすすめ」タブ
if (CONFIG.HIDE_TAB_OSUSUME) {
document.querySelectorAll('[data-testid="ScrollSnap-List"] [role="tab"]').forEach((tab) => {
const text = tab.textContent.trim();
if (text.startsWith('おすすめ') || text.startsWith('For you'))
(tab.closest('[role="presentation"]') || tab).style.display = 'none';
});
}
hideExploreContents();
hideNavLinks();
hideMoreMenuItems();
if (location.pathname === '/home') mountSearchBox();
}
hideAll();
const observer = new MutationObserver(() => hideAll());
observer.observe(document.body, { childList: true, subtree: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment