Pure CSS3 en HTML slider
Op 10 nov. 2011 zei Jeffrey Way op Google+: “So here’s what I came up with for my simple CSS3-only slider. Not practical yet - but as a proof of concept… http://jsfiddle.net/8TYm3/2/”
Dit heeft mij aan het denken gezet om ook een CSS3 slider te maken, die een mooie HTML heeft en makkelijk te bedienen is. In dit bericht wil ik graag laten zien wat het resultaat is geworden en hoe je tot zoiets komt.
CSS3 Animations
Allereerst kun je zoiets natuurlijk niet met CSS2 af. Je zult CSS3 technieken moeten gebruiken, animations om exact te zijn. Dit betekend dat het momenteel alleen zal werken in Chrome of FireFox.
Helaas, maar dit is natuurlijk ook alleen als test en oefening, het is momenteel nog niet serieus te gebruiken.
Het concept
Wat vaak het beste werkt als je met iets nieuws begint is je computer afsluiten of je lap top dichtklappen en een kladblok, potlood en gum te pakken. Vervolgens ga je al je ideeën opschreven en kijk je of ze wel mogelijk zijn.
Deze techniek heb ik deze keer ook gebruikt, alleen vandaag heb ik nog wat extra’s erbij gepakt: Wat lijm en een schaar. Vervolgens heb ik hier wat zitten knippen en plakken en ben zo tot het basis concept gekomen.
Probleem 1: Hoe beweeg je de afbeeldingen?
Dit probleem lijkt, als je CSS3 animations doorhebt, in het begin makkelijk. Maar dat is schijn. Want je kan moeilijk per afbeelding een animatie frame maken. Laten we eerst eens kijken hoe we dit willen gebruiken als HTML code. Wat zou de beste manier zijn om iets semantisch correct en makkelijk handelbaar te krijgen?
Het eerste idee:
1
2
3
4
5
<div id="slider">
<img src="img/slide1.png" alt="some text">
<img src="img/slide2.png" alt="some other text">
<!-- ... -->
</div>
Ziet er niet verkeerd uit, zo werken de meeste jQuery sliders ook. Alleen hoe
gaan we deze nou bewegen? We kunnen moeilijk de hele slider div
gaan bewegen
en een ander element die alle slides omringt hebben we niet… Laat ik hier
stoppen en bedenk eerst zelf een oplossen voordat je verder scrolled.
Oplossing
Als we nou eens de slides zien als een lijst van afbeeldingen (slides)? Dan
kunnen we de ul
als overkoepelende element gebruiken en de li’s daarmee
animeren. Ook qua semantisch opzicht is het te verdedigen en zeker niet fout.
De code wordt dus zoiets:
1
2
3
4
5
6
<div id="slider">
<ul>
<li><img src="img/slide1.png" alt="some text"></li>
<li><img src="img/slide2.png" alt="some other text"></li>
</ul>
</div>
Probleem 2: Hoe verbergen we de andere afbeeldingen?
Je wilt per keer maar 1 afbeelding laten zien, dus de andere moet je zien te verbergen. Nu heb ik ooit een jQuery scriptje gemaakt waarbij je een soort spotlight effect creëerde. Als je met de muis over de afbeelding bewoog werd alles donker behalve een cirkel met een diameter van ong. 10px rond je muis. Daar moest ik hierbij als eerst aan denken. Ik gebruikte hiervoor destijds een gigantisch grote (qua formaat) donkere afbeelding met in het midden een doorzicht cirkeltje. Als we dit nu ook toepassen in dit voorbeeld? Helaas, is dit niet praktisch (en dat is nou juist niet wat we willen). Want:
- Je moet het formaat van het doorzichtige gat telkens aanpassen als je het slider-formaat veranderd
- Je moet het niet doorzichtige gedeelte telkens aanpassen aan de kleur die je als achtergrond op de pagina wilt hebben.
Wat kan dan wel de oplossing zijn? Denk eerst zelf wat na en ga wat knippen en plakken, zo kun je hier nog wat van leren, of bekijk meteen het filmpje waarin ik (helaas zonder geluid) laat zien hoe je het kan oplossen:
Even kort beschreven de oplossing is dat we #slider
overflow: hidden;
meegeven en de breedte en hoogte van de slides. Hierdoor zie je telkens maar
1 afbeelding.
Uitvoering
Tot zover het verkennen van de mogelijkheden en het uitwerken van het idee. Nu moeten we de CSS gaan schrijven. Laten we weer bij het begin beginnen:
Afbeeldingen in ul
naast elkaar krijgen
Eerst moeten we de slides naast elkaar krijgen. Dit doen we heel simpel door
float: left;
mee te geven aan li
. NOTE: Gebruik geen display: inline-block;
hiervoor, dit is onjuist. Waarom dat zo is schrijf ik misschien nog wel een
bericht over.
#slider
opmaken
Vervolgens gaan we de #slider
opmaken. De oplossing voor het 2e
probleem was dat we deze overflow: hidden;
en de hoogte en
breedte van de afbeelding meegeven. Nou, laten we dat dan maar gaan doen:
1
2
3
4
5
#slider{
width:610px;
height:244px;
overflow:hidden;
}
De animatie
En dan komt nu het moeilijkste onderdeel: De CSS3 animatie. Omdat dit voor veel mensen die dit lezen nieuw zal zijn zal ik dit stap voor stap doen, zodat je het kunt begrijpen.
Elke animatie heeft een animatie frame (keyframe genoemd). Dit is niet een HTML frame, maar in CSS. Met dit keyframe geef je aan wat de animatie precies is. Dus de keyframe bevat een gedetailleerde overzicht van de animatie. Als we bijv. een animatie willen maken die de achtergrondkleur van rood naar blauw veranderd doen we:
1
2
3
4
5
6
7
8
@keyframes changeBgColor {
from {
background:red;
}
to {
background:green;
}
}
Merk wel op dat het geen je hier ziet alleen de animatie zelf is. We moeten
deze animatie nog toevoegen aan een element. Dit doen we met animation
en
omdat het nog in de test fase is moeten hier nog de prefixen (bijv. -webkit-
en -moz-
) toegevoegd worden. Als waardes verwacht animation
als eerste de
naam van het keyframe, deze is changeBgColor in het voorbeeld hierboven. Als
2e waarde wordt de duration verwacht, of te wel de snelheid van de animatie.
Dit kan van alles zijn. Vervolgens kun je er andere opties bijzetten. Welke
opties en meer informatie kun je vinden op de
CSS Animations Module level 3
specificaties.
Terug naar onze code
In ons geval willen we een animatie maken die de ul steeds de breedte van 1 slide opschuift en als hij bij het eind is weer terug gaat. Voordat we een keyframe kunnen maken moeten we weten hoeveel slides we hebben en hoe groot deze slides zijn en als extra hoelang de slide duurt (het glijden van de afbeeldingen). In mijn voorbeeld heb ik 4 slides van ong. 620px breed.
I.p.v. een keyframe te gebruiken met from
en to
kun je ze ook met
procenten gebruiken en zelfs combineren. In dit voorbeeld gebruiken we het
laatste. We gaan de ul doormiddel van margin-left
bewegen, zodat de
afbeeldingen sliden. Om ervoor te zorgen dat alle slides even lang duren doen
we 100% / aantal slides - 0.5
om tot het antwoord te komen. In dit
geval wordt dat 100% / (4 -0.5)
en dan krijg je het geweldige antwoord van
28.57% met nog heel wat decimalen erachter. Vervolgens kunnen we dit gebruiken
voor de keyframes. We beginnen bij 0%, wat gelijk is aan from, en hierbij is
de margin-left
ook 0. Vervolgens gaan we naar de eerste stap, 28%, waarbij
de margin-left
de negatieve waarde van de breedte van onze slide heeft, in
dit geval dus -620px
. De tweede stap is op 56% met de waarde van 2 slides
dus -1240px
. En zo ga je door met 74% en 100% (to), waarbij deze beide een
waarde van -1860px
hebben. De totale code wordt dus zoiets:
1
2
3
4
5
6
7
@keyframes slider
{
from { margin-left:0; }
28% { margin-left:-620px; }
56% { margin-left:-1240px; }
74%, to { margin-left:-1860px; }
}
Nu moeten we alleen de ul nog deze keyframe meegeven, een tijd en wat extra
opties, en we hebben onze slider af. De aanroep in #slider ul
wordt:
1
animation: slider 10s linear infinite alternate;
Even een uitleg:
- slider, dit is de keyframe die we gebruiken
- 10s, een slideshow van de eerste tot de laatste slide duurt 10 seconden (dit kun je aanpassen)
- linear, er is niks van vertraging of effect in de slide
- infinite, herhaal de animatie oneindig
- alternate, voer de keyframe de eerste keer van from naar to uit en de 2e keer van to naar from, zodat het mooi blijft doorlopen.
Helaas, sliders zijn niet makkelijk
Het leek zo simpel en ik wou zo graag nu al het eind resultaat laten zien, maar dit werkt nog niet. Dit komt door weer 2 problemen:
Prefixen
Zowel de animatie aanroepen en de prefixen in de @keyframes
moeten worden
toegevoegd. Aangezien dit alleen in Chrome en FireFox werkt hoeven we maar 2
prefixen toe te voegen: @-webkit-keyframes
en @-moz-keyframes
en
-webkit-animation
en -moz-animation
. Hou de officiële properties, dus
zonder prefixen, er altijd ook gewoon in.
Ruimte voor de slide
Het zal nu in 1 keer van links tot rechts doorlopen. We hebben namelijk niet
aangegeven wat er tussen 0% en 28% zit en dus zal hij telkens tussen deze 2
waardes een stapje opschuiven. We moeten dus aangeven dat hij voor 28% nog
steeds op 0px
zet. Dus doen we dit:
1
[css]
@keyframes slider
{
from,27% { margin-left:0; }
28%, 55% { margin-left:-620px; }
56%, 73% { margin-left:-1240px; }
74%, to { margin-left:-1860px; }
}
Hierbij kan CSS nog niks animaten en begin het pas met sliden bij 27% en dan bij 28% stopt het weer tot 56% en zo gaat het door.
Weer een probleem, de slides duren nu veel te kort en we moeten dus de CSS slide tijd verlengen. Ik stel voor dat we een slide tijd hebben van 6%. Dit betekend dat er 3% vanaf gaat en 3% bij komt. We krijgen dus uiteindelijk zoiets:
1
[css]
@keyframes slider
{
from, 24% { margin-left:0; }
31%, 53% { margin-left:-620px; }
59%, 71% { margin-left:-1240px; }
77%, to { margin-left:-1860px; }
}
Feestje?
Ja, eindelijk is het zo ver! Onze slider werkt en is hier te aanschouwen met de juiste prefixen en met nog een slide optie met alleen CSS3 en HTML.
Ik hoop dat je van deze tutorial hebt geleerd hoe je iets van een idee tot een CSS en HTML code kunt omtoveren en dat je warm bent gemaakt dingen uit te proberen met CSS3 en dan vooral het geweldige animations.
Mocht je net zo’n animatie hebben gemaakt als Anthony Calzadilla</a> of vind je dat je iets geweldigs hebt gemaakt? Deel het met ons in de reacties!