CSS άσκηση: το εφέ της αρχικής σελίδας
Έχω λάβει κάποια email από φίλους τον τελευταίο καιρό σχετικά με το πώς έχει δημιουργηθεί η πάνω ενότητα της αρχικής σελίδας: δηλαδή το κείμενο που κάνει καμπυλωτό wrap γύρω από τον μεγάλο κύκλο, ενώ μέσα σε αυτόν κινούνται οι δύο μικρότεροι κύκλοι. Οπότε, σκέφτηκα να το πω με ένα post.
Μιλάμε για δύο διαφορετικά πράγματα:
- Πώς το κείμενο καμπυλώνεται γύρω από τον κύκλο
- Πώς γίνεται η κίνηση των κύκλων
Κατ’αρχήν και τα δύο γίνονται μόνο με CSS κώδικα - αν ήταν να χρησιμοποιήσω JavaScript ή κάτι άλλο, δεν άξιζε τον κόπο.
Πάμε να τα δούμε ένα-ένα.
Η HTML
Πριν απ’ ότιδήποτε άλλο, μια ματιά στην HTML.
<div class="big-intro"> <img class="shape" src="img/home/purple.png"> <img class="blue" src="img/home/blue.png"> <img class="yellow" src="img/home/yellow.png"> <h1>Title</h1> <p>Text here</p> </div>
Απλά πράγματα: μέσα σε ένα div
έχουμε τρεις εικόνες, έναν τίτλο και κείμενο σε μια παράγραφο.
Η βάση του όλου layout είναι ο μωβ κύκλος, δηλ. το purple.png
και θα φανεί σε λίγο γιατί. Χωρίς αυτόν όλα είναι στον αέρα.
Πώς ένα κείμενο μπορεί να κάνει wrap γύρω από μία καμπύλη
Αυτό που γνωρίζουμε καλά στον κόσμο των CSS είναι το wrapping κειμένου γύρω από ένα τετράγωνο, γύρω από ένα box. Αλλά η ίδια αρχή επεκτείνεται μέσω του CSS Shapes Module.
Η λογική είναι να ορίσεις σωστά ένα νοητό σχήμα (CSS Shape), το οποίο μπορεί να είναι κύκλος, έλλειψη, πολύγωνο ή ακόμα και εικόνα και μετά να επιβάλλεις στο κείμενο να το “αγκαλιάσει”. Στη συγκεκριμένη περίπτωση ο κύκλος μας είναι το purple.png
και ο κώδικας για το shape είναι πραγματικά απλός:
.shape{ -webkit-shape-outside: circle(210px at 210px 200px); shape-outside: circle(210px at 210px 200px); float: right; margin: 0 0 0 20px; position: relative; z-index: 1; }
Οι δύο πρώτες γραμμές κώδικα λένε ουσιαστικά το ίδιο πράγμα μόνο που απευθύνονται σε διαφορετικούς browsers: όριζουν έναν κύκλο ακτίνας 210px
σε απόσταση 210px
και 200px
από το div
που το περιβάλλει.
Η γραμμή float: right
είναι απαραίτητη γιατί αλλιώς δε λειτουργούν τα CSS Shapes. Χρειάζονται floating οπωσδήποτε.
Οι υπόλοιπες γραμμές είναι συμπληρωματικές και αφορούν την απόσταση του σχήματος από το κείμενο (margin
) και το εφέ με τους τρεις κύκλους (position
, z-index
).
Η δυσκολία σε όλο αυτό είναι ουσιαστικά είναι να βρεις μια σωστή ακτίνα για τον κυκλο και να τον τοποθετήσεις σε μια καλή θέση σε σχέση με το κείμενο σου. Είναι δηλαδή θέμα διάταξης κι όχι δυσκολίας στον κώδικα.
Μια σημείωση για το shape-outside
μόνο: ακόμα δεν υποστηρίζεται σωστά απ’όλους τους browers. Γιατί Firefox; Γιατί Edge; Ωστόσο, σύντομα περιμένουμε να επανορθώσουν και οι δύο.
Το εφέ με τους τρεις κύκλους
Εδώ είναι λίγο πιο πολύπλοκα τα πράγματα. Για να δούμε τι προσπαθούμε να κάνουμε:
- Θέλουμε τρεις κύκλους, εκ των οποίων οι δύο πιο μικροί θα βρίσκονται εντός του μεγάλου.
- Επίσης, θέλουμε οι δύο μικροί κύκλοι να κινούνται συνεχώς εντός μεγάλου, αλλά ποτέ να μην αγγίζει ο ένας τον άλλο.
- Τέλος, θέλουμε όταν κάνουμε rollover στο
div
που περιλαμβάνει όλη την περιοχή οι δύο μικροί κύκλοι να αλλάζουν θέση και να σχηματίζουν το logo του site.
Τρεις κύκλοι, οι δύο μικρότεροι εντός του μεγάλου κύκλου
Εύκολο.
Το purple.png
έχει position: relative
όπως είδαμε πιο πάνω ενώ οι άλλοί δύο κύκλοι position: absolute
και μεγαλύτερο z-index
για να φαίνονται πάντα από πάνω του.
Οι δύο μικρότεροι κύκλοι πρέπει να κινούνται συνέχεια χωρίς ο ένας να αγγίζει τον άλλο
Αυτό είναι και το πιο δύσκολο κομμάτι του κώδικα. Αν φτάσατε μέχρι εδώ, αξίζει να μην το παρατήσετε τώρα.
Ας δούμε τι γίνεται με τον μπλε κύκλο.
.blue{ position: absolute; top: 220px; right: 132px; z-index: 2; transition: all .8s cubic-bezier(0.455, 0.030, 0.515, 0.955); -webkit-transition: all .8s cubic-bezier(0.455, 0.030, 0.515, 0.955); animation: bluerotation 7s infinite linear; }
Ζητάω από τον κύκλο να σταθεί σε μια συγκεκριμένη θέση πάνω στον μωβ (position, top, right, z-index
) και ας ξεχάσουμε για λίγο ό,τι ακολουθεί. Θα επανέλθουμε.
Αυτό που πρέπει τώρα να κάνουμε είναι να ορίσουμε ένα animation
με τον CSS τρόπο. Πάλι για τον μπλε κύκλο έχουμε:
@keyframes bluerotation{ from { transform: rotate(0deg) translate(-10px); -moz-transform: rotate(0deg) translate(-10px); } to { transform: rotate(360deg) translate(-10px); -moz-transform: rotate(360deg) translate(-10px); } }
Αρχικά, ονομάζω το εφέ bluerotation
και του ζητάω δύο πράγματα: να περιστρέφεται κυκλικά ενώ θα μετακινείται 10px
προς τ’αριστερά. Τα απαραίτητα prefixes μας αναγκάζουν να γράψουμε ουσιαστικά δύο φορές τον ίδιο κώδικα ώστε να καλύπτεται και ο Firefox.
Πώς γίνεται αυτό το animation; Όπως το έχω ορίσει πιο πάνω:
animation: bluerotation 7s infinite linear;
Να κρατάει δηλαδή 7 δευτερόπλεπτα, να γίνεται επ’ αόριστον και να γίνεται με σταθερή, χωρίς αυξομειώσεις ταχύτητα.
Ό,τι έχει γίνει για τον μπλε κύκλο ακριβώς το ίδιο έχει γίνει και για τον κίτρινο, με μόνες διαφορές τις τιμές στις διάφορες ιδιότητες. Για παράδειγμα ο χρόνος του anmiation για τον κίτρινο είναι 10 δευτερόλπετα γιατί ήθελα να πηγαίνει πιο αργά και να μην κουράζει.
Πώς γίνεται και οι δύο κύκλοι δε συναντιούνται ποτέ; Με την αλάνθαστη μέθοδο της δοκιμής και του λάθους. Άλλαξα αυτόν τον κώδικα πάνω από 40 φορές μέχρι να βεβαιωθώ ότι δε θα τράκαρε ποτέ ο ένας τον άλλο. Ε τώρα αν κάτι μου έχει φύγει κι μετά από 55 περιστροφές φτάσουν να τρακάρουν, χαλάλι τους.
Πώς με rollover σχηματίζεται το logo
Χρωστάω δύο γραμμές κώδικα από την πιο πάνω ενότητα:
transition: all .8s cubic-bezier(0.455, 0.030, 0.515, 0.955); -webkit-transition: all .8s cubic-bezier(0.455, 0.030, 0.515, 0.955);
Στην ουσία είναι μια γραμμή, δύο βγαίνουν λόγω του prefix. Είναι η κίνηση που κάνει ο μπλε κύκλος όταν το ποντίκι περνάει πάνω από ολόκληρη την ενότητα με το κείμενο και τους κύκλους. Αυτό που του λέω είναι να κινηθεί σε χρόνο 0.8s
με κίνηση cubic-bezier
. Γιατί cubic-bezier; Γιατί δεν ήθελα ούτε κατά τη διάρκεια του rollover του ποντικιού να συναντιούνται ο μπλε και ο κίτρινος κύκλος (συνέβαινε κάποιες φορές, άρα ήθελα ασύμμετρη κίνηση) και γιατί έτσι μου φαινόταν πιο ενδιαφέρον.
Τι συμβαίνει λοιπόν όταν το ποντίκι κάνει hover
;
.blue:hover{ top: 0; right: 36px; animation: none; transition: all .5s cubic-bezier(0.455, 0.030, 0.515, 0.955); -webkit-transition: all .5s cubic-bezier(0.455, 0.030, 0.515, 0.955); }
Ο μπλε κύκλος αλλάζει θέση (top, right
), καταργεί το animation
της προηγούμενης κατάστασης πάνω στον μωβ κύκλο και εκεί κανονικά θα τελειώναμε. Όμως όταν φεύγει το ποντίκι από την περιοχή θέλουμε οι δύο μικροί κύκλοι να ξαναπέφτουν πάνω στον μωβ και να ξαναρχίζει η κίνηση. Γι’ αυτό υπάρχουν και οι δύο τελευταίες γραμμές του hover
.
Επίλογος
Όλο αυτό φαίνεται μεγάλο και δύσκολο και μάλλον είναι. Αλλά αν αρχίσεις να παίζεις και να σου γίνεται εμμονή, ο κώδικας βγαίνει χωρίς μεγάλες δυσκολίες.
Ένα θέμα μένει μόνο αναπάντητο: τι γίνεται με το Responsive Web Design; Όχι πολλά είναι η απάντηση.
Τα CSS Shapes είναι μια χαρά και σε μεγάλο βαθμό έχουν το browser support που χρειαζόμαστε.
Το animation ακριβώς επειδή γίνεται με rollover και η έννοια δεν υπάρχει στα touch devices, χάνουμε όλο το εφέ. Έχω κάνει μια προσπάθεια να αντικαταστήσω το hover με tap μέσω JavaScript, κι ενώ γενικά ο κώδικας ανταποκρίνεται σωστά, στο συγκεκριμένο δε φαίνεται να παίζει όσο κι αν το πιέσω.
Το animation με CSS είναι πολύ διαδεδομένο και υπάρχουν πολλές πηγές για περισσότερα. Έτσι, παραθέτω μερικά ωραία links που έχουν να κάνουν με τα CSS Shapes.
- shape-outside στο CSS Tricks. Καλό σημείο για ν’αρχίσει κάποιος.
- Getting Started with CSS Shapes. Ξεκινάει ήρεμα και αγριεύει στην πορεία. Αλλά είναι πολύ κατατοπιστικό.
- Creating Non-Rectangular Layouts With CSS Shapes Το πιο πλήρες. Μεγάλο αλλά πάρα πάρα πολύ καλό.
Δημοσιευμένο και στο Medium.