Skip to content

Minimal, Responsive, Pure JavaScript, Single Page App. Get the functionality of Bootstrap and React, minus the bloat and complication.

i1li/i1li.github.io

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minimal, Responsive, Pure JavaScript, Single Page App

Minimal, no frameworks, just pure JavaScript (a.k.a. vanilla JavaScript), CSS, & HTML, Single Page App (SPA)
Responsive Design: images, video, & text automatically adjust to fit accordingly across small & large screens.
Light/Dark Mode, Page Zoom, Full Screen Image Overlay, Go to Top Button, Embedded Content Display Toggle,
Target Links as Subpages, Custom CSS Color-Shifting Gradients, Lazy Loading, External Link Handling.
Open in GitHub Codespaces Deploy to Netlify Open in VSCode
Demo site contains my personal writing & learning resources.
Quickstart: Use a quick deploy button above, or clone this repo locally, open a terminal in the project directory,
& enter either:

npm i express
node serv.js

(the simplest option), or, if you'd like to use Netlify's serverless functions, enter the following. (example of serverless function.)

npm i netlify-cli
netlify dev
  • For SPA (Single Page App) routing across different hosting environments, the app uses netlify.toml on Netlify, or
  • 404.html & github-pages.js on GitHub Pages, or
  • serv.js elsewhere.
  • Enables seamless navigation within the application without full page reloads, improving user experience without complication of a framework.
  • Default "display all posts" view at root directory, with posts auto-expanding upon scroll, shows a welcome intro message & navigation links at top of page.
  • Individual post view at unique URLs removes the welcome intro from display, & autoscrolls post header to top. Also clones a copy of the post navigation links shown in the post header, to the bottom of post.
  • Manages browser history & navigation state using the History API (history.pushState & window.onpopstate), allowing for bookmarkable URLs & functional forward/backward navigation.
  • Implements custom logic to show/hide content based on the current navigation state, simulating the behavior of a multi-page application within a single HTML document.
  • Allows proper permalinks for specific areas of posts (target links, a.k.a. hashlinks or subpages), so they get a url of /route/target instead of /route#target
  • Demo at /edu/mind
  • Easy to use YouTube embed that saves space, bandwidth, & privacy. With a bare amount of code (<y-t v="videoid"></y-t>), it responsively fits videos & playlists that only load once user clicks "show/hide" button. Demo at /edu
  • Updates all <y-t> elements on the page, <y-t v="YouTube Video ID"> becomes <y-t v="YouTube ID" t="The Video's Title"> To use, open a terminal in the project directory, & enter:
node yt-titles.js
  • Extracts all IDs found within the 'v' attribute of <y-t> tags.
  • For playlists, it gets all the available video IDs for each, then moves the playlist ID from the 'v' attribute to 'p', listing all video IDs in the 'v' attribute. To use, put your API Key in the empty quotes at const KEY = "", & then open a terminal in the project directory, & enter:
node yt-ids.js
  • proccessAndCombine combines all video IDs, (limiting how many come from each playlist), from the music section into one <y-t> element, at the top of /edu/vibes.
  • shuffleAndDraw shuffles an array of playlists & videos extracted from the music section, with its own 'next' button. It then "draws" from the shuffled array, cloning the drawn <y-t> element into the 'draw' <div>. Demo at top of main page
  • The order of the elements is shuffled at each page load, as well as the video IDs within each element.
  • Limited to specific divs so playlist order is preserved in other sections of the site.
  • Since shuffled playlists are constructed with each video ID in the URL, there is a limit of 150 per playlist, although each shuffle picks from the entire list of video IDs (in this case several thousand for the combined playlist)
More info on the shuffle function The hybrid shuffle function combines two different techniques to optimize performance for a wide range of input array sizes. The first is the "Knuth Shuffle" (a.k.a. "Durstenfeld Shuffle"), which has a time complexity of O(n * log n), where n is the size of the input array. This is a variation of the Fisher-Yates shuffle algorithm that is optimized for small arrays. For larger arrays, the function uses the standard Fisher-Yates shuffle algorithm, which has a time complexity of O(n), where n is the size of the input array. The decision to use which shuffle method, is based on the size of the input array in relation to the limit parameter (limit is how many items are used from the array after shuffling): If the array length is less than limit * 2, the Knuth Shuffle is used. If the array length is greater than or equal to limit * 2, the Fisher-Yates Shuffle is used.

Light/Dark Mode Toggle

  • Allows users to switch between light & dark themes, enhancing accessibility & user preference.
  • Utilizes window.matchMedia to detect & respect the system's preferred color scheme, & localStorage to persist the user's theme choice across sessions.

Zoom In/Out Functionality

  • Provides users with the ability to adjust the text size for better readability.
  • Dynamically adjusts the font size of key elements on the page based on user interaction, with the zoom level persisted in localStorage.
  • Responsive full screen overlay when user clicks to expand image. Exits by clicking anywhere, pressing any key, or clicking "x"

Background Gradient Shift, & other CSS Effects

  • background.js & background.css create a constant shifting gradient by creating & replacing blended layers.
  • Several layers of semi-transparent gradients for background & page elements.
  • Dynamic cursor hover & filter effects.
  • color-change.js - Random color on hover, click, or touch of links and buttons. Also shifts colors of other elements at randomly varying rate, regardless of hover.

Sticky Header & Scroll-to-Top Button

  • Improves navigation & accessibility by providing a sticky header & a convenient way to return to the top of the page.
  • The sticky header adjusts its style based on the scroll position, becoming more compact as the user scrolls down.
  • A "scroll to top" button appears after scrolling down, allowing quick return to the top of the page with a single click.

Responsive Design

  • Responsive container styling with automatic margin and maximum width adjustments based on screen size (.container with various @media queries)
  • Get the performance of Bootstrap, minus the bloat and complication.

Lazy Loading

  • Uses the IntersectionObserver API for lazy loading content as it becomes visible, reducing initial load time.
  • This gives the main view at the root URL an infinite scroll for all posts.
  • Identifies & handles external links to ensure they open in a new tab, preserving SPA integrity.
  • Checks the URL of clicked links & sets them to open in a new tab if they lead outside the current domain, using target="_blank" & rel="noreferrer" for privacy & security.
  • Easy solution for an email-verified contact form, and simple free content gating. Kept on a separate site for simplicity in this case, but easily integrated.

Efficiency & Minimalism

  • The code demonstrates efficient use of native JavaScript APIs to achieve functionality often reliant on external libraries, showcasing a minimalist approach that reduces load times & dependency overhead.
  • By combining CSS class toggles, native browser APIs, & simple event handling, it achieves a responsive, user-friendly SPA experience with minimal code.

This SPA implementation is a testament to the power of modern JavaScript & browser capabilities, allowing full-featured creation of rich, interactive web applications without any reliance on frameworks or libraries.