Gemini 聊天页面轻量美化:更舒服的排版 + 发光代码块 & 表格(保持原生布局),主题自适应 + 可访问性增强。
// ==UserScript==
// @name Gemini Singularity (V5.7 Lite++)
// @namespace http://tampermonkey.net/
// @version 5.7
// @description Gemini 聊天页面轻量美化:更舒服的排版 + 发光代码块 & 表格(保持原生布局),主题自适应 + 可访问性增强。
// @author GQLJ + GPT
// @match https://gemini.google.com/*
// @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+CiAgPGRlZnM+CiAgICA8bGluZWFyR3JhZGllbnQgaWQ9ImJnIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMxMTE4MjciLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDIwNjE3Ii8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPHJhZGlhbEdyYWRpZW50IGlkPSJnbG93IiBjeD0iNTAlIiBjeT0iMCUiIHI9IjcwJSI+CiAgICAgIDxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiM2MGE1ZmEiIHN0b3Atb3BhY2l0eT0iMC45Ii8+CiAgICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzFkNGVkOCIgc3RvcC1vcGFjaXR5PSIwLjAiLz4KICAgIDwvcmFkaWFsR3JhZGllbnQ+CiAgPC9kZWZzPgogIDxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSI1NiIgaGVpZ2h0PSI1NiIgcng9IjE0IiBmaWxsPSJ1cmwoI2JnKSIvPgogIDxjaXJjbGUgY3g9IjMyIiBjeT0iMTgiIHI9IjE4IiBmaWxsPSJ1cmwoI2dsb3cpIiAvPgogIDx0ZXh0IHg9IjUwJSIgeT0iNTYlIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSIjZTVlN2ViIiBmb250LWZhbWlseT0ic3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsICdTZWdvZSBVSScsIHNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMzAiIGZvbnQtd2VpZ2h0PSI3MDAiPgogICAgRwogIDwvdGV4dD4KPC9zdmc+
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @run-at document-start
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const DEBUG = false;
if (window.top !== window.self) return;
// =========================
// 可配置项(菜单开关)
// =========================
const DEFAULTS = {
maxWidth: 980,
fontSize: 17,
fontSizeMobile: 16,
enableRemoteFonts: true,
enableGlow: true,
enableEntryAnim: true,
justifyText: true,
roundImages: true,
tableMobileScroll: true,
};
const cfg = {
maxWidth: Number(GM_getValue('maxWidth', DEFAULTS.maxWidth)),
fontSize: Number(GM_getValue('fontSize', DEFAULTS.fontSize)),
fontSizeMobile: Number(GM_getValue('fontSizeMobile', DEFAULTS.fontSizeMobile)),
enableRemoteFonts: !!GM_getValue('enableRemoteFonts', DEFAULTS.enableRemoteFonts),
enableGlow: !!GM_getValue('enableGlow', DEFAULTS.enableGlow),
enableEntryAnim: !!GM_getValue('enableEntryAnim', DEFAULTS.enableEntryAnim),
justifyText: !!GM_getValue('justifyText', DEFAULTS.justifyText),
roundImages: !!GM_getValue('roundImages', DEFAULTS.roundImages),
tableMobileScroll: !!GM_getValue('tableMobileScroll', DEFAULTS.tableMobileScroll),
};
function toggle(key) {
GM_setValue(key, !cfg[key]);
window.location.reload();
}
try {
GM_registerMenuCommand(`远程字体: ${cfg.enableRemoteFonts ? '开' : '关'}`, () => toggle('enableRemoteFonts'));
GM_registerMenuCommand(`发光效果: ${cfg.enableGlow ? '开' : '关'}`, () => toggle('enableGlow'));
GM_registerMenuCommand(`入场动画: ${cfg.enableEntryAnim ? '开' : '关'}`, () => toggle('enableEntryAnim'));
GM_registerMenuCommand(`段落两端对齐: ${cfg.justifyText ? '开' : '关'}`, () => toggle('justifyText'));
GM_registerMenuCommand(`图片圆角: ${cfg.roundImages ? '开' : '关'}`, () => toggle('roundImages'));
GM_registerMenuCommand(`移动端表格横滑: ${cfg.tableMobileScroll ? '开' : '关'}`, () => toggle('tableMobileScroll'));
} catch (_) {}
// =========================
// 字体加载(可关)— 用 link 替代 @import
// =========================
function injectFonts() {
if (!cfg.enableRemoteFonts) return;
const head = document.head || document.documentElement;
const pre1 = document.createElement('link');
pre1.rel = 'preconnect';
pre1.href = 'https://fonts.googleapis.com';
head.appendChild(pre1);
const pre2 = document.createElement('link');
pre2.rel = 'preconnect';
pre2.href = 'https://fonts.gstatic.com';
pre2.crossOrigin = 'anonymous';
head.appendChild(pre2);
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href =
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;750&family=JetBrains+Mono:wght@400;500;600&display=swap';
head.appendChild(link);
}
injectFonts();
// =========================
// 阴影强度(可关)
// =========================
const glowShadows = cfg.enableGlow
? `
box-shadow:
0 0 0 1px rgba(255,255,255,0.04),
0 0 22px var(--singularity-glow-soft),
0 22px 55px -18px rgba(0,0,0,0.7) !important;
`
: `
box-shadow:
0 0 0 1px rgba(255,255,255,0.04),
0 18px 45px -22px rgba(0,0,0,0.55) !important;
`;
const glowShadowsHover = cfg.enableGlow
? `
box-shadow:
0 0 0 1px var(--singularity-glow-strong),
0 0 40px var(--singularity-glow-strong),
0 25px 65px -20px rgba(0,0,0,0.85) !important;
`
: `
box-shadow:
0 0 0 1px rgba(255,255,255,0.06),
0 22px 55px -24px rgba(0,0,0,0.75) !important;
`;
const tableShadows = cfg.enableGlow
? `
box-shadow:
0 0 0 1px rgba(255,255,255,0.03),
0 0 18px var(--singularity-glow-soft),
0 4px 20px rgba(0,0,0,0.05);
`
: `
box-shadow:
0 0 0 1px rgba(255,255,255,0.03),
0 4px 18px rgba(0,0,0,0.05);
`;
const tableShadowsHover = cfg.enableGlow
? `
box-shadow:
0 0 0 1px var(--singularity-glow-strong),
0 0 28px var(--singularity-glow-strong),
0 6px 28px rgba(0,0,0,0.12);
`
: `
box-shadow:
0 0 0 1px rgba(255,255,255,0.05),
0 6px 26px rgba(0,0,0,0.12);
`;
const entryAnimCSS = cfg.enableEntryAnim
? `
@keyframes singularFadeIn {
0% { opacity: 0; transform: translateY(8px); }
100% { opacity: 1; transform: translateY(0); }
}
.model-response-text > :is(p, h1, h2, h3, h4, blockquote, table, ul, ol, code-block, mjx-container[display="true"]),
markdown-renderer > :is(p, h1, h2, h3, h4, blockquote, table, ul, ol, code-block, mjx-container[display="true"]) {
animation: singularFadeIn 0.45s var(--ease-out-expo) both;
}
`
: `
.model-response-text > *,
markdown-renderer > * { animation: none !important; }
`;
const justifyCSS = cfg.justifyText
? `
:where(.model-response-text, markdown-renderer) p {
text-align: justify;
text-justify: inter-ideograph;
}
`
: `
:where(.model-response-text, markdown-renderer) p { text-align: left; }
`;
const imagesCSS = cfg.roundImages
? `
:where(.model-response-text, markdown-renderer) img {
max-width: 100%;
height: auto;
border-radius: 14px;
box-shadow: 0 8px 28px rgba(0,0,0,0.08);
}
`
: `
:where(.model-response-text, markdown-renderer) img {
max-width: 100%;
height: auto;
}
`;
const tableMobileCSS = cfg.tableMobileScroll
? `
@media (max-width: 768px) {
:where(.model-response-text, markdown-renderer) table {
display: block;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
}
`
: '';
// =========================
// CSS
// =========================
const css = `
:root {
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
--glass-blur: blur(20px) saturate(180%);
--body-font: ${cfg.enableRemoteFonts ? `'Inter', ` : ''}system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--code-font: ${cfg.enableRemoteFonts ? `'JetBrains Mono', ` : ''}'Fira Code', 'Menlo', ui-monospace, SFMono-Regular, monospace;
--accent: #4285f4;
--accent-strong: #1a73e8;
--accent-soft: rgba(66, 133, 244, 0.08);
--singularity-glow-soft: rgba(138, 180, 248, 0.26);
--singularity-glow-strong: rgba(138, 180, 248, 0.55);
--singularity-max-width: ${cfg.maxWidth}px;
--singularity-font-size: ${cfg.fontSize}px;
--singularity-font-size-mobile: ${cfg.fontSizeMobile}px;
/* 代码块:主题自适应变量(默认按浅色) */
--sg-code-bg: var(--gm-surface-variant, #f6f7f8);
--sg-code-text: var(--gm-on-surface, #202124);
--sg-code-border: var(--gm-outline-variant, rgba(0,0,0,0.10));
--sg-code-header-bg: rgba(255,255,255,0.75);
--sg-code-header-sep: rgba(0,0,0,0.06);
scrollbar-width: thin;
scrollbar-color: var(--gm-outline-variant, rgba(128,128,128,0.2)) transparent;
}
/* 深色主题兜底 */
@media (prefers-color-scheme: dark) {
:root {
--sg-code-bg: #050608;
--sg-code-text: #e4e4e4;
--sg-code-border: var(--gm-outline-variant, rgba(255,255,255,0.12));
--sg-code-header-bg: rgba(30, 30, 30, 0.6);
--sg-code-header-sep: rgba(255,255,255,0.06);
}
}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
background: var(--gm-outline-variant, rgba(128,128,128,0.2));
border-radius: 99px;
border: 2px solid transparent;
background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--gm-outline, rgba(128,128,128,0.5)); }
.conversation-container,
.bottom-container,
.input-area-container {
max-width: var(--singularity-max-width) !important;
margin: 0 auto !important;
padding-inline: 12px;
}
::selection { background: rgba(66, 133, 244, 0.25); color: inherit; }
${entryAnimCSS}
@media (prefers-reduced-motion: reduce) {
.model-response-text > *,
markdown-renderer > * { animation: none !important; }
code-block,
.model-response-text table,
markdown-renderer table { transition: none !important; }
}
/* 更强的“减少透明/特效”降级(支持就用,不支持也不影响) */
@media (prefers-reduced-transparency: reduce) {
code-block, :where(.model-response-text, markdown-renderer) table {
box-shadow: none !important;
}
.code-block-decoration {
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
}
/* ====== 正文排版 ====== */
:where(.model-response-text, markdown-renderer) {
font-family: var(--body-font) !important;
font-size: var(--singularity-font-size) !important;
line-height: 1.85 !important;
letter-spacing: 0.012em;
color: var(--gm-on-surface) !important;
hyphens: auto;
}
:where(.model-response-text, markdown-renderer) :is(h1, h2, h3, h4) {
font-weight: 750 !important;
letter-spacing: -0.02em;
margin-top: 1.8em !important;
margin-bottom: 0.8em !important;
color: var(--gm-on-surface);
position: relative;
}
:where(.model-response-text, markdown-renderer) h1 { font-size: 1.6em !important; }
:where(.model-response-text, markdown-renderer) h2 { font-size: 1.35em !important; }
:where(.model-response-text, markdown-renderer) h3 { font-size: 1.18em !important; }
:where(.model-response-text, markdown-renderer) h4 { font-size: 1.05em !important; }
:where(.model-response-text, markdown-renderer) :is(h1, h2, h3, h4)::after {
content: '';
position: absolute;
left: 0;
bottom: -6px;
width: 72px;
height: 2px;
border-radius: 99px;
background: linear-gradient(90deg, var(--accent), transparent);
opacity: 0.55;
}
:where(.model-response-text, markdown-renderer) p {
margin-bottom: 1.8em !important;
max-width: 100%;
}
${justifyCSS}
@media (max-width: 768px) {
:where(.model-response-text, markdown-renderer) {
font-size: var(--singularity-font-size-mobile) !important;
}
:where(.model-response-text, markdown-renderer) p { text-align: left !important; }
}
/* 列表 */
:where(.model-response-text, markdown-renderer) ul li::marker { color: var(--accent); }
:where(.model-response-text, markdown-renderer) ol li::marker {
color: var(--accent);
font-weight: 600;
font-variant-numeric: tabular-nums;
}
:where(.model-response-text, markdown-renderer) li {
padding-left: 4px;
margin-bottom: 0.8em !important;
}
/* 链接:hover 不抖动 */
:where(.model-response-text, markdown-renderer) a {
text-decoration: none !important;
color: var(--accent-strong) !important;
border-bottom: 1.5px solid rgba(26, 115, 232, 0.3);
transition: box-shadow 0.18s ease-out, background 0.18s ease-out, border-color 0.18s ease-out;
font-weight: 500;
border-radius: 4px;
}
:where(.model-response-text, markdown-renderer) a:hover {
border-bottom-color: var(--accent-strong);
background: var(--accent-soft);
box-shadow: 0 0 0 4px var(--accent-soft);
}
@media (prefers-color-scheme: dark) {
:where(.model-response-text, markdown-renderer) a {
color: #8ab4f8 !important;
border-color: rgba(138, 180, 248, 0.35);
}
}
/* ===== 可访问性:键盘 focus ring(范围尽量收在主区) ===== */
:where(.conversation-container, .bottom-container, .input-area-container)
:is(a, button, [role="button"], input, textarea, select):focus-visible {
outline: 2px solid var(--accent) !important;
outline-offset: 3px !important;
border-radius: 8px;
box-shadow: 0 0 0 4px var(--accent-soft) !important;
}
/* ====== 代码块(主题自适应) ====== */
code-block {
display: block;
margin: 32px 0 !important;
border-radius: 16px !important;
border: 1px solid var(--sg-code-border) !important;
background: var(--sg-code-bg) !important;
${glowShadows}
overflow: hidden !important;
position: relative;
z-index: 1;
transition: box-shadow 0.22s var(--ease-out-expo), border-color 0.22s var(--ease-out-expo);
}
code-block:hover {
border-color: var(--singularity-glow-strong);
${glowShadowsHover}
}
.code-block-decoration {
height: 50px !important;
display: flex;
align-items: center;
padding: 0 22px !important;
background: var(--sg-code-header-bg) !important;
border-bottom: 1px solid var(--sg-code-header-sep);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
.code-block-decoration {
backdrop-filter: var(--glass-blur) !important;
-webkit-backdrop-filter: var(--glass-blur) !important;
}
}
.code-block-decoration::before {
content: '';
width: 12px;
height: 12px;
border-radius: 50%;
background: #ff5f56;
box-shadow: 20px 0 0 #ffbd2e, 40px 0 0 #27c93f;
margin-right: 20px;
opacity: 0.8;
transition: opacity 0.3s;
}
code-block:hover .code-block-decoration::before { opacity: 1; }
/* 仅影响 code-block 内 pre */
code-block pre {
background: transparent !important;
padding: 24px !important;
font-family: var(--code-font) !important;
font-size: 14.5px !important;
line-height: 1.7 !important;
color: var(--sg-code-text) !important;
text-shadow: none;
overflow-x: auto;
tab-size: 4;
}
@media (prefers-color-scheme: dark) {
code-block pre { text-shadow: 0 1px 2px rgba(0,0,0,0.5); }
}
/* 行内代码 */
:where(.model-response-text, markdown-renderer) :not(pre) > code {
font-family: var(--code-font) !important;
background: var(--gm-secondary-container, rgba(0,0,0,0.05)) !important;
color: var(--gm-on-secondary-container, #d93025) !important;
padding: 4px 8px !important;
border-radius: 8px !important;
font-size: 0.85em !important;
border: 1px solid var(--gm-outline-variant, rgba(0,0,0,0.05));
vertical-align: baseline;
font-weight: 600;
word-break: break-word;
}
/* 引用块 */
:where(.model-response-text, markdown-renderer) blockquote {
border: none !important;
position: relative;
margin: 2.4em 0 !important;
padding: 1.6em 2em !important;
background: linear-gradient(
135deg,
var(--gm-surface-variant, rgba(66, 133, 244, 0.05)) 0%,
rgba(66, 133, 244, 0.01) 100%
);
border-radius: 16px;
color: var(--gm-on-surface-variant) !important;
}
:where(.model-response-text, markdown-renderer) blockquote::before {
content: '❝';
position: absolute;
top: 10px;
right: 14px;
font-size: 28px;
opacity: 0.18;
color: var(--accent);
pointer-events: none;
}
:where(.model-response-text, markdown-renderer) blockquote::after {
content: '';
position: absolute;
left: 0;
top: 12px;
bottom: 12px;
width: 3px;
background: var(--accent);
border-radius: 0 4px 4px 0;
box-shadow: 2px 0 8px rgba(66, 133, 244, 0.3);
}
/* 表格 */
:where(.model-response-text, markdown-renderer) table {
border-collapse: separate !important;
border-spacing: 0;
width: 100%;
margin: 2.4em 0 !important;
border-radius: 12px;
overflow: hidden;
border: 1px solid var(--gm-outline-variant, rgba(128,128,128,0.2));
${tableShadows}
transition: box-shadow 0.22s var(--ease-out-expo), border-color 0.22s var(--ease-out-expo);
}
:where(.model-response-text, markdown-renderer) table:hover {
border-color: var(--singularity-glow-strong);
${tableShadowsHover}
}
:where(.model-response-text, markdown-renderer) th {
background: var(--gm-surface-variant, #f1f3f4);
color: var(--gm-on-surface);
padding: 16px 18px !important;
font-weight: 700;
font-size: 0.95em;
text-transform: uppercase;
letter-spacing: 0.05em;
white-space: nowrap;
}
:where(.model-response-text, markdown-renderer) td {
padding: 14px 18px !important;
border-top: 1px solid var(--gm-outline-variant, rgba(128,128,128,0.05));
background: var(--gm-surface, transparent);
transition: background 0.1s;
}
:where(.model-response-text, markdown-renderer) tr:hover td {
background: var(--gm-secondary-container, rgba(66, 133, 244, 0.05));
}
${tableMobileCSS}
/* LaTeX */
:where(.model-response-text, markdown-renderer) mjx-container[display="true"] {
margin: 2.5em 0 !important;
padding: 1.5em 2em !important;
background: var(--gm-surface-variant, rgba(128,128,128,0.03));
border-radius: 12px;
border: 1px solid var(--gm-outline-variant, transparent);
color: var(--gm-on-surface) !important;
overflow-x: auto;
}
${imagesCSS}
.input-area-container { padding-bottom: 40px !important; }
/* ===== 高对比模式/强制颜色:禁用发光/渐变,确保可读 ===== */
@media (forced-colors: active) {
code-block,
:where(.model-response-text, markdown-renderer) table,
:where(.model-response-text, markdown-renderer) blockquote,
:where(.model-response-text, markdown-renderer) mjx-container[display="true"] {
box-shadow: none !important;
background: Canvas !important;
color: CanvasText !important;
border: 1px solid CanvasText !important;
}
.code-block-decoration {
background: Canvas !important;
border-bottom: 1px solid CanvasText !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
:where(.model-response-text, markdown-renderer) :is(h1,h2,h3,h4)::after {
background: CanvasText !important;
opacity: 1 !important;
}
}
`;
if (typeof GM_addStyle !== 'undefined') {
GM_addStyle(css);
} else {
const style = document.createElement('style');
style.textContent = css;
document.documentElement.appendChild(style);
}
if (DEBUG) console.log('Gemini Singularity (V5.7 Lite++) Activated.', cfg);
})();