/* styles.css Combined light and dark themes for the Nginx FancyIndex page. Optimized for modern browsers: Chrome, Firefox, Safari, Edge * ยฉ 2015-17, Lilian Besson (Naereen) and contributors, * open-sourced under the MIT License, https://lbesson.mit-license.org/ * hosted on GitHub, https://GitHub.com/Naereen/Nginx-Fancyindex-Theme */ /* */ /* ========================= Base: box sizing + smooth scroll ========================= */ *, *::before, *::after { box-sizing: border-box; /* predictable sizing model */ } html { scroll-behavior: smooth; /* smooth anchor jumps */ } /* ========================= Accessibility: honor reduced motion Generally not applicable to a nginx static file server, but doesn't hurt to include https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion ========================= */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; /* effectively disables animations */ animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; /* disables transitions */ scroll-behavior: auto !important; /* avoids smooth scrolling */ } } /* ========================= Theme tokens (Light) Centralized design variables used throughout higher specificity than the html selector https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascade/Specificity https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:root ========================= */ :root { --bg: #f4f6fb; /* page background */ --bg-elev: #ffffff; /* elevated surfaces (cards, inputs) */ --fg: #1e2430; /* primary text */ --muted: #5e6877; /* secondary text */ --row-hover: #eef1f8; /* table row hover */ --rule: #d7dde6; /* borders / rules */ --accent: #2d6cdf; /* accent + links */ --focus: 0 0 0 3px rgba(45, 108, 223, 0.25); /* focus ring shadow */ --link: var(--accent); /* primary link color */ --clear-link: var(--muted); /* subtle action links */ --input-border: var(--rule); /* input border */ --focus-border: var(--accent); /* input focus border */ --table-shadow: 0 18px 38px rgba(15, 30, 55, 0.08); /* table elevation */ --td-border: rgba(0, 0, 0, 0.05); /* table row separators */ --parent-hover: #1b1f2a; /* parent dir hover */ --footer-link: var(--accent); /* footer link color */ --toggle-bg: #e8ecf6; /* theme toggle background */ --toggle-fg: #1e2430; /* theme toggle text */ --toggle-border: rgba(30, 36, 48, 0.1); --toggle-hover-bg: #dbe3f5; /* theme toggle hover */ --card-bg: #ffffff; /* card background */ --border-color: #d7dde6; /* border color */ --button-bg: #f4f6fb; /* button background */ --button-fg: #1e2430; /* button foreground */ --button-hover-bg: #eef1f8; /* button hover background */ --button-hover-border: #2d6cdf; /* button hover border */ --link-color: #2d6cdf; /* link color */ --link-hover-color: #1b4ddd; /* link hover color */ --text-color: #1e2430; /* text color */ } /* ========================= Theme tokens (Dark) Override variables when .theme-dark is on Values taken from Nginx-Fancyindex-Theme-dark/styles.css ========================= */ body.theme-dark { --bg: #2f343f; --bg-elev: #262a32; --fg: #ffffff; --muted: #9099a3; --row-hover: #3d4351; --rule: #3c404a; --accent: #cfd6df; --focus: 0 0 0 3px rgba(255, 255, 255, 0.25); --link: #ffffff; --clear-link: #cbd3dc; --input-border: #3c404a; --focus-border: #cfd6df; --table-shadow: 0 20px 40px rgba(0, 0, 0, 0.35); --td-border: rgba(255, 255, 255, 0.07); --parent-hover: #2a2a2a; --footer-link: #ffffff; --toggle-bg: #1f222b; --toggle-fg: #ffffff; --toggle-border: rgba(255, 255, 255, 0.12); --toggle-hover-bg: #2a2f3a; } /* ========================= Global typography + colors prioritize the default user interface font of the operating system for native look and feel https://css-tricks.com/snippets/css/system-font-stack/ ========================= */ html { font-family: system-ui, -apple-system, 'Segoe UI', Ubuntu, Cantarell, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji'; color: var(--muted); /* default text color (secondary) */ font-weight: 300; font-size: clamp(14px, 1.2vw, 16px); /* fluid base size */ line-height: 1.6; /* TO DO: 1.6x font height is "confortable", add toggle for condensed ~1.2*/ text-size-adjust: 100%; background-color: var(--bg); } body { margin: 0; justify-content: center; /* layout centering when used with flex contexts */ align-items: flex-start; min-height: 100vh; padding: clamp(12px, 2.5vw, 24px); /* responsive page padding */ color: var(--fg); /* main text color */ background-color: var(--bg); transition: background-color 150ms ease-in, color 150ms ease-in; /* theme fade */ } /* ========================= Headings and table headers ========================= */ thead { font-weight: 200; font-size: 1.2em; } h1 { font-weight: 300; text-align: center; font-size: clamp(1.5rem, 2vw + 1rem, 2.4rem); line-height: 1.4; margin-bottom: 1.25rem; } /* ========================= Directory header: search + theme toggle container ========================= */ .directory-controls { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; margin-bottom: 1.5rem; } /* Arrange controls horizontally on wider screens */ @media (min-width: 720px) { .directory-controls { flex-direction: row; justify-content: center; } } /* ========================= Links ========================= */ a { color: var(--link); text-decoration: none; } a:hover { text-decoration: underline; } /* "Clear" link style (e.g., reset search) */ a.clear, a.clear:link, a.clear:visited { color: var(--clear-link); padding: 2px 0; font-weight: 400; font-size: 1rem; margin-left: 1rem; line-height: 1; display: inline-block; border-bottom: 1px solid transparent; transition: border-color 200ms ease-in; } a.clear:hover { border-bottom-color: currentColor; } /* ========================= Theme toggle button ========================= */ .theme-toggle { appearance: none; border-radius: 999px; /* pill */ border: 1px solid var(--toggle-border); background: var(--toggle-bg); color: var(--toggle-fg); padding: 0.35rem 1.2rem; font: 500 0.9rem/1.2 'Roboto', system-ui, sans-serif; cursor: pointer; transition: background-color 150ms ease-in, transform 150ms ease-in; display: inline-flex; align-items: center; gap: 0.45rem; /* icon/text spacing */ } .theme-toggle:hover { background: var(--toggle-hover-bg); } .theme-toggle:focus-visible { outline: none; box-shadow: var(--focus); /* tokenized focus ring */ } .theme-toggle[aria-pressed="true"] { font-weight: 600; /* pressed state emphasis */ } /* ========================= Inputs (search) ========================= */ input { display: block; margin: 0 auto; width: clamp(16rem, 60vw, 32rem); /* fluid width */ height: 2.25rem; padding: 0 0.75rem; color: var(--fg); background-color: var(--bg-elev); border: 1px solid var(--input-border); border-radius: 6px; font: 300 0.95rem/1.2 'Roboto', system-ui, sans-serif; transition: border-color 150ms ease-in, box-shadow 150ms ease-in; } input:focus-visible { outline: 0; border-color: var(--focus-border); box-shadow: var(--focus); } #search { color: var(--fg); background-color: var(--bg-elev); display: block; margin-inline: auto; width: min(100%, 320px); margin-top: 0; appearance: textfield; /* normalizes iOS search styles */ } /* ========================= Table: container + rows/cols ========================= */ table { border-collapse: collapse; font-size: 0.95em; width: 100%; margin: 24px 0 0; background: var(--bg-elev); border-radius: 16px; overflow: hidden; box-shadow: var(--table-shadow); } tr { outline: 0; border: 0; } tr:hover td { color: var(--fg); background: var(--row-hover); } tr td:first-of-type { padding-left: 10px; padding-right: 10px; } tr.parent a { color: var(--muted); /* subtle parent directory row */ } th { text-align: left; font-size: 0.75em; padding: 12px 20px; text-transform: uppercase; letter-spacing: 0.08em; color: #7a8597; background: #e3e8f1; } body.theme-dark th { color: #8a94a6; background: #1f222b; } th + th { width: 25%; /* constrain mid columns */ } th + th + th + th { width: 5%; /* final column (e.g., size) narrow */ } td { padding: 14px 20px; outline: 0; border: 0; border-bottom: 1px solid var(--td-border); /* row separators */ vertical-align: middle; text-align: left; transition: background 300ms ease-in; } td:last-child, th:last-child { text-align: right; /* align trailing numeric data */ padding-right: 10px; } td a { display: block; /* make entire cell clickable */ } /* ========================= File type "icons" via ::before content Applied to first column links https://stackoverflow.com/a/60198998 https://www.smashingmagazine.com/2009/08/taming-advanced-css-selectors/#before-and-after ========================= */ #list tbody tr td:first-child a::before { content: '๐Ÿ“„'; margin-right: 0.5rem; display: inline-block; font-style: normal; } /* Directory/Folder */ #list tbody tr td:first-child a[href$="/"]::before { content: '๐Ÿ“'; } /* Parent directory */ #list tbody tr.parent td:first-child a::before { content: 'โฌ†๏ธ'; } /* Images */ #list tbody tr td:first-child a[href$=".jpg"]::before, #list tbody tr td:first-child a[href$=".jpeg"]::before, #list tbody tr td:first-child a[href$=".png"]::before, #list tbody tr td:first-child a[href$=".gif"]::before, #list tbody tr td:first-child a[href$=".svg"]::before, #list tbody tr td:first-child a[href$=".webp"]::before, #list tbody tr td:first-child a[href$=".ico"]::before, #list tbody tr td:first-child a[href$=".bmp"]::before { content: '๐Ÿ–ผ๏ธ'; } /* Videos */ #list tbody tr td:first-child a[href$=".mp4"]::before, #list tbody tr td:first-child a[href$=".avi"]::before, #list tbody tr td:first-child a[href$=".mov"]::before, #list tbody tr td:first-child a[href$=".wmv"]::before, #list tbody tr td:first-child a[href$=".flv"]::before, #list tbody tr td:first-child a[href$=".webm"]::before, #list tbody tr td:first-child a[href$=".mkv"]::before { content: '๐ŸŽฌ'; } /* Audio */ #list tbody tr td:first-child a[href$=".mp3"]::before, #list tbody tr td:first-child a[href$=".wav"]::before, #list tbody tr td:first-child a[href$=".flac"]::before, #list tbody tr td:first-child a[href$=".aac"]::before, #list tbody tr td:first-child a[href$=".ogg"]::before, #list tbody tr td:first-child a[href$=".m4a"]::before { content: '๐ŸŽต'; } /* Archives */ #list tbody tr td:first-child a[href$=".zip"]::before, #list tbody tr td:first-child a[href$=".rar"]::before, #list tbody tr td:first-child a[href$=".tar"]::before, #list tbody tr td:first-child a[href$=".gz"]::before, #list tbody tr td:first-child a[href$=".7z"]::before, #list tbody tr td:first-child a[href$=".bz2"]::before, #list tbody tr td:first-child a[href$=".xz"]::before { content: '๐Ÿ“ฆ'; } /* Documents */ #list tbody tr td:first-child a[href$=".pdf"]::before { content: '๐Ÿ“•'; } #list tbody tr td:first-child a[href$=".doc"]::before, #list tbody tr td:first-child a[href$=".docx"]::before { content: '๐Ÿ“˜'; } #list tbody tr td:first-child a[href$=".xls"]::before, #list tbody tr td:first-child a[href$=".xlsx"]::before, #list tbody tr td:first-child a[href$=".csv"]::before { content: '๐Ÿ“Š'; } #list tbody tr td:first-child a[href$=".ppt"]::before, #list tbody tr td:first-child a[href$=".pptx"]::before { content: '๐Ÿ“™'; } #list tbody tr td:first-child a[href$=".txt"]::before, #list tbody tr td:first-child a[href$=".md"]::before, #list tbody tr td:first-child a[href$=".markdown"]::before { content: '๐Ÿ“'; } /* Code files */ #list tbody tr td:first-child a[href$=".html"]::before, #list tbody tr td:first-child a[href$=".htm"]::before, #list tbody tr td:first-child a[href$=".css"]::before, #list tbody tr td:first-child a[href$=".js"]::before, #list tbody tr td:first-child a[href$=".json"]::before, #list tbody tr td:first-child a[href$=".xml"]::before, #list tbody tr td:first-child a[href$=".php"]::before, #list tbody tr td:first-child a[href$=".py"]::before, #list tbody tr td:first-child a[href$=".java"]::before, #list tbody tr td:first-child a[href$=".c"]::before, #list tbody tr td:first-child a[href$=".cpp"]::before, #list tbody tr td:first-child a[href$=".h"]::before, #list tbody tr td:first-child a[href$=".sh"]::before, #list tbody tr td:first-child a[href$=".rb"]::before, #list tbody tr td:first-child a[href$=".go"]::before, #list tbody tr td:first-child a[href$=".rs"]::before, #list tbody tr td:first-child a[href$=".ts"]::before, #list tbody tr td:first-child a[href$=".tsx"]::before, #list tbody tr td:first-child a[href$=".jsx"]::before { content: '๐Ÿ’ป'; } /* Executables */ #list tbody tr td:first-child a[href$=".exe"]::before, #list tbody tr td:first-child a[href$=".app"]::before, #list tbody tr td:first-child a[href$=".dmg"]::before, #list tbody tr td:first-child a[href$=".iso"]::before { content: 'โš™๏ธ'; } /* Configuration */ #list tbody tr td:first-child a[href$=".ini"]::before, #list tbody tr td:first-child a[href$=".cfg"]::before, #list tbody tr td:first-child a[href$=".conf"]::before, #list tbody tr td:first-child a[href$=".yaml"]::before, #list tbody tr td:first-child a[href$=".yml"]::before, #list tbody tr td:first-child a[href$=".toml"]::before { content: '๐Ÿ”ง'; } /* ========================= Parent directory hover ========================= */ .parent a:hover { color: var(--parent-hover); } /* ========================= Footer ========================= */ footer { font-size: 12px; text-align: center; } footer a { text-decoration: underline; color: var(--footer-link); } /* ========================= Breadcrumb Navigation ========================= */ .breadcrumb-nav { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; padding: 0.75rem 1rem; background-color: var(--card-bg); border: 1px solid var(--border-color); border-radius: 6px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .breadcrumb-container { display: flex; align-items: center; flex-wrap: wrap; font-size: 1rem; } .breadcrumb-container a { color: var(--link-color); text-decoration: none; transition: color 0.2s ease; padding: 0.25rem 0; } .breadcrumb-container a:hover, .breadcrumb-container a:focus { color: var(--link-hover-color); text-decoration: underline; } .breadcrumb-separator { padding: 0 0.5rem; color: var(--muted); } .breadcrumb-current { color: var(--text-color); font-weight: 500; padding: 0.25rem 0; } /* ========================= Copy page URL button ========================= */ .copy-page-url-btn { appearance: none; border-radius: 4px; border: 1px solid var(--border-color); background: var(--button-bg); color: var(--button-fg); padding: 0.25rem 0.75rem; font: 400 0.875rem/1.2 'Roboto', system-ui, sans-serif; cursor: pointer; transition: all 150ms ease-in; white-space: nowrap; } .copy-page-url-btn:hover, .copy-page-url-btn:focus { background: var(--button-hover-bg); border-color: var(--button-hover-border); } .copy-page-url-btn:focus-visible { outline: none; box-shadow: var(--focus); } /* ========================= Pagination controls ========================= */ .pagination { display: flex; flex-direction: column; align-items: center; gap: 1rem; margin: 2rem 0; padding: 1rem; } .pagination-info { color: var(--muted); font-size: 0.9rem; } .pagination-buttons { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; justify-content: center; } .pagination-btn { appearance: none; border: 1px solid var(--rule); background: var(--bg-elev); color: var(--fg); padding: 0.5rem 0.75rem; border-radius: 6px; font: 400 0.9rem system-ui, sans-serif; cursor: pointer; transition: all 150ms ease-in; min-width: 2.5rem; } .pagination-btn:hover:not(:disabled) { background: var(--row-hover); border-color: var(--accent); } .pagination-btn:focus-visible { outline: none; box-shadow: var(--focus); } .pagination-btn:disabled { opacity: 0.5; cursor: not-allowed; } .pagination-btn.active { background: var(--accent); color: white; border-color: var(--accent); font-weight: 600; } .pagination-ellipsis { color: var(--muted); padding: 0 0.25rem; } /* ========================= Responsive: mobile layout Converts the table into stacked cards and adjusts controls ========================= */ @media (max-width: 720px) { body { padding: clamp(16px, 4vw, 32px); box-shadow: none; } /* Stack table elements as blocks for small screens */ table, thead, tbody, th, td, tr { display: block; width: 100%; } table { background: transparent; box-shadow: none; border-radius: 0; overflow: visible; } thead { display: none; /* hide header row on mobile */ } tr { margin-bottom: 16px; border: 1px solid var(--td-border); border-radius: 12px; box-shadow: var(--table-shadow); overflow: hidden; background: var(--bg-elev); } body.theme-dark tr { box-shadow: 0 16px 32px rgba(0, 0, 0, 0.35); } td { padding: 12px 16px; border-bottom: 1px solid var(--td-border); display: flex; justify-content: space-between; gap: 12px; } td:last-child { border-bottom: none; text-align: left; } td::before { content: attr(data-label); /* adds pseudo header */ font-weight: 600; color: rgba(27, 31, 42, 0.7); text-transform: uppercase; letter-spacing: 0.04em; } body.theme-dark td::before { color: rgba(255, 255, 255, 0.65); } /* Fallback labels if data-label not provided */ td:nth-of-type(1):not([data-label])::before { content: 'ๆ–‡ไปถๅ'; } td:nth-of-type(2):not([data-label])::before { content: 'ไฟฎๆ”นๆ—ถ้—ด'; } td:nth-of-type(3):not([data-label])::before { content: 'ๅคงๅฐ'; } td:nth-of-type(4):not([data-label])::before { content: 'ๆ่ฟฐ'; } /* Mobile breadcrumb styles */ .breadcrumb { font-size: 0.85rem; } .breadcrumb-nav { padding: 0.5rem 0.75rem; } /* Mobile pagination styles */ .pagination-btn { padding: 0.4rem 0.6rem; font-size: 0.85rem; min-width: 2.25rem; } .pagination-info { font-size: 0.85rem; } /* Mobile copy button styles */ .copy-page-url-btn { font-size: 0.8rem; padding: 0.4rem 0.75rem; margin-left: 0; margin-top: 0.5rem; } }