HSL-kleurenkiezer met HTML en CSS

Maak zelf een HSL-kleurkiezer in HTML en CSS (3)

Handboek HTML 5 en CSS3Het boek van de maand oktober is Handboek HTML5 en CSS3, 5de editie van Peter Doolaard. Deze maand bespreken we het boek, geven we op dit blog wat voorproefjes uit het boek. Dit is deel 3 uit een serie over het maken van een HSL-kleurenkiezer met HTML, CSS en wat JavaScript. Lees ook deel 1, deel 2 en deel 4. Bezoek ook de site Handboek HTML5 en CSS3.

Tijd voor het vervolg van een serie over het maken van je eigen HSL-kleurkiezer. In deel 2 is met hulp van het schaduw-DOM de basisopmaak voor de regelaars ingesteld en kreeg de tintregelaar een kleurverloop volgens het HSL-systeem. Die kleur is niet meer dan een achtergrond. De werkelijke waarde komt uit het attribuut value. Hetzelfde geldt voor de andere regelaars. Met JavaScript kunnen we die waarden lezen en verwerken tot een CSS-kleurdeclaratie of de inhoud van een tekstveld.

De laatste opmaakregels

Er ontbreekt nog opmaak voor het kleurvak, het invoervak en de knoppen. Die voegen we nu eerst toe. De CSS bevat geen bijzonderheden.

.color-box {
  border: 1px solid black;
  height: 100px;
  margin: 6px 0 2px;
}
input[type="text"] {
  -webkit-appearance: none;
  border: none;
  font-size: 1.25em;
  margin: 2px 0;
  outline: 1px solid black;
  padding: 2px;
  text-align: center;
}
button {
  border: none;
  outline: 1px solid black;
  font-size: 1.25em;
  margin: 2px 0;
  padding: 4px;
}

Terug naar het doel

Wat was ook alweer het doel van de kleurkiezer?

  • Drie regelaars bieden waarmee je een HSL-kleur kunt maken.
  • Een veld tonen waarin de actuele kleur is te zien.
  • Een invoerveld (alleen-lezen) bieden waarin de waarde van de actuele kleur is te zien en kan worden gekopieerd naar het klembord.

Voor die eisen moeten we een volwaardige HSL-kleur kunnen samenstellen. Dat lukt alleen met regelaars die echt wat doen.

Van schuifregelaar naar kleur

We willen:

  • de waarden van de drie regelaars combineren tot een geldige HSL-kleurwaarde;
  • de resulterende kleur weergeven in een kleurvak;
  • de code van die kleur als CSS-declaratie tonen in een invoerveld.

Tijd voor wat JavaScript!

De JavaScript-code kan op twee manieren worden gebruikt (maar de tweede methode heeft de voorkeur).

  • Typ de JavaScript-code in een blok <script> ... </script> onder in het HTML-bestand, vlak boven de sluittag </body>.
  • Typ de JavaScript-code in een afzonderlijk bestand met de naam script.js (de naam is vrije keus, de extensie moet .js zijn). Typ onder in het HTML-bestand, vlak boven de sluittag </body>, de HTML-code <script src="script.js">.

Elk element op een HTML-pagina kan worden gevonden en gemanipuleerd met JavaScript. Sterker nog: je kunt elementen aan de pagina toevoegen en ze eruit verwijderen. Hetzelfde kan met HTML-attributen, CSS-klassen, inline stijlen en tekst. Dit is mogelijk dankzij het Document Object Model (DOM). Je kunt ook reageren op gebeurtenissen (events). Klikken (op een link of knop) is een gebeurtenis. De stand van een schuifregelaar veranderen is ook een gebeurtenis. Het is allemaal precies wat we nodig hebben.

Om een element te kunnen manipuleren hebben we een verwijzing naar dat element nodig. Omdat het telkens om een bepaald element gaat, gebruiken we de selector id als kenmerk. We pikken het element uit het document en wijzen het toe aan een variabele. We kunnen dan de variabele gebruiken als we dat bepaalde element nodig hebben voor een bewerking.

Nu is het belangrijk dat alle elementen zijn geladen voordat we op zoek gaan naar een bepaald element. Daarvoor is de gebeurtenis DOMContentLoaded. Om te beginnen luisteren we op het document of de gebeurtenis DOMContentLoaded heeft plaatsgevonden. Pas als dat zo is, gaan we verder.

document.addEventListener('DOMContentLoaded', () => {
  // code die wordt uitgevoerd als alle elementen zijn geladen
});

Nu maken we variabelen (const) voor de schuifregelaars. Elk element dat we met JavaScript willen benaderen, hebben we in de HTML een id gegeven. De namen zijn een persoonlijke keus. We maken ook gelijk variabelen voor het kleurvak en het invoerveld met de kleurcode.

document.addEventListener('DOMContentLoaded', () => {
  const colorSlider = document.getElementById('color-slider');
  const saturatSlider = document.getElementById('saturat-slider');
  const lightSlider = document.getElementById('light-slider');
  const colorBox = document.getElementById('color-box');
  const colorValueField = document.getElementById('color-value-field'); 
});
// dit sluit het luisteren naar DOMContentLoaded af

In de code kunnen we nu de regelaar voor de kleur benaderen met de variabele colorSlider. Om de inhoud van het attribuut value te krijgen, gebruiken we colorSlider.value.

Aangezien we de waarde van de kleurregelaars regelmatig nodig hebben, maken we ook daar variabelen voor. Die krijgen de waarde die we bij het starten van de app willen gebruiken.

  // voorgaande code is weggelaten
  let hue = 180;
  let sat = 100;
  let light = 50;
}); // dit sluit het luisteren naar DOMContentLoaded af

Nu kunnen we in de interface eindelijk een kleur en een kleurcode weergeven. De kleurcode komt in het invoerveld:

  // voorgaande code is weggelaten
  colorValueField.setAttribute('value', `hsl(${hue},${sat}%,${light}%)`);
  colorBox.style.backgroundColor = colorValueField.value;
}); // dit sluit het luisteren naar DOMContentLoaded af

Wat gebeurt hier!?

  • Het invoerveld wordt benaderd via de variabele colorValueField.
  • Aan het element voegen we met de methode setAttribute(naam, waarde) het attribuut met de naam value toe. De waarde is een combinatie van tekst en variabelen. De tekst wordt letterlijk weergegeven en van de variabelen wordt de inhoud getoond. (Dit werkt doordat de hele waarde tussen backticks (het achteroverhellende aanhalingsteken op de toets ~) staat en de variabelen tussen accolades met een dollarteken ervoor.) Dat geeft als resultaat hsl(180, 100%, 50%). Dit resultaat wordt letterlijk ingevuld bij de CSS-eigenschap background-color van het kleurvak. Deze eigenschap wordt als inline opmaakregel aan het element toegevoegd. In de Inspector (F12) zie je dus staan:
<div class="color-box" id="color-box" style="background-color: rgb(0, 255, 255);"
</div>

Verwarrend kan zijn dat hier geen HSL te bekennen is. Dat komt doordat de browser HSL direct omzet naar RGB. Maar waar het om gaat, is dat met JavaScript de achtergrondkleur van het kleurvak (colorBox) is ingesteld op de CSS-kleurwaarde die is opgeslagen in het attribuut value van het element in de variabele colorValueField.

Tint, verzadiging en helderheid instellen

We kunnen nu ook de regelaars voor tint, verzadiging en helderheid instellen op de beginwaarden uit de variabelen hue, sat en light.

  // voorgaande code is weggelaten
  colorSlider.setAttribute('value', hue);
  saturatSlider.setAttribute('value', sat);
  saturatSlider.style.backgroundImage = `linear-gradient(to right, hsl(${hue},0%,${light}%), hsl(${hue},100%,${light}%))`;
  lightSlider.setAttribute('value', light);
  lightSlider.style.backgroundImage = 'linear-gradient(to right, black, white)';
}); // dit sluit het luisteren naar DOMContentLoaded af

De beginwaarde voor de tint is 180. De beginwaarde voor verzadiging is 100%. De achtergrondkleur van die regelaar is gekoppeld aan de tint (de waarde van hue) en aan de helderheid (light). De actuele kleur wordt getoond in een kleurverloop van 0% naar 100% verzadiging. Net als bij de kleurregelaar is de achtergrondkleur vooral een hulpmiddel voor de gebruiker. De echte waarde zit in het attribuut value van de regelaar.

De regelaar voor de helderheid heeft als achtergrond gewoon een verloop van zwart (0% helderheid) naar wit (100% helderheid). De beginwaarde is 50%.

Het verschuiven van de kleurregelaar verwerken

Het schuiven aan een schuifregelaar levert een gebeurtenis op: input. We kunnen luisteren of die gebeurtenis optreedt en daarop reageren. De volgende code handelt het verschuiven van de kleurregelaar af:

  // voorgaande code is weggelaten
  colorSlider.addEventListener('input', () => {
      hue = colorSlider.value;
      saturatSlider.style.backgroundImage = `linear-gradient(to right, hsl(${hue},0%,${light}%), hsl(${hue},100%,${light}%))`;
    colorValueField.setAttribute('value', `hsl(${hue},${sat}%,${light}%)`);
    colorBox.style.backgroundColor = colorValueField.value;
  });
}); // dit sluit het luisteren naar DOMContentLoaded af

Wat gebeurt hier?

Er wordt geluisterd of op het element colorSlider de gebeurtenis input optreedt. Als dat zo is, wordt een functie uitgevoerd. De functie zorgt ervoor dat:

  • de variabele hue (tint) de waarde van de nieuwe stand van de regelaar (0 tot 360) krijgt;
  • het kleurverloop in de achtergrond van de regelaar voor de verzadiging opnieuw wordt opgebouwd met de nieuwe waarde van hue;
  • het attribuut value van het invoerveld met de waarde van hue wordt bijgewerkt naar de nieuwe kleur. Het veld toont dus de CSS voor de huidige HSL-kleur;
  • de achtergrondkleur van het kleurvak de waarde van het invoerveld krijgt; dat is de CSS voor de huidige HSL-kleur.

Het verschuiven van de verzadiginsgregelaar verwerken

Ook als regelaar voor de verzadiging wordt verschoven, wordt een functie uitgevoerd.

  // voorgaande code is weggelaten
  saturatSlider.addEventListener('input', () => {
    sat = saturatSlider.value;
    saturatSlider.style.backgroundImage = `linear-gradient(to right, hsl(${hue},0%,${light}%), hsl(${hue},100%,${light}%))`;
    colorValueField.setAttribute('value', `hsl(${hue},${sat}%,${light}%)`);
    colorBox.style.backgroundColor = colorValueField.value;
  });
}); // dit sluit het luisteren naar DOMContentLoaded af

Wat gebeurt hier?

  • De variabele sat (verzadiging) krijgt de waarde van de nieuwe stand van de regelaar (0 tot 100).
  • Het kleurverloop in de achtergrond van de regelaar voor de verzadiging wordt opnieuw opgebouwd met de nieuwe waarde van sat.
  • Het attribuut value van het invoerveld wordt met de waarde van sat bijgewerkt naar de nieuwe kleur. Het veld toont dus de CSS voor de huidige HSL-kleur.
  • De achtergrondkleur van het kleurvak krijgt de waarde van het invoerveld: de CSS voor de huidige HSL-kleur.

Dit klinkt bekend? Het zijn inderdaad dezelfde stappen als bij de kleurregelaar.

Het verschuiven van de helderheidsregelaar verwerken

Als de helderheid wordt aangepast, verandert de waarde van de variabele light (0 tot 100). Met die nieuwe waarde wordt de achtergrondkleur van de verzadigingsregelaar en van het kleurvak aangepast. Het invoerveld toont de nieuwe CSS-waarde voor de HSL-kleur.

  // voorgaande code is weggelaten
  lightSlider.addEventListener('input', () => {
    light = lightSlider.value;
    saturatSlider.style.backgroundImage = `linear-gradient(to right, hsl(${hue},0%,${light}%), hsl(${hue},100%,${light}%))`;
    colorValueField.setAttribute('value', `hsl(${hue},${sat}%,${light}%)`);
    colorBox.style.backgroundColor = colorValueField.value;
  });
}); // dit sluit het luisteren naar DOMContentLoaded af

De knoppen aan het werk zetten

We hebben twee knoppen, Kopieer en Herstel, maar die doen nog niet wat er van ze wordt verwacht. Ook bij de knoppen gaan we luisteren naar een gebeurtenis: click. Wordt er geklikt, dan wordt een functie uitgevoerd.

Eerst maken we boven in het script variabelen met verwijzingen naar de twee elementen <button>. Voeg ze toe onder de andere variabelen:

  // voorgaande code is weggelaten
  const btnCopyColorValue = document.getElementById('btn-copy-color-value');
  const btnReset = document.getElementById('btn-reset');

Dan laten we luisteren naar de klikgebeurtenissen. De code komt onder de andere luisteraars.

  // voorgaande code is weggelaten
  btnCopyColorValue.addEventListener('click', (e) => {
    e.preventDefault();
    colorValueField.select();
    document.execCommand('copy');
  });
  btnReset.addEventListener('click', () => {
    hue = 180;
    sat = 100;
    light = 50;
    colorSlider.setAttribute('value', hue);
    saturatSlider.setAttribute('value', sat);
    lightSlider.setAttribute('value', light);
    colorValueField.setAttribute('value', `hsl(${hue},${sat}%,${light}%)`);
    colorBox.style.backgroundColor = colorValueField.value;
    saturatSlider.style.backgroundImage = `linear-gradient(to right, hsl(${hue},0%,${light}%), hsl(${hue},100%,${light}%))`;
  });
});// dit sluit het luisteren naar DOMContentLoaded af

Wat gebeurt hier?

Eerst de kopieerknop. Een <button> heeft verzenden als standaardactie (submit). Maar wij willen kopiëren, niet verzenden. Met e.preventDefault() voorkomen we dat de standaardactie wordt uitgevoerd. De opdracht colorValueField.select(); selecteert de inhoud van het invoervak. De opdracht document.execCommand('copy'); kopieert die inhoud naar het klembord.

Opmerking: In de HTML kan een <button> ook het attribuut type="button" krijgen. Dan heeft de knop geen standaardactie en is de opdracht e.preventDefault() niet nodig.

Dan de herstelknop.

De variabelen voor tint, verzadiging en helderheid worden op de beginwaarden gezet. Met die variabelen wordt van elke regelaar het attribuut value ingesteld. Vervolgens worden de variabelen gebruikt om het invoerveld, het kleurvak en de verzadigingsregelaar opnieuw in te stellen.

Opmerking: Het ‘midden’ van de schuifregelaar is het nulpunt. Bij een reset zonder extra instellingen komt een schuifjes dus vanzelf in het midden. Het is daarom niet per se nodig om de tint en de helderheid in de code in te stellen.

Opmerking: De JavaScript-code kan korter en efficiënter, maar daar wordt de code niet duidelijker van. Vandaar dit uitgebreide voorbeeld.

De volgende aflevering

De kleurkiezer doet nu alles wat die moet doen. Het enige wat nog ontbreekt is de overlay met de informatie over het gebruik. Die maken we in deel 4.

Dit was deel 3 van de serie. Lees ook deel 1 van de serie, deel 2 en deel 4 .


Goed om te zien dat het artikel je tot het einde toe heeft kunnen interesseren. De meeste artikelen op dit blog worden geschreven door de auteurs van
uitgeverij Van Duuren Media.
Ben je geïnteresseerd in verdere verdieping of meer praktische toepassingen? Klik op onderstaande banner voor het meest actuele overzicht.

Geef een reactie

Deze site gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.