# Reader view in Publish using cssClasses > [!noteinfo] > 27.07.2024 · [[../../Info/Marco Noris|Marco Noris]] · [GitHub - marconoris/Obsidian-Publish-stuff](https://github.com/marconoris/Obsidian-Publish-stuff/tree/main) · #obsidian #code #css #javascript This script activates a "reading view" on an Obsidian Publish website. This view can be useful to visualize poetic texts or to browse through images as a portfolio or simply to have a clearer view while reading. Now you can activate the "reading view" in 4 different ways: - using a button - pressing the <kbd>r</kbd> key - by defining the reader-view class in the cssClass property in the frontmatter - adding `?reader=true` to the url of the page. Reader view hides sidebars and page title and adapts the layout. ###### JS ```Javascript // READER VIEW // Iconos SVG para los estados visible y oculto const iconVisible = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize-2"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" x2="14" y1="3" y2="10"/><line x1="3" x2="10" y1="21" y2="14"/></svg>`; // SVG para cuando las sidebars están visibles const iconHidden = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-minimize-2"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="14" x2="21" y1="10" y2="3"/><line x1="3" x2="10" y1="21" y2="14"/></svg>`; // SVG para cuando las sidebars están ocultas // Función para alternar la clase 'reader-view' en todas las instancias de .node-insert-event function toggleReaderView() { const markdownPreviews = document.querySelectorAll('.node-insert-event'); const toggleButton = document.querySelector('#toggle-sidebar-btn'); if (markdownPreviews.length > 0 && toggleButton) { const isReaderView = Array.from(markdownPreviews).some(preview => preview.classList.contains('reader-view')); markdownPreviews.forEach(preview => { if (isReaderView) { preview.classList.remove('reader-view'); } else { preview.classList.add('reader-view'); } }); // Cambia el icono del botón según el estado de la clase 'reader-view' toggleButton.innerHTML = isReaderView ? iconVisible : iconHidden; // Guardar el estado en localStorage localStorage.setItem('readerView', !isReaderView); } } // Añadir un evento de escucha para la tecla "r" document.addEventListener('keydown', function(event) { const activeElement = document.activeElement; const isSearchInputFocused = activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA'); if (event.key === 'r' && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey && !isSearchInputFocused) { toggleReaderView(); } }); // Función para verificar y aplicar el estado de visibilidad inicial function applyInitialVisibilityState() { const markdownPreviews = document.querySelectorAll('.node-insert-event'); const toggleButton = document.querySelector('#toggle-sidebar-btn'); // Obtener el estado de localStorage const isReaderView = localStorage.getItem('readerView') === 'true'; markdownPreviews.forEach(preview => { if (isReaderView) { preview.classList.add('reader-view'); } else { preview.classList.remove('reader-view'); } }); toggleButton.innerHTML = isReaderView ? iconHidden : iconVisible; } // Función para crear y añadir el botón de alternar al .site-body-center-column function addToggleButton() { const siteBodyCenterColumn = document.querySelector('.site-body-center-column'); if (siteBodyCenterColumn) { // Crea el botón const toggleButton = document.createElement('button'); toggleButton.id = 'toggle-sidebar-btn'; toggleButton.setAttribute('aria-label', 'Toggle reader view'); // Establece el icono inicial del botón toggleButton.innerHTML = iconVisible; // Añade el evento de clic al botón toggleButton.addEventListener('click', toggleReaderView); // Añade el botón al .site-body-center-column siteBodyCenterColumn.appendChild(toggleButton); } } // Función para iniciar el observador de mutaciones function waitForSiteBodyCenterColumn() { const observer = new MutationObserver((mutations, obs) => { if (document.querySelector('.site-body-center-column')) { addToggleButton(); applyInitialVisibilityState(); // Aplica el estado de visibilidad inicial obs.disconnect(); // Detiene el observador una vez que el .site-body-center-column ha sido encontrado } }); observer.observe(document.body, { childList: true, subtree: true, }); } // Función para verificar el parámetro de la URL y activar el reader-view si es necesario function checkURLParameter() { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get('reader') === 'true') { const markdownPreviews = document.querySelectorAll('.node-insert-event'); markdownPreviews.forEach(preview => { preview.classList.add('reader-view'); }); // Actualizar el icono del botón const toggleButton = document.querySelector('#toggle-sidebar-btn'); if (toggleButton) { toggleButton.innerHTML = iconHidden; } // Guardar el estado en localStorage localStorage.setItem('readerView', true); } } // Función para restablecer el estado de la vista de lectura después de la navegación function resetReaderViewAfterNavigation() { document.addEventListener('click', (event) => { if (event.target.closest('.site-body-left-column-site-logo, .nav-file-title, .nav-folder-title, .nav-file, .nav-folder')) { setTimeout(applyInitialVisibilityState, 100); // Espera un momento para que la navegación se complete } }); } // Función para restablecer el estado de la vista de lectura después de la carga completa de la página function resetReaderViewOnLoad() { window.addEventListener('load', applyInitialVisibilityState); } // Ejecuta la función waitForSiteBodyCenterColumn cuando el script se carga waitForSiteBodyCenterColumn(); // Verifica el parámetro de la URL al cargar la página checkURLParameter(); // Restablece el estado de la vista de lectura después de la navegación resetReaderViewAfterNavigation(); // Restablece el estado de la vista de lectura después de la carga completa de la página resetReaderViewOnLoad(); // END TOGGLE READER VIEW ``` ###### CSS (Standard site header) ```css /************************ READER ************************/ @media screen and (min-width: 751px) { #toggle-sidebar-btn { margin: 0px; width: 30px; background: none; padding: 5px; position: fixed; right: 5px; top: 5px; background: none; border-radius: 50%; background: var(--background-primary); opacity: 1; color: var(--component-title-color); z-index: 100; } .sliding-windows #toggle-sidebar-btn { right: 287px; top: 25px; } #toggle-sidebar-btn:hover { color: var(--color-base-100); background: var(--background-secondary); } #toggle-sidebar-btn:hover { cursor: pointer; } .theme-dark #toggle-sidebar-btn { top: 25px; } .site-body:has(.reader-view) #toggle-sidebar-btn { color: var(--component-title-color); } .site-body:has(.reader-view) #toggle-sidebar-btn::before { content: "Press r to switch view"; position: absolute; right: 33px; color: var(--text-faint); font-size: var(--font-smaller); } .site-body:has(.reader-view) .published-container .markdown-rendered h1 { margin-top: 0px; } .site-body:has(.reader-view) .markdown-preview-view { font-size: calc(0.8rem + 0.30vw); } .site-body:has(.reader-view) #toggle-sidebar-btn { top: 5px; background: transparent; } .site-body:has(.reader-view) #toggle-sidebar-btn:hover { background: none; } .sliding-windows .site-body:has(.reader-view) #toggle-sidebar-btn { right: 5px; } .published-container:has(.reader-view) .site-header { display: block; position: fixed; top: 0; z-index: 10; } .sliding-windows .site-body:has(.reader-view) .markdown-preview-view { padding-top:40px; } .published-container:has(.reader-view) .site-header .site-header-text::after { display: none; } .sliding-windows:has(.reader-view) .publish-renderer, .sliding-windows:has(.reader-view) .render-container, body:has(.reader-view) { background-color: var(--background-reader); } .site-body:has(.reader-view) .render-container-inner { margin: 0 auto; } body:not(.sliding-windows):has(.reader-view) .is-readable-line-width.has-outline.has-navigation .publish-renderer > .markdown-preview-view > .markdown-preview-sizer { margin-right: inherit; } body:not(.sliding-windows):has(.reader-view) .publish-renderer > .markdown-preview-view > .markdown-preview-sizer { margin: 0 auto; } .sliding-windows .publish-renderer:has(.reader-view) { position: sticky; width: 800px; flex: 0 0 800px; } .sliding-windows div.hover-popover.is-loaded .publish-renderer { width: inherit!important; flex:inherit!important; } .sliding-windows .site-body:has(.reader-view) .site-body-center-column, .sliding-windows .published-container.has-graph .site-body:has(.reader-view) .site-body-center-column { padding-right: 0px; } .site-body:has(.reader-view) .site-body-center-column { padding-left: 0px; box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1); margin-top: 40px; } .theme-dark .site-body:has(.reader-view) .site-body-center-column { border-top: 1px solid var(--divider-color); } .site-body:has(.reader-view) .page-header, .site-body:has(.reader-view) .mod-footer, .site-body:has(.reader-view) .outline-view-outer, .site-body:has(.reader-view) .graph-view-outer .published-section-header, .site-body:has(.reader-view) .site-footer, .site-body:has(.reader-view) .search-view-container, .site-body:has(.reader-view) .nav-view-outer, .site-body:has(.reader-view) .site-body-right-column, .site-body:has(.reader-view) .site-body-left-column-site-name, .site-body:has(.reader-view) .site-body-left-column-site-logo, .site-body:has(.reader-view) .site-body-left-column { display: none; } } @media screen and (max-width: 750px) { #toggle-sidebar-btn { display: none; } .site-body:has(.reader-view) .site-body-left-column { display: flex!important; } } @media screen and (max-width: 1024px) { #toggle-sidebar-btn { right: 10px; } } /************************ READER END ************************/ ``` ###### CSS (Side site header) ```css /************************ READER ************************/ @media screen and (min-width: 751px) { #toggle-sidebar-btn { margin: 0px; width: 30px; background: none; padding: 5px; position: fixed; right: 5px; top: 5px; background: none; border-radius: 50%; background: var(--background-primary); opacity: 1; color: var(--component-title-color); z-index: 100; } .sliding-windows #toggle-sidebar-btn { right: 287px; top: 25px; } #toggle-sidebar-btn:hover { color: var(--color-base-100); background: var(--background-secondary); } #toggle-sidebar-btn:hover { cursor: pointer; } .theme-dark #toggle-sidebar-btn { top: 25px; } .site-body:has(.reader-view) #toggle-sidebar-btn { color: var(--component-title-color); } .site-body:has(.reader-view) #toggle-sidebar-btn::before { content: "Press r to switch view"; position: absolute; top: 82px; right: -47px; transform: rotate(90deg); color: var(--text-faint); font-size: var(--font-smaller); } .site-body:has(.reader-view) .published-container .markdown-rendered h1 { margin-top: 0px; } .site-body:has(.reader-view) .markdown-preview-view { font-size: calc(0.8rem + 0.30vw); } .site-body:has(.reader-view) #toggle-sidebar-btn { top: 5px; background: transparent; } .site-body:has(.reader-view) #toggle-sidebar-btn:hover { background: none; } .sliding-windows .site-body:has(.reader-view) #toggle-sidebar-btn { right: 5px; } .published-container:has(.reader-view) .site-header { display: block; position: fixed; top: -2px; right: 20px; z-index: 10; background: var(--background-primary); height: auto; } .sliding-windows .site-body:has(.reader-view) .markdown-preview-view { padding-top:40px; } .published-container:has(.reader-view) .site-header .site-header-text::after { display: none; } .sliding-windows:has(.reader-view) .publish-renderer, .sliding-windows:has(.reader-view) .render-container, body:has(.reader-view) { background-color: var(--background-reader); } .site-body:has(.reader-view) .render-container-inner { margin: 0 auto; } body:not(.sliding-windows):has(.reader-view) .is-readable-line-width.has-outline.has-navigation .publish-renderer > .markdown-preview-view > .markdown-preview-sizer { margin-right: inherit; } body:not(.sliding-windows):has(.reader-view) .publish-renderer > .markdown-preview-view > .markdown-preview-sizer { margin: 0 auto; } .sliding-windows .publish-renderer:has(.reader-view) { position: sticky; width: 800px; flex: 0 0 800px; } .sliding-windows div.hover-popover.is-loaded .publish-renderer { width: inherit!important; flex:inherit!important; } .sliding-windows .site-body:has(.reader-view) .site-body-center-column, .sliding-windows .published-container.has-graph .site-body:has(.reader-view) .site-body-center-column { padding-right: 40px; } .site-body:has(.reader-view) .site-body-center-column { padding-left: 0px; box-shadow: none; } .site-body:has(.reader-view) .page-header, .site-body:has(.reader-view) .mod-footer, .site-body:has(.reader-view) .outline-view-outer, .site-body:has(.reader-view) .graph-view-outer .published-section-header, .site-body:has(.reader-view) .site-footer, .site-body:has(.reader-view) .search-view-container, .site-body:has(.reader-view) .nav-view-outer, .site-body:has(.reader-view) .site-body-right-column, .site-body:has(.reader-view) .site-body-left-column-site-name, .site-body:has(.reader-view) .site-body-left-column-site-logo, .site-body:has(.reader-view) .site-body-left-column { display: none; } } @media screen and (max-width: 750px) { #toggle-sidebar-btn { display: none; } .site-body:has(.reader-view) .site-body-left-column { display: flex!important; } } @media screen and (max-width: 1024px) { #toggle-sidebar-btn { right: 10px; } } /************************ READER END ************************/ ```