starlight-theme-obsidian
Version:
A Starlight theme inspired by the Obsidian Publish website theme
368 lines (306 loc) • 12.3 kB
CSS
@layer obsidian {
/* When only the left-sidebar or both sidebars are visible */
@media (min-width: 50em) {
/* Align sidebar and content next to each other, make scrollable, add padding for centered reading */
.page {
flex-direction: row;
height: 100vh;
overflow-y: scroll;
/* This expression can become negative (has no effect) */
padding-left: calc((100vw - var(--sl-content-width) - 2 * var(--sl-sidebar-width)) / 2);
}
/* Make sidebar sticky w.r.t scrolled content */
.sidebar {
position: sticky;
top: 0;
align-self: flex-start;
z-index: 1;
height: inherit;
/* Ensure that the sidebar is either this size or smaller */
max-width: var(--sl-sidebar-width);
}
.mobile-header {
.title-wrapper {
display: none;
}
}
}
/* When both sidebars are visible */
@media (min-width: 72em) {
/* Only offset content when regular header is visible (hero pages), not for regular content */
:root:not(:has(header)) {
--sl-nav-height: 0;
}
/* Fully hide the mobile header */
.mobile-header {
display: none;
visibility: hidden;
}
/* Make right sidebar sticky w.r.t scrolled content */
.right-sidebar-container {
position: sticky;
top: 0;
align-self: flex-start;
z-index: 1;
height: inherit;
/* Ensure that the sidebar is either this size or smaller */
max-width: var(--sl-sidebar-width);
}
/* FIXME: This is very, very, very bad.
Some background:
The .right-sidebar-container is a sticky element, so it has its own stacking context.
That means that the blur filter applied by the .background-blur element within the slsg-graph-component
is _not_ applied to the .sidebar (left sidebar) due to it being in a different stacking context;
regardless of what the z-index of the .sidebar is.
So there are four solutions:
1. Just keep it as is and reason that the left sidebar should always be drawn on top (nope, bad).
2. Rework the right sidebar so it is an absolutely positioned element so that the usage of sticky can be avoided
(a lot of work, also requires a lot of finagling with the page and right sidebar widths and offsets
to make the sizing and positioning work properly).
(Solution that will need to be implemented eventually)
3. Keep all the code as is and make the right sidebar positioned normally (no sticky)
-> This is an undesirable solution: when the user has scrolled down, the sidebar will completely disappear when fullscreen is toggled
4. Keep all the code as is and only make the right sidebar positioned fixed when the background blur is applied
Then, approximate the width and relative position of the sidebar based on the current available space.
Currently, I opted for the fourth solution, but it does have the issue that when the sidebar is slightly folded,
everything is off by a bit, and there will be a visible jump when toggling fullscreen (happens between 1151px and 1300px)
Anyways, good luck to future me when you eventually get around to fixing this issue, xxx
EDIT (2025/05/08): This issue only exists in Firefox, Chrome seems to work fine.
*/
body[data-graph-blur='true'] {
.right-sidebar-container {
--right-sidebar-width: clamp(var(--sl-sidebar-width) / 2, calc(100vw - var(--sl-content-width) - var(--sl-sidebar-width)), var(--sl-sidebar-width));
background-color: var(--sl-color-bg-sidebar);
position: fixed;
right: calc(50vw - var(--right-sidebar-width) - var(--sl-content-width) / 2);
width: var(--right-sidebar-width);
}
}
}
/* When screen becomes too narrow to neatly contain both title and mobile-toc */
@media (max-width: 23em) {
/* 'Move' title from mobile header to sidebar */
.mobile-header {
.title-wrapper {
display: none;
}
}
.sidebar-pane.sidebar-pane.sidebar-pane {
.title-wrapper {
display: block;
}
}
}
/* When neither of the sidebars is visible */
@media (max-width: 50em) {
/* Show mobile header with specified height, with hairline */
.mobile-header {
max-width: unset;
border-bottom: 1px solid var(--sl-color-hairline);
mobile-starlight-toc {
.dropdown {
top: calc(var(--sl-nav-height) + 1px);
left: 0;
}
}
}
}
/* When neither sidebar or only the left sidebar is visible */
@media (max-width: 72em) {
/* Do not add padding to main-frame, such that mobile-header is on top */
.main-frame {
padding-top: unset;
}
/* Make flex folded right-sidebar (see site-graph css) take up full width of the page */
.right-sidebar-container {
width: 100%;
}
/* Allow page to fill entire width when there is no right-sidebar */
.page .main-pane.main-pane.main-pane {
max-width: unset;
.sl-container {
max-width: unset;
}
}
}
/* FIXME: Inconsistent scrolling behaviour between FireFox and Chrome,
Current situation: .sidebar-pane { overflow-y: scroll; }\
In Firefox, position sticky does not work
When changing this to .sidebar-content { overflow-y: scroll; }, it does not work in Chrome (unscrollable)
So solution is to use @supports to apply different rules based on browser
*/
@supports not(-moz-appearance:none) {
.sidebar-pane {
overflow-y: scroll;
}
}
@supports (-moz-appearance:none) {
.sidebar-content {
overflow-y: scroll;
scrollbar-width: thin;
scrollbar-gutter: stable;
}
}
/* Reorder page such that content and sidebar are adjacent to each other */
.page {
overflow: clip;
scrollbar-gutter: stable;
}
/* Make sidebar positioned within content (instead of absolute) */
.sidebar-pane, .right-sidebar {
position: unset;
}
/* Make sidebar information and buttons sticky */
.sidebar-top {
position: sticky;
top: 0;
z-index: 1;
background-color: var(--sl-color-bg-nav);
display: flex;
flex-direction: column;
gap: 0.75rem;
padding-top: 1em;
}
/* Make sidebar scrollable (with persistence) */
/* @note: if scrollable property is placed lower in the hierarchy, persistence will not function */
.sidebar-pane {
position: static;
height: inherit;
border-inline-end: unset;
}
/* Make sidebar only take up viewport height, remove top padding for better scroll behaviour */
.sidebar-content {
height: inherit;
padding-top: unset;
}
/* Limit the width for centered reading */
.main-frame {
padding-inline-start: unset;
overflow-y: scroll;
width: 100%;
}
.main-pane {
flex: 1;
margin-top: var(--sl-nav-height);
max-width: var(--sl-content-width);
}
/* Center content if no sidebars are present (e.g. banner splash) */
.page:not(:has(>.sidebar)) {
padding-left: unset;
div.header {
margin-left: auto;
margin-right: auto;
max-width: var(--sl-content-width);
}
.main-pane {
margin-left: auto;
margin-right: auto;
}
}
/* Style site search in folded sidebar similar to regular style */
@media (max-width: 50em) {
.sidebar site-search {
button[data-open-modal] {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.5rem;
padding-inline-start: 0.75rem;
padding-inline-end: 0.5rem;
background-color: var(--sl-color-black);
color: var(--sl-color-gray-2);
font-size: var(--sl-text-sm);
width: 100%;
}
button[data-open-modal]:hover {
border-color: var(--sl-color-gray-2);
color: var(--sl-color-white)
}
button[data-open-modal] > :last-child {
margin-inline-start: auto
}
:is(button, .inc-spec) span {
display: block;
}
}
/* Hide site sidebar on left, make it take up the entire screen (below mobile ToC), animate reveal */
.sidebar-pane.sidebar-pane {
position: fixed;
width: 100%;
height: calc(100vh - var(--sl-nav-height));
z-index: 2;
visibility: unset;
transition: transform 0.2s ease-in-out;
transform: translateX(-100%);
background-color: var(--sl-color-bg);
.title-wrapper {
display: none;
}
}
/* When mobile menu button is pressed, reveal the site sidebar */
body[data-mobile-menu-expanded] .sidebar-pane {
transform: translateX(0);
}
}
/* Show mobile header at the top of the page as a replacement container for the mobile-toc/button */
.mobile-header {
position: fixed;
width: 100%;
height: var(--sl-nav-height);
z-index: 5;
background-color: var(--sl-color-bg-nav);
padding: 0 1rem;
display: flex;
align-items: center;
/* Determines the speed at which the title becomes smaller when overflowing */
.title-wrapper {
flex-shrink: 1;
span {
font-size: clamp(0.2rem, 3vmin, var(--sl-text-h4));
}
}
/* Restyle the menu button to not be contained within a circle */
starlight-menu-button {
flex-shrink: 0;
margin-left: auto;
:is(.inc-spec, button) {
scale: 1.5;
position: unset;
display: flex;
height: fit-content;
width: fit-content;
padding: unset;
color: var(--sl-color-gray-5);
background: unset;
box-shadow: unset;
}
&[aria-expanded="true"] :is(.inc-spec, button) {
background-color: unset;
color: var(--sl-color-accent);
}
}
/* Change the styling of the mobile starlight ToC */
mobile-starlight-toc {
flex-shrink: 0;
nav {
/* Draw mobile ToC on top, align on left side with site sidebar */
position: unset;
border-top: unset;
/* Remove hairline border on bottom of "On this page" element (moved to mobile-header) */
summary {
border-bottom: unset;
padding: 0 0.5rem
}
/* Fix "On this page" dropdown first element not having a top border, make it absolutely positioned */
.dropdown {
position: fixed;
width: 100%;
border-top-color: var(--sl-color-hairline);
}
/* Add hover background */
.dropdown a:hover {
background-color: var(--sl-color-bg-nav);
color: var(--sl-color-accent-high);
}
}
}
}
}