Sidopanelens teknik
Uppdaterad dokumentation: Denna sida innehåller detaljerad information om hur sidopanelen och huvudinnehållet samverkar, AJAX-teknik för dynamisk innehållsladdning, och tips för bildcollage-hantering.
Gamla tekniken
Den ursprungliga hemsidan använde HTML frames för att dela upp sidan i en sidopanel och ett huvudinnehåll. Detta var en vanlig teknik på 90-talet, men har sedan dess blivit föråldrad av flera anledningar:
- Frames är inte längre stödda i HTML5
- Frames kan orsaka problem med sökmotorer då varje frame indexeras separat
- Frames kan vara svåra att hantera responsivt för mobila enheter
- Frames kan orsaka problem med bokmärken, delning av länkar och navigationshistorik
Här är ett exempel på hur den gamla tekniken såg ut:
<frameset cols="200,*"> <frame src="sidebar.html" name="sidebar"> <frame src="main.html" name="main"> </frameset>
Nya tekniken
Den nya hemsidan använder moderna webtekniker för att uppnå samma funktionalitet som frames gav, men på ett mer modernt och flexibelt sätt:
- HTML5 semantisk struktur med <nav> och <main> element för bättre tillgänglighet och SEO
- CSS för layout och responsiv design som anpassar sig till olika skärmstorlekar
- JavaScript för dynamisk innehållsladdning och interaktivitet
- AJAX för att ladda innehåll utan att ladda om hela sidan, vilket ger en smidigare användarupplevelse
Här är ett exempel på den nya strukturen:
<body> <div class="menu-toggle">☰</div> <div class="overlay"></div> <nav id="sidebar"> <!-- Sidopanelsinnehåll --> </nav> <main> <!-- Huvudinnehåll --> </main> <script src="script.js"></script> </body>
Förhållandet mellan sidopanel och huvudinnehåll
På moderna webbplatser används vanligtvis två huvudkomponenter för layout: sidopanelen (sidebar) och huvudinnehållet (main content).
Sidopanelen (Sidebar)
Sidopanelen är den fasta navigationssektion som oftast finns på vänster sida av skärmen. Den innehåller:
- Navigationsmenyer
- Länkar till viktiga sektioner
- Tillbaka-till-startsida länkar
- Ibland även kontaktinformation eller sociala medier-länkar
I HTML representeras den av <nav id="sidebar">
elementet.
Huvudinnehållet (Main Content)
Huvudinnehållet är det dynamiska området där det primära innehållet visas. Det kan vara:
- Text och artiklar
- Bildgallerier
- Formulär
- Dynamiskt innehåll som laddas in via AJAX
I HTML representeras det av <main>
elementet.
Hur de samverkar
Förhållandet mellan sidopanelen och huvudinnehållet är nyckeln till en välfungerande webbplats:
- Fast vs. Dynamisk: Sidopanelen förblir oftast stationär medan huvudinnehållet uppdateras dynamiskt när användaren navigerar.
- Kontextuell navigering: Sidopanelen anpassar sina länkar baserat på var i hierarkin användaren befinner sig.
- Responsivitet: På mobila enheter döljs sidopanelen ofta och kan visas vid behov genom en menyknapp.
- Samordnad uppdatering: När innehållet i huvuddelen ändras måste sidopanelens länkar anpassas för att undvika brutna länkar.
Viktigt att tänka på: När man implementerar en sidopanel och huvudinnehåll utan frames krävs JavaScript för att upprätthålla riktig navigering mellan sidorna och för att hantera webbläsarens historik (tillbaka-knapp).
Kodexempel: Grundläggande struktur
<!-- HTML struktur --> <div class="container"> <nav id="sidebar"> <h2><a href="/">Tillbaka till hemsidan</a></h2> <div class="nav-section"> <h3>Navigering</h3> <ul> <li><a href="sida1.html">Sida 1</a></li> <li><a href="sida2.html">Sida 2</a></li> </ul> </div> </nav> <main> <!-- Huvudinnehåll som laddas dynamiskt --> </main> </div> <!-- CSS för layout --> <style> .container { display: flex; } #sidebar { width: 250px; position: fixed; height: 100vh; overflow-y: auto; background-color: #f5f5f5; } main { margin-left: 250px; flex: 1; padding: 20px; } @media (max-width: 768px) { #sidebar { transform: translateX(-100%); } main { margin-left: 0; } } </style>
AJAX-teknik för dynamisk innehållsladdning
AJAX (Asynchronous JavaScript And XML) är en teknik som möjliggör att webbsidor kan uppdateras asynkront genom att utbyta data med en server i bakgrunden. Detta innebär att webbsidor kan uppdatera delar av sidan utan att behöva ladda om hela sidan.

Hur AJAX fungerar i vår implementation
I vår implementation av sidopanelen och huvudinnehållet använder vi AJAX för att:
- Fånga länkklick i sidopanelen
- Förhindra standardnavigeringen genom
event.preventDefault()
- Göra ett AJAX-anrop för att hämta innehållet från den länkade sidan
- Extrahera main-innehållet från det hämtade HTML-dokumentet
- Uppdatera huvudinnehållet med det nya innehållet utan att ladda om hela sidan
- Uppdatera URL:en med
history.pushState()
för att bibehålla navigeringshistoriken
Steg för steg: AJAX-processen
1. Fånga länkklicket
link.addEventListener('click', function(event) { // Förhindra standardnavigeringen event.preventDefault(); // Hämta URL:en från länken const url = this.getAttribute('href'); // Ladda innehållet loadContent(url); });
2. Ladda innehållet med fetch API
function loadContent(url) { // Visa laddningsindikator mainContent.innerHTML = '<div class="loading-indicator">' + 'Laddar innehåll...</div>'; // Hämta innehållet med fetch fetch(url) .then(response => response.text()) .then(html => { // Hantera innehållet här }) .catch(error => { // Visa felmeddelande }); }
3. Extrahera och uppdatera innehållet
.then(html => { // Skapa en temporär div för att parsa HTML const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); // Extrahera main-innehållet const newContent = doc.querySelector('main'); // Uppdatera huvudinnehållet if (newContent) { mainContent.innerHTML = newContent.innerHTML; } else { mainContent.innerHTML = doc.body.innerHTML; } // Uppdatera URL:en utan omladdning history.pushState({}, '', url); // Uppdatera sidopanellänkar updateSidebarLinks(url); });
4. Hantera navigeringshistorik
// Hantera webbläsarens bakåt/framåt-knappar window.addEventListener('popstate', function() { // Om vi navigerar till startsidan if (location.pathname === '/' || location.pathname === '/index.html') { mainContent.innerHTML = originalContent; return; } // För andra sidor, ladda innehållet loadContent(location.pathname); });
Fördelar med AJAX-tekniken
- Snabbare användarupplevelse - endast det nödvändiga innehållet laddas, inte hela sidan
- Smidigare övergångar - ingen fullständig omladdning av sidan vilket ger en mer applikationsliknande känsla
- Minskad serverbörda - bara delar av innehållet behöver skickas, inte hela HTML-strukturen
- Bibehållen sidopanel - sidopanelen förblir synlig och behöver inte laddas om för varje navigation
Utmaningar med AJAX-tekniken
- Komplexare JavaScript - kräver mer kodning för att hantera navigering, historik och länkhantering
- Korrekt URL-hantering - måste använda
history.pushState()
för att uppdatera URL och möjliggöra bokmärken - Relativa sökvägar - måste hantera relativa sökvägar i både HTML och CSS för innehåll som laddas dynamiskt
- Hantering av script - skript i dynamiskt laddade sidor måste utvärderas explicit
handleImageGalleryLinks()
efter att innehållet har laddats för att säkerställa att bildlänkar fungerar korrekt.
Länkhantering
En av de mest komplexa aspekterna av en dynamisk webbplats är hur länkarna hanteras mellan sidopanelen och huvudinnehållet. Särskilt viktig är hanteringen av relativa sökvägar när användaren navigerar mellan olika nivåer i webbplatsens hierarki.
Olika typer av länkar
- Absoluta sökvägar (börjar med /) - pekar från roten av webbplatsen, t.ex.
/intyg/certifikat.pdf
- Relativa sökvägar (t.ex. elin.html eller ./bilder/foto.jpg) - pekar relativt till aktuell sida
- Externa länkar (http://... eller https://...) - öppnas normalt i nytt fönster/flik
- Specialfiler (PDF, DOC, GIF, etc.) - kan ha särskild hantering
Intelligenta beslut om länköppning
För att bestämma hur en länk ska hanteras använder vi funktionen shouldOpenInNewWindow()
som analyserar länkens egenskaper:
function shouldOpenInNewWindow(link) { const url = link.getAttribute('href'); if (!url) return false; const isExternalLink = url.startsWith('http://') || url.startsWith('https://'); const isSpecialFile = url.toLowerCase().endsWith('.pdf') || url.toLowerCase().endsWith('.doc') || url.toLowerCase().endsWith('.docx') || url.toLowerCase().endsWith('.xlsx') || url.toLowerCase().endsWith('.zip'); const hasTargetBlank = link.hasAttribute('target') && link.getAttribute('target') === '_blank'; // Kontrollera om det är en bildgalleri-sida const isGalleryPage = isImageGalleryPage(url); // Kontrollera om det är en GIF-fil som länkas direkt från sidopanelen const isDirectGifLink = url.toLowerCase().endsWith('.gif') && link.closest('#sidebar') !== null; // Öppna i nytt fönster endast om det är en extern länk, specialfil eller explicit target="_blank" // och INTE om det är en bildgalleri-sida eller en direkt GIF-länk från sidopanelen return (isExternalLink || isSpecialFile || hasTargetBlank) && !isGalleryPage && !isDirectGifLink; }
Hantering av relativa sökvägar
När användaren navigerar mellan olika nivåer av webbplatsen (t.ex. från startsidan till /intyg/ och tillbaka) behöver länkarna i sidopanelen uppdateras för att reflektera den nya platsen. Detta hanteras genom:
function updateSidebarLinks(currentPath) { // Ta bort inledande och avslutande snedstreck för att få en ren sökväg const cleanPath = currentPath ? currentPath.replace(/^\/+|\/+$/g, '') : ''; // Om vi är i roten, återställ länkarna till originalstatus if (!cleanPath) { sidebarLinks.forEach(link => { const originalHref = link.getAttribute('data-original-href'); if (originalHref) { link.setAttribute('href', originalHref); } }); return; } // För varje länk i sidopanelen sidebarLinks.forEach(link => { const originalHref = link.getAttribute('data-original-href'); if (!originalHref) return; // Om länken har en absolut sökväg (börjar med /), gör den relativ if (originalHref.startsWith('/')) { // Ta bort inledande snedstreck const relativeHref = originalHref.substring(1); // Om vi är i en undermapp, lägg till ../ för att gå tillbaka till roten if (cleanPath) { const depth = cleanPath.split('/').length; const backToRoot = '../'.repeat(depth); link.setAttribute('href', backToRoot + relativeHref); } else { link.setAttribute('href', relativeHref); } } // Om länken har en relativ sökväg (börjar med ./ eller inte börjar med /) else if (originalHref.startsWith('./') || !originalHref.startsWith('/')) { // Om vi är i en undermapp, lägg till ../ för att gå tillbaka till roten if (cleanPath) { const depth = cleanPath.split('/').length; const backToRoot = '../'.repeat(depth); link.setAttribute('href', backToRoot + originalHref); } else { link.setAttribute('href', originalHref); } } }); }
Viktiga överväganden för länkhantering
- Spara originalvärden: Spara alltid original href för varje länk för att kunna återställa den
- Djupberäkning: Beräkna hur många "../" som behövs baserat på aktuell sökvägsdjup
- Olika behandling: Hantera olika länktyper (bilder, gallerisidor, dokument) på olika sätt
- Historikhantering: Använd history API för att uppdatera URL:en och möjliggöra bakåt/framåt-navigering
- Konsekvens: Var konsekvent i hur du hanterar olika typer av länkar över hela webbplatsen
- Att inte hantera relativa länkar korrekt när man navigerar mellan olika djup i mappstrukturen
- Att inte spara original href-värden, vilket gör det svårt att återställa länkar
- Att inte uppdatera URL:en med history.pushState(), vilket bryter webbläsarhistoriken
- Att inte hantera specialfall för olika filtyper (bilder, dokument, etc.)
Bildcollage och gallerihantering
Ett bildcollage eller galleri är ett effektivt sätt att visa en samling bilder på en webbsida. På denna webbplats används bildcollagen för att visa bilder på familjemedlemmar som Elin, Erik, Lotta och Kent.
Struktur för bildcollage
En bra bildcollage-struktur i HTML och CSS innehåller följande delar:
<!-- HTML-struktur för ett bildcollage --> <div class="gallery-container"> <h1>Bilder på Elin</h1> <div class="gallery-grid"> <div class="gallery-item"> <img src="./bilder/elin/bild1.jpg" alt="Elin 2019"> <div class="gallery-caption">Elin 2019</div> </div> <div class="gallery-item"> <img src="./bilder/elin/bild2.jpg" alt="Elin 2020"> <div class="gallery-caption">Elin 2020</div> </div> <!-- Fler bilder... --> </div> </div> <!-- CSS för bildcollage --> <style> .gallery-container { max-width: 1200px; margin: 0 auto; padding: 20px; } .gallery-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; padding: 20px; } .gallery-item { position: relative; overflow: hidden; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); transition: transform 0.3s ease; aspect-ratio: 1; /* Viktigt för jämna proportioner */ } .gallery-item img { width: 100%; height: 100%; object-fit: cover; /* Viktigt för att hantera olika bildstorlekar */ display: block; } .gallery-caption { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.7); color: white; padding: 10px; opacity: 0; transition: opacity 0.3s ease; } .gallery-item:hover .gallery-caption { opacity: 1; } </style>
Viktiga aspekter för bildcollage
1. Proportioner och storlek
- Använd aspect-ratio: Säkerställer att alla bildcontainrar har samma proportioner, oavsett innehåll
- object-fit: cover: Ser till att bilden fyller hela containern utan att förvrängas
- Dynamiska kolumner: Använd
repeat(auto-fit, minmax(300px, 1fr))
för att låta galleriet anpassa antalet kolumner efter skärmstorlek - Gap: Definiera mellanrum mellan bilderna för ett snyggt och luftigt utseende
2. Användarupplevelse
- Hover-effekter: Lägg till svaga transformationer eller skuggeffekter vid hover
- Bildtexter: Visa bildtexter endast vid hover för en renare layout
- Mjuka övergångar: Använd
transition
för att skapa mjuka animationer - Klickbeteende: Se till att bilder öppnas i nytt fönster eller i en lightbox
Utmaningar med dynamiskt laddade gallerier
När bildgallerier laddas dynamiskt via AJAX kan vissa utmaningar uppstå:
- CSS laddas inte: Inline-CSS i huvudet på den laddade sidan kan ignoreras
- JavaScript för galleri körs inte automatiskt: Skript i laddade sidor måste köras explicit
- Relativa sökvägar till bilder kan brytas: Beroende på navigationssökväg
- Bildstorlekar kan variera: Vilket kan skapa ett ojämnt collage
Vår lösning med JavaScript
För att säkerställa att bildcollagen fungerar korrekt när de laddas dynamiskt via AJAX har vi implementerat följande lösning:
// Kontrollera om det är en bildgalleri-sida if (isImageGalleryPage(url)) { console.log("Bildgalleri-sida laddad:", url); // Försök hitta .gallery-grid elementet const galleryGrid = mainContent.querySelector('.gallery-grid'); console.log("Gallery grid element:", galleryGrid); if (galleryGrid) { // För bildgalleriet, hitta alla gallery-item element const galleryItems = galleryGrid.querySelectorAll('.gallery-item'); console.log("Gallery items:", galleryItems.length); // Säkerställ att CSS för galleri laddas korrekt galleryGrid.style.display = 'grid'; galleryGrid.style.gridTemplateColumns = 'repeat(auto-fit, minmax(300px, 1fr))'; galleryGrid.style.gap = '20px'; // Justera bilderna i galleriet galleryItems.forEach(item => { item.style.position = 'relative'; item.style.overflow = 'hidden'; item.style.borderRadius = '10px'; item.style.boxShadow = '0 4px 8px rgba(0,0,0,0.1)'; item.style.transition = 'transform 0.3s ease'; item.style.aspectRatio = '1'; const img = item.querySelector('img'); if (img) { img.style.width = '100%'; img.style.height = '100%'; img.style.objectFit = 'cover'; img.style.display = 'block'; } const caption = item.querySelector('.gallery-caption'); if (caption) { caption.style.position = 'absolute'; caption.style.bottom = '0'; caption.style.left = '0'; caption.style.right = '0'; caption.style.background = 'rgba(0,0,0,0.7)'; caption.style.color = 'white'; caption.style.padding = '10px'; } }); } }
Bästa praxis för bildcollage
- Optimera bilderna för webben med rätt storlek och komprimering
- Var konsekvent med bildstorlekar och proportioner
- Använd CSS Grid eller Flexbox istället för tabeller eller flyt-baserade layouter
- Testa på olika enheter för att säkerställa responsivitet
- Använd lazy loading för bilder som inte är direkt synliga
- Inkludera alternativtext (alt) för alla bilder
- Överväg användning av thumbnails för stora bildsamlingar
Responsiv design
Responsiv design är avgörande för moderna webbplatser. Till skillnad från den gamla tekniken med frames, som var svår att göra responsiv, använder vår nya tekniklösning CSS och JavaScript för att anpassa sig efter användarens enhet.
Nyckelkomponenter i vår responsiva design
Mobil meny med toggle
På mobila enheter döljs sidopanelen som standard och kan visas med en menyknapp. Detta sparar värdefullt skärmutrymme på små enheter.
// Toggle för mobilmeny document.querySelector('.menu-toggle') .addEventListener('click', function() { document.getElementById('sidebar') .classList.toggle('nav-active'); document.querySelector('.overlay') .classList.toggle('overlay-active'); }); // Stäng menyn när man klickar utanför document.querySelector('.overlay') .addEventListener('click', function() { document.getElementById('sidebar') .classList.remove('nav-active'); document.querySelector('.overlay') .classList.remove('overlay-active'); });
CSS Media Queries
Med media queries kan vi definiera olika stilar för olika skärmstorlekar. Detta är grundläggande för responsiv design.
/* Grundläggande stilar för alla skärmstorlekar */ #sidebar { width: 250px; position: fixed; height: 100vh; background-color: #f5f5f5; transition: transform 0.3s ease; } main { margin-left: 250px; padding: 20px; transition: margin-left 0.3s ease; } /* Anpassningar för små skärmar */ @media (max-width: 768px) { #sidebar { transform: translateX(-100%); z-index: 1000; } #sidebar.nav-active { transform: translateX(0); } main { margin-left: 0; } .menu-toggle { display: block; } .overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 900; } .overlay-active { display: block; } }
Responsiva bildcollage
För att göra bildcollagen responsiva använder vi CSS Grid med auto-fit
och minmax
:
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; padding: 20px; }
Denna CSS-kod gör att:
- På stora skärmar visas flera bilder per rad
- När skärmen blir mindre, minskar antalet bilder per rad automatiskt
- På mobila enheter visas vanligtvis en bild per rad
- Varje bild har minst 300px bredd, men kan expandera för att fylla tillgängligt utrymme
Viktiga principer för responsiv design
- Mobile First: Designa först för mobila enheter och lägg sedan till funktionalitet för större skärmar
- Flytande layout: Använd procentuella breddvärden istället för fasta pixelvärden
- Flexibla bilder: Säkerställ att bilder aldrig blir större än deras container
- Läsbar text: Se till att text alltid är läsbar oavsett skärmstorlek
- Touch-vänliga gränssnitt: Knappar och länkar bör vara tillräckligt stora för fingrar på pekskärmar
- Progressiv förbättring: Börja med grundläggande funktionalitet och lägg till mer avancerade funktioner för enheter som stöder dem
Testning av responsiv design
För att säkerställa att webbplatsen fungerar korrekt på alla enheter bör du regelbundet testa den på:
- Olika webbläsare (Chrome, Firefox, Safari, Edge)
- Olika skärmstorlekar (desktop, tablet, mobil)
- Olika orientering (liggande och stående)
- Olika pixeldensiteter (standardskärmar och högupplösta skärmar)
- Att inte testa på tillräckligt många olika enheter
- Att använda för små touch-mål på mobila enheter
- Att hårdkoda pixelstorlekar istället för att använda relativa enheter
- Att dölja viktigt innehåll på mobila enheter
- Att inte optimera bilder för mobila nätverk
Sammanfattning och slutsatser
I denna dokumentation har vi utforskat de tekniska aspekterna av vår implementering av sidopanel och huvudinnehåll på kentlundgren.se. Här är de viktigaste punkterna att komma ihåg:
Arkitektur
- Moderna HTML5 semantiska element ersätter föråldrade frames
- CSS för layout och responsivitet på alla enheter
- JavaScript och AJAX för dynamisk innehållsladdning
- History API för korrekt URL-hantering och navigering
Nyckelkomponenter
- Sidopanelen: Fast navigationspanel med länkar
- Huvudinnehållet: Dynamiskt innehåll som uppdateras via AJAX
- Bildcollage: Responsiva rutnät för bildvisning
- Länkhantering: Intelligent hantering av relativa och absoluta länkar
Fördelar med den nya tekniklösningen
- Bättre användarupplevelse med smidigare navigering
- Förbättrad responsivitet på olika enheter
- Bättre SEO genom semantisk HTML5
- Enklare underhåll och uppdatering
- Framtidssäkrad kodstruktur enligt moderna standarder
Framtida utvecklingsmöjligheter
- Implementera en laddningsindikator för AJAX-anrop
- Lägga till animationer vid innehållsbyten
- Förbättra cachehantering för snabbare navigering
- Implementera lazy loading för bilder i galleriet
- Lägga till lightbox-funktionalitet för bildvisning