NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Reddit Fluid Width
// @namespace https://github.com/XxUnkn0wnxX/Scripts
// @version 1.0.0
// @description Widens Reddit post/comment pages only while preserving native feed and landing layouts. Vibe coded with OpenAI.
// @homepageURL https://github.com/XxUnkn0wnxX/Scripts
// @supportURL https://discord.gg/slayersicerealm
// @author XxUnkn0wnxX
// @license AGPL-3.0-or-later
// @updateURL https://raw.githubusercontent.com/XxUnkn0wnxX/Scripts/master/userscripts/reddit-fluid-width.user.js
// @downloadURL https://raw.githubusercontent.com/XxUnkn0wnxX/Scripts/master/userscripts/reddit-fluid-width.user.js
// @match https://www.reddit.com/r/*
// @run-at document-start
// @grant none
// @noframes
// ==/UserScript==
(() => {
'use strict';
const STYLE_ID = 'reddit-fluid-width-style';
const ROOT_ATTR = 'data-reddit-fluid-width';
const HISTORY_PATCH_FLAG = '__redditFluidWidthHistoryPatched';
const ROUTE_RE = /^\/r\/[^/]+\/comments\/[^/]+(?:\/|$)/i;
/*** CONFIG ***/
// Set 85-95 here for narrower/wider post containers.
// true (default) pins the right edge at 100%/0px; false centers the whole grid.
const CONFIG = Object.freeze({
contentWidthPercent: 95,
minGutterPx: 32,
pinRightSidebar: true,
});
const config = normalizeConfig(CONFIG);
const style = ensureStyle();
const html = document.documentElement;
style.textContent = buildStyles();
syncRouteState();
installRouteSyncHooks();
function normalizeConfig(source) {
const percentRaw = Number(source?.contentWidthPercent);
const gutterRaw = Number(source?.minGutterPx);
const pinRightSidebar = source?.pinRightSidebar;
const contentWidthPercent = Number.isFinite(percentRaw)
? Math.max(1, Math.min(100, percentRaw))
: 95;
const minGutterPx = Number.isFinite(gutterRaw)
? Math.max(16, Math.min(128, Math.round(gutterRaw)))
: 32;
return Object.freeze({
contentWidthPercent,
minGutterPx,
pinRightSidebar: typeof pinRightSidebar === 'boolean' ? pinRightSidebar : true,
});
}
function syncRouteState() {
const isPostRoute = isRedditPostCommentsRoute(location.pathname);
if (isPostRoute) {
html.setAttribute(ROOT_ATTR, '');
return;
}
html.removeAttribute(ROOT_ATTR);
}
function isRedditPostCommentsRoute(pathname) {
return ROUTE_RE.test(String(pathname || '').trim());
}
function buildStyles() {
const isPinned = config.pinRightSidebar;
const horizontalModeStyles = isPinned
? `
margin-inline-start: auto !important;
margin-inline-end: 0px !important;
`
: `
margin-inline: auto !important;
`;
const gutteredWidth = isPinned
? `calc(100% - var(--reddit-fluid-gutter))`
: `calc(100% - var(--reddit-fluid-gutter) - var(--reddit-fluid-gutter))`;
return `
@media (min-width: 1472px) {
html[${ROOT_ATTR}] #subgrid-container {
--reddit-fluid-width: ${config.contentWidthPercent}%;
--reddit-fluid-gutter: ${config.minGutterPx}px;
width: max(
1120px,
min(var(--reddit-fluid-width), ${gutteredWidth})
) !important;
box-sizing: border-box;
${horizontalModeStyles}
}
html[${ROOT_ATTR}] #subgrid-container > .main-container.fixed-sidebar {
grid-template-columns: minmax(0, 1fr) minmax(0, 316px) !important;
}
}
`;
}
function ensureStyle() {
let styleNode = document.getElementById(STYLE_ID);
if (!styleNode) {
styleNode = document.createElement('style');
styleNode.id = STYLE_ID;
(document.head || document.documentElement).appendChild(styleNode);
}
return styleNode;
}
function installRouteSyncHooks() {
if (!history[HISTORY_PATCH_FLAG]) {
const originalPushState = history.pushState;
const originalReplaceState = history.replaceState;
history.pushState = function (...args) {
const result = originalPushState.apply(this, args);
syncRouteState();
return result;
};
history.replaceState = function (...args) {
const result = originalReplaceState.apply(this, args);
syncRouteState();
return result;
};
history[HISTORY_PATCH_FLAG] = true;
}
window.addEventListener('popstate', syncRouteState, true);
window.addEventListener('pageshow', syncRouteState, true);
}
})();