To English version

Technisch ontwerp van de website

Introductie

Zorg voor een voldoende breed scherm om deze toelichting te kunnen zien, bijvoorbeeld door je smart­phone horizontaal te houden.

© Ton Kostelijk, Veldhoven 2022, 2023.
webtech Deze webpagina beschrijft het technisch ontwerp en realisatie van de website en de problemen en oplossingen die zich tijdens de ontwikkeling voordeden. De lezer wordt verondersteld enige basiskennis van HTML en CSS te hebben. HTML bestanden bevatten de content. Deze wordt gekoppeld met tags* aan opmaakstijlen die in CSS gedefinieerd zijn.



Het doel van het ontwerp is dat de website goed functioneert en er goed uit ziet op de volgende platformen: PC, laptop, tablet en smartphone (in horizontale en verticale houding). Dit ook met verschillende webbrowsers als Firefox, Edge, Google Chrome en Safari. De grootste uitdagingen geven smartphones met hun beperkte schermgroottes, én twee zeer verschillende hoogte-breedte verhoudingen en soms afwijkende brow­sers.
Waar gaat het concreet om? Ten eerste gaat het om een heldere schermindeling, ten tweede om het realiseren van een goed werkend menu systeem om te kunnen navigeren binnen de website, zowel met muis- als aanrakingsbediening. Tenslotte gaat het om flexibele oplossingen voor verschillende schermformaten, zodat schermindeling, tekst, plaatjes en menu's goed zichtbaar of bereikbaar zijn en de eventuele beperkte ruimte goed benut wordt. Met het woord scherm wordt ook venster bedoeld als er meerdere applicaties op een scherm zichtbaar zijn.
Om het resultaat te beoordelen kunnen de webpagina's het beste op een laptop of PC bekeken worden, waarbij het formaat van het venster gevarieerd wordt: smal, breed, hoog, laag, etc. Op deze webpagina is alles al te zien, uitgezonderd de thuispagina. Web­browsers ondersteunen ook simulatoren voor allerlei tablets en smartphones. De broncode kan via de webbrowser gelezen worden, zet daartoe view-source: voor de url, handmatig, of via het commando control-u.
Als technische informatiebron is gebruik gemaakt van w3schools en de hulpmiddelen voor de web­ontwikkelaar in Firefox en Chrome. Als context gevoelige broncode editor is Notepad++ gebruikt.

*  Een tag is letterlijk vertaalt een label, maar in HTML hebben 'tag' en 'label' ieder een eigen betekenis. Daarom is de vertaling achterwege gelaten. Verderop in de tekst is het HTML begrip 'anchor' ook onvertaald gebleven.

Opzet en indeling

Deze website bestaat uit een twintigtal webpagina's. Er is één HTML bestand per webpagina die gebruik maakt van het gemeenschappelijke CSS bestand, style.css dat klassen bevat. Er is geen gebruik gemaakt van scripting. Een klasse definieert opmaak, een combinatie van formattering, layout en kleur eigenschappen. Hierin wordt een afstand of grootte (b.v. breedte), absoluut weergegeven (b.v. 10px, px = pixels), relatief (b.v. 10%) of met een expressie door gebruik te maken van calc, min en max. Daarnaast bevat een CSS bestand identiteiten. Een identiteit (afkorting: id) is een klasse die maar 1x per pagina wordt gebruikt.

De indeling van een webpagina wordt in de volgende vier figuren getoond, waarbij de lichtblauwe achtergrond het scherm of venster aangeeft.
 

header

zij-
me-
nu




main




footer

Algemene pagina

 icon
headertext
headertext
topmenu


main


footer



Welkompagina

icon
headertext
topmenu



zij-
me-
nu



main


footer

Andere pagina's
breed scherm



icon

Z
header-
tekst
top-
menu

main



footer


zij-
me-
nu




Andere pagina's
smal scherm
 
Een algemene webpagina van deze website bestaat uit een header, het main gedeelte en een kleine footer. Verder is er optioneel een zijmenu links naast het main deel. Een header bestaat uit het icon, headertext en topmenu. De precieze opbouw van de header is verschillend voor de thuispagina (welkompagina) en andere pagina's. Bij een smal scherm splitst het topmenu (en headertext) zich op over twee rijen als het niet meer op één rij past. Ook is voor een smal scherm het optionele zijmenu standaard buiten beeld, zodat er meer ruimte voor main overblijft. Als de linkerzijde van het scherm wordt aangeraakt verschuift het zijmenu binnen beeld, over de linkerkant van main heen. Ook kan het kleine zijmenu-icon Z aangeraakt worden. Deze geeft met zijn aanwezigheid aan dat er links buiten beeld een zijmenu is.

De welkom pagina

De welkom pagina is eenvoudiger dan de anderen. Deze heeft geen zijmenu en de header zit gewoon altijd boven main, en beweegt mee met scrollen. Er staat meer tekst in de header dan bij de andere pagina's. De welkom pagina is vrij kort en het topmenu staat in het midden, navigatie naar andere pagina's is onder handbereik. Het meest rechtse element van het topmenu is een Engelse vlag, om naar de Engels versie van de website te kunnen gaan.
Om bij kleine schermen met de schaarse ruimte om te gaan, wordt het logo kleiner naarmate het scherm smaller wordt. Als de schermhoogte onder een bepaalde waarde zakt verkleint de hoogte van de hele header door een @media only screen declaratie in het css bestand.

Probleem: Op een smal scherm, zoals een smartphone in verticale houding, is het icon te klein en de headertext rommelig door ruimtegebrek.
Oplossing: Laat het icon en het tekstvak gedeeltelijk overlappen in de welkomheader, zoals de figuur ook laat zien. De tekst vouwt zich nu om het figuur van de icon. Dit overlappen is gedaan met een negatieve margin-left.
Detail: dit werkt niet in een td tag maar wel in een div tag, vandaar dat het tekstvak in de td in een div element is ingepakt.

De andere pagina's

Om ruimte te sparen heeft de header van de andere pagina's een veel kleinere hoogte dan in de welkompagina, minder headertext en het topmenu zit bovenin. Als al genoemd kan het zijmenu links buiten beeld geplaatst worden om main meer ruimte in de breedte te geven.

Probleem: Bij het naar beneden scrollen verdwijnt het topmenu snel uit beeld en is navigatie buiten bereik.
Oplossing: De header krijgt position: fixed. Zo blijft de header met het topmenu altijd zichtbaar bovenin het scherm vastgepind. Bij verticaal scrollen beweegt main er als het ware onderdoor. Daarom is de header hierboven getekend met dikke rand, en is de bovenste rand van main weggelaten. Ook het zijmenu krijgt position: fixed zodat je deze altijd kunt gebruiken om te navigeren binnen de pagina. Wel moet deze bij een smal scherm soms eerst vanaf links tevoorschijn gehaald worden door de linkerkant aan te raken.

Probleem: Op een ondiep scherm, zoals bij een smartphone in horizontale houding, valt het zijmenu gedeeltelijk onder het beeld. Er kan ook niet naar gescrold worden, want deze is 'fixed', vastgepind aan de positie buiten beeld.
Oplossing: Schuif op een ondiep scherm het zijmenu omhoog dichtbij het icon. Verklein de tussenruimte tussen de knoppen zodat maximaal 4 knoppen passen. Als er meer dan 4 knoppen in het menu zijn, dan worden deze gedeeltelijk in submenu's ondergebracht. Op een breed scherm strekt dit submenu zich uit naar rechts, op een smal scherm (zoals smartphone in verticale houding) naast het zijmenu naar beneden. Deze scherm breedte/hoogte afhankelijkheden zijn gerealiseerd met @media only screen declaraties in CSS.

Menu's

Een menu is in wezen een rij knoppen met in elke knop een link. Door op een knop te klikken (met de muis) of tikken (bij aanraakbediening) navigeert de webbrowser naar een andere plek binnen de website. Ook verandert het uiterlijk van de knop bij klikken/tikken, idem bij aanraking.
Het topmenu dient om tussen webpagina's te navigeren. Elke knop van het topmenu heeft naast een link ook een submenu dat normaal onzichtbaar is. Het submenu bestaat uit een rij knoppen met directe toegang binnen de topmenu pagina (of het biedt een ruimere keuze van webpagina's). Het submenu van een knop verschijnt bij aanraking van de menuknop (met muis of vinger).
Het zijmenu dient om binnen de pagina direct naar bepaalde plekken (de zogenaamde anchors) te springen. Een zijmenuknop heeft ook een submenu als er veel anchors zijn, b.v. in Uitgebreid.html. Dit zou anders een te lang zijmenu geven met te veel knoppen onder elkaar.
De realisatie van een menu of submenu is als volgt. Elk menu is een rij knoppen. Een rij is in HTML een lijst ul, waarin elk lijstitem li een knop (een link a) bevat en optioneel een submenu. De knop van een submenu heeft geen sub-submenu. De opmaak van het menu en de knoppen, en het effect na aanraking van een knop, wordt bepaald door de gebruikte CSS klasse. Het topmenu gebruikt de klasse navigation. Het zijmenu gebruikt de klasse linavigation. De locatie van het zijmenu wordt door id leftsidemenu bepaald. Deze is ook in CSS gedefinieerd.
Bij aanraking, hover, van een top- of zijmenuknop met submenu verandert de display eigenschap van de submenulijst van none (onzichtbaar) in block (zichtbaar). Tegelijk wordt hiermee het aanraakgevoelige gebied uitgebreid met de submenulijst omdat deze nu zichtbaar is geworden. Hierdoor kan de muis of vinger vervolgens een submenu knop aanklikken. Als het aanraakgevoelige gebied verlaten wordt, ofwel hover stopt, verandert de display eigenschap van de submenulijst weer in de standaard waarde, none (onzichtbaar). Ook krijgt de aangeraakte menuknop weer de standaard opmaak.
Het naar een anchor toe springen in een pagina is verfraaid door een animatie van een gladde verticale scroll beweging. Dit wordt gerealiseerd door in CSS de tag html de declaratie scroll-behavior: smooth te geven, mits ondersteund door de browser (zo niet: zie de details in CSS).
Ter vermaak wiegt het logo van de header na aanraking even heen en weer (dd dec 2023). Dit is gerealiseerd door logo:hover de wieganimation te laten triggeren. Deze is gedefinieerd met @keyframes en bestaat vooral uit twee rotates.

Menu's in een smal scherm

Als het scherm niet breed genoeg is breekt het topmenu af en komen de rest van de knoppen in een tweede rij (zie figuur 'Andere pagina's smal scherm'). De header wordt dan hoger. Het zijmenu staat voor smallere schermen links buiten het beeld, zodat main meer ruimte heeft door schermbreed te kunnen zijn. Het zijmenu verschijnt op de normale plek (bovenop de verbrede main) door het scherm aan de linker kant aan te raken, of door het zijmenu-icon Z aan te raken. Deze laatste bevindt zich op de grens van main en header aan de linker zijde. Een @media only screen declaratie in CSS herkent een breed scherm en maakt de ruimte voor een permanent zichtbaar zijmenu in main.
De vanaf buiten beeld links inschuivende variant van het zijmenu wordt in CSS gerealiseerd met de klassen popup-zijmenutop, popup-zijmenu, en ids leftsidemenu en leftsidemenutop. Het werkt op een vergelijkbare manier als dat een submenu verschijnt na aanraking van een menuknop. Alleen wordt nu door de aanraking niet display: none vervangen door display: block, maar margin-left: -8.5em (links ver buiten beeld) door margin-left: 10px (normale positie, bovenop main). Ook is het aanraakgevoelige gebied groter gekozen dan bij menuknoppen: de hele linkerkant van main is aanraakgevoelig. De verschuiving van buiten beeld naar binnen beeld kan geleidelijk verlopen als een animatie, door gebruik te maken van transition: margin-left 0.5s. Dit verduidelijkt waar het zijmenu vandaan komt, in plaats van een verschijning ogenschijnlijk uit het niets.
Ter vermaak maakt de kleine sidebarbutton Z dan een halve rotatie, alsof deze het zijmenu al draaiende binnen sleept. Dit is gerealiseerd met een transform: rotate die met een transition: transform 0.5s geanimeerd is.
Detail: na een halve rotatie is het schaduweffect van Z naar de tegenovergestelde kant meeverhuisd. Dat ziet er heel vreemd uit. Daarom is een aanvullende actie nodig om het schaduweffect box-shadow naar de gewone kant terug te brengen. Deze overgang van het schaduweffect (transition box-shadow) heeft bovendien een timing nodig die past bij de rotatie (namelijk de halve rotatietijd) om geen rare tijdelijke effecten te krijgen, zoals plotseling even een tegenovergestelde schaduw aan het begin of einde van de rotatie.

De 'fixed' header geeft problemen in main

De header van de andere pagina's heeft position: fixed, ofwel het topmenu ligt vast boven in het scherm boven op main. Om main helemaal zichtbaar te laten zijn, moet dus het bovenste stuk (waar de header zit) overgeslagen worden. Dit kan in principe door margin-top te gebruiken in main, zo kan main onder de header uit geschoven worden. Daarnaast is de hoogte van de header variabel, omdat het topmenu en de headertext uit 1 of 2 rijen kan bestaan, afhankelijk van de breedte van het scherm.

Probleem: Main heeft twee verschillende waarden van margin-top nodig, afhankelijk van de breedte van het scherm.
Oplossing: Dit is dynamisch instelbaar door gebruik te maken van @media only screen declaraties in CSS.
De main van de welkompagina heeft dit probleem niet. Daarom overschrijft deze de margin-top met een kleine vaste waarde.

Probleem: Bij het springen naar een anchor (vanuit het zijmenu of topsubmenu) scrolt de webbrowser het anchor bovenin het scherm, ofwel, verborgen onder de fixed header.
Oplossing: De oplossing bestaat uit twee elementen: de browser wijs maken dat de anchor hoger zit dan dat hij zit, en deze hoogte dynamisch instelbaar maken afhankelijk van de schermbreedte. Het eerste doen we door elke anchor vooraf te laten gaan door een lege span van klasse anchored. Door de details van deze klasse wordt de browser wijs gemaakt dat hij naar een hogere positie moet scrollen, zodat de anchor lager belandt, onder de header uit. De precieze werking staat als commentaar in CSS. De grootte van de aanpassing wordt dynamisch door @media only screen declaraties in CSS gerealiseerd.
(Mogelijk zou ditzelfde gerealiseerd kunnen worden door de eigenschap scroll-margin-top, al zegt w3schools er niets over en staat op diverse plekken dat deze eigenschap niet altijd werkt.)

Verbetering weergave van de headertext (dd nov 2023)

De headertext op de andere pagina's begon pal rechts naast het logo boven het topmenu. Dit is minder fraai. Het is mooier als deze tekst gecentreerd boven het topmenu staat. In elke andere pagina werd deze zin herhaald. Bij wijziging is dit onhandig, de zin kan het beste op één plek staan. Daarnaast is de afbreking van de headertext bij een smaller scherm niet zo mooi, het kan er dan b.v. als volgt uitzien:

Praktijk Ton Kostelijk - Voor ontspanning, pijnverlichting en zelf-
ontwikkeling

De oplossing is ten eerste om de headertext te centreren met text-align: center (in id headertext en headertexteng) en de juiste breedte berekening te geven van het topmenu (zie max-width). Ten tweede kan de zin in style.css opgenomen worden als twee halve niet-afbreekbare zinnen (met whitespace: nowrap). De vaak toegepaste   werkt hier niet want deze wordt letterlijk weergegeven, niet met zijn html betekenis als een non-breakable space. Als er te weinig ruimte komt breekt de zin precies af in de twee helften. Hiertoe moet er wel in de html-code,

<div id="headertext"><span id="htxt"> </span></div>,

een spatie staan (voor </span>), anders komt er geen whitespace afbrekingsmogelijkheid tussen de twee helften van de zin. (Ja, het kan subtiel zijn.) Met behulp van de selectoren ::before en ::after kunnen de twee helften in bestand style.css gedefinieerd worden, in de id htxt. Voor de Engelse versie kan hetzelfde gedaan worden met de id htxteng. Bovenstaande voorbeeld ziet er dan uit als:


Ook kan nu de klasse headertext hergebruikt worden op de Engelse pagina's. De klasse headertexteng is overbodig geworden.

Main: interne schaalbaarheid

Het main gedeelte is onderverdeeld in hoofdstukjes, met h2 opmaak voor de hoofdstuktitel. Een hoofdstuktitel heeft ook een anchor, zodat er naartoe gesprongen kan worden vanuit de menu's. De externe schaalbaarheid van het main gedeelte wordt bepaald door het zijmenu en de header: welke ruimte laten zij over voor main. Als hierboven beschreven krijgt het main deel meer ruimte in de breedte door het uit beeld schuivende zijmenu, en minder ruimte bovenin als het topmenu zich opsplitst over twee rijen.
Het main gedeelte kan verder intern op verschillende manieren omgaan met variabele breedtes/hoogtes van het scherm als volgt.
Woorden kunnen worden afgebroken aan het einde van een regel en op de volgende regel verder gaan, m.a.w., hyphenation is ingesteld voor Nederlands, in tag html met lang="nl". Als dit niet goed werkt in een woord kan met het zogenaamde soft-hyphen &shy; de afbreekplek aangegeven worden.
Voor sommige bezoekers kan meer informatie interessant zijn op specifieke punten. Dit kan je op de huidige webpagina optioneel tonen als popup of dropdown. Na aanraking zweeft de content van de popup boven de tekst met klassencombinatie popup, touchable, popup-content, zie in het Voorbeeld van HTML bovenaan deze pagina. De content van de dropdown wordt tijdelijk aan de tekst toegevoegd door de klassencombinatie popup, touchable, popup-content te hergebruiken, en door de position van popup-content te veranderen in relative.




Probleem: Centrering van popups (dd nov 2023)
Blokken of objecten die horizontaal gecentreerd zijn zien er beter uit dan als ze links geplaatste zijn. Helaas is niet eenvoudig te realiseren: er bestaat niet iets algemeen toepasbaar als 'align: center'. De methode om dit te doen is om te werken met "margin: auto" als de breedte bekend is, of door de linker positie en de breedte van het object expliciet te berekenen. Deze methoden zijn beiden gebruikt, respectievelijk, in de klassen touchable en popup-content. Als de content daarnaast een gelimiteerde maximale breedte (max-width) toegekend krijgt in html, zal ook de linkerpositie een minimale left positie toegekend krijgen, m.b.v. de functie min. Aangezien pulldown gerealiseerd wordt met de popup-klassen, werkt deze oplossing meteen ook voor pulldown.

Probleem: Hoe plaatjes te tonen als er weinig ruimte beschikbaar is.
Oplossing 1: Plaatjes kunnen groeien en krimpen met de schermbreedte door de breedte een percentage te laten zijn van de achtergrond, b.v. width: 15%. Ook moeten plaatjes niet te groot of te klein worden, dit kan als volgt in een style of klasse worden opgenomen: max-width:30% en min-width: 30px. Een handige combinatie is in de klasse righttopkwart vastgelegd. Deze positioneert een plaatje aan de rechterzijde, en geeft het een maximale breedte van een kwart.
Oplossing 2: Bij afnemende breedte kunnen plaatjes verhuizen van naast de tekst naar onder de tekst. Dit kan met 'wrap around', met behulp van de style display: flex; flex-wrap: wrap; flex-direction: row;. Alleen als details van het plaatje inhoudelijk belangrijk zijn, heeft oplossing 2 de voorkeur.

Soms wordt er voor gekozen om content pas zichtbaar te maken als de schermbreedte voldoende is. Dit wordt gerealiseerd met lokale style definities in HTML, door display: none of juist display: inline in te stellen, afhankelijk van de breedte met @media only screen declaraties. Om dit in actie te zien: bekijk deze pagina met een smartphone in verticale houding, en dan horizontaal. Als er geen enkele content meer staat kan het zijmenu beter ook onzichtbaar zijn.

Overlappingsproblemen (dd okt 2023)

Welk element boven ligt als elementen overlappen lijkt instelbaar te zijn met de z-index. Echter, de stapelingsvolgorde blijkt door veel meer zaken bepaald te worden. Het was even zoeken, maar het is uitstekend beschreven in 4 reasons why your z-index is not working (and how to fix it). Nu bevinden de topmenu- en zijmenuknoppen zich altijd boven de pagina inhoud.

Verbetering van footer (dd sept 2023)

De footer tekstregel onderaan elke pagina is veranderd in een rijtje knoppen zodat in 1 klik contact gemaakt kan worden. Implementatie: een iframe naar bestand contactinfo.html, met daarin bel, mail, app en adres knoppen. Om de knoppen ook aan de linkerkant van een smal scherm klikbaar te houden, moest het gevoelige gebied van het zijmenu verkleind worden. De hoogte van dit gebied is veranderd van 100% naar 60%. Dit betreft de klassen popup-zijmenu en popup-zijmenutop.

Tenslotte

Het is aardig om een website te maken alleen uitgaande van de HTML en CSS, en dat die dan toch werkt op zoveel systemen en webbrowsers. Het voordeel van de aanpak is dat alles onder eigen controle is, alles is aanpasbaar. Daarnaast is HTML en CSS goed gedocumenteerd en niet echt moeilijk. Accumulatie van meer technologieën, zoals het toevoegen van sjablonen en scripting, vergroot de complexiteit aanzienlijk en is daarom voorlopig achterwege gelaten.
Het ontwikkelproces is iteratief met elke keer voortschrijdende inzichten na een geconstateerd probleem, vaak na feedback van anderen. Het resultaat voldoet. Natuurlijk kan het altijd beter, daarom blijven suggesties welkom.
Mocht de website ook gegevensinvoer van de gebruiker gaan gebruiken, dan zou scripting (b.v. JavaScript of php) niet meer te vermijden zijn. Nu gaat interactie met de gebruiker via mail, telefoon, whatsapp of een ontmoeting.

Het belangrijkste van een website is hierboven onbenoemd gebleven. Dat zijn goede teksten, plaatjes, kortom, content. Hoe leg je kort de essentie van je boodschap uit op een prettige manier aan de doelgroep. Ook wat dat betreft blijven suggesties welkom.

© Ton Kostelijk, Veldhoven 2022, 2023.